воскресенье, 27 мая 2012 г.

Игра́ «Жизнь» (англ. Conway's Game of Life). Часть 2.


Исходники N2 тут


Основные изменения:
- добавил тесты на генерацию поля и убрал random (вот оно, кодирование "на будущее"! и зачем написал? да шут его знает...)

- добавил тесты на основную логику Tick
- добавил тесты на необходимость клонирования в методе Tick (тоже конечно было написано "на будущее" и лучше добавлять код "по факту проблем", но здесь я точно знал что они будут и только фиксировал необходимость для этой ситуации дополнительного кода, кстати неправильного в первоначальном варианте, и тестов, которые неправильность выявили)
- добавил публичные константы для значений "воскресить" и границ продолжения жизни - это упрощает документацию (такие значения можно тупо нагенерить в доку немного облегчив жизнь писателю), работу с классом без документации (VS показывает значения таких свойств из подключенной библиотеки) и сокращает дублирование (значения начали расползаться по тестам)

Выявился один из моих принципов в продаваемом коде: я НЕ продаю то, для чего я НЕ гарантирую надежную работу.
В самом простом случае это вырождается в "я не продаю то, на что я не написал тесты". Хотя все еще бывает что под соусом "ну ведь вроде работает?" непротестированные наборы входных параметров заявляются как "go live" и бремя тестирования и проверки ложится на плечи клиентов.

Из получившегося кода имеют право на продажу только три элемента:
1. Surface.Generate
2. Surface.Tick
3. LiveAroundCalculatorTwoDimensions.Calculate

Все это - статические методы, на которые написаны тесты. Они уже готовы для описания в документации (см. тесты и переводи код на человеческий язык) и я гарантирую их высокую надежность в заявленных сценариях использования (т.е. если их будут использовать так как я написал в тестах).

Необходимость раздельного тестирования двух алгоритмов (количество "живых" соседей и "убийство/воскрешение" точки) породило решение: разделение кода на две конструкции. Здесь я их оформил в виде двух классов со статическими методами.
Это разделение позволяет подменять алгоритм расчета живых соседей на свой и использовать мой алгоритм в своих корыстных целях. Этот сценарий тоже зафиксирован: в тестах я именно так и делаю.

Есть конечно еще Generate, "засунутый" в Surface, но с ним пока нет определенности из-за отсутствия его клиентского кода: я точно не знаю где и как он будет использоваться, а из-за близости этого события не хочу строить догадки. Дойду до этого этапа - и любое решение будет обоснованным тогда как сейчас это чистой воды гадание.

Ну, "кубики" вроде есть, грани спрямлены и прямота проверена, выступающие части ампутированы, можно двигаться дальше.

Следующий этап, отрисовка в простейшую сетку с черно-белыми квадратиками, должен показать новые направления для изменения этого кода.