Экстремальное программирование. Разработка через тестирование | страница 110



• в Java можно объявить подметод абстрактным;

• в Smalltalk создайте реализацию метода, которая генерирует ошибку SubclassResponsibility.

Я не рекомендую изначально проектировать код так, чтобы в нем использовался шаблонный метод. Лучше всего формировать шаблонные методы исходя из накопленного опыта. Каждый раз, когда я говорю себе: «Ага, вот последовательность, а вот – детали реализации», – позднее я всегда обнаруживаю, что мне приходится переделывать созданный мною шаблонный метод, заново перетасовывая код между общим и частным.

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

Встраиваемый объект (Pluggable Object)

Как можно выразить несколько разных вариантов поведения кода? Проще всего использовать явный условный оператор:


if(circle) then {

… код, относящийся к circle.

} else {

… код, не относящийся к circle

}


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

Вторая по важности задача TDD – устранение дублирования, поэтому вы должны подавить угрозу распространения явных условных операторов в зародыше. Если вы видите, что одно и то же условие проверяется в двух разных местах вашего кода, значит, настало время выполнить базовое объектно-ориентированное преобразование: «Встраиваемый объект» (PluggableObject).

Иногда обнаружить необходимость применения этого шаблона не так просто. Один из самых любимых мною примеров использования встраиваемого объекта был придуман мною и Эрихом Гаммой. Представьте, что мы занимаемся разработкой графического редактора. Если вы когда-нибудь занимались чем-либо подобным, должно быть, вы знаете, что операция выделения объектов обладает несколько усложненной логикой. Если указатель мыши находится над графической фигурой и пользователь нажимает кнопку мыши, значит, последующие перемещения мыши приводят к перемещению фигуры, а при отпускании кнопки мыши выбранная фигура остается на новом месте. Если указатель мыши не находится над какой-либо фигурой, значит, нажав кнопку, пользователь выделяет несколько фигур, последующие перемещения мыши приводят к изменению размера прямоугольника выделения, а при отпускании кнопки мыши фигуры внутри прямоугольника выделения становятся выделенными. Изначальный код выглядит примерно так: