Читаем Экстремальное программирование: Разработка через тестирование полностью

И снова тест получился длиннее тестируемого кода. (Те, кто достаточно много работал с JUnit, должно быть уже догадались, как решить эту проблему. Остальным я рекомендую прочитать раздел «Fixture (Фикстура)» в главе 29, посвященной шаблонам xUnit.)

Sum

Expression times(int multiplier) {

return new Sum(augend.times(multiplier), addend.times(multiplier));

}

В предыдущей главе мы изменили тип переменных augend и addend на Expression, поэтому теперь, чтобы скомпилировать код, нам необходимо добавить в интерфейс Expression метод times():

Expression

Expression times(int multiplier);

При этом нам следует изменить режим видимости методов Money.times() и Sum.times() (они должны стать общедоступными):

Sum

public Expression times(int multiplier) {

return new Sum(augend.times(multiplier), addend.times(multiplier));

}

Money

public Expression times(int multiplier) {

return new Money(amount * multiplier, currency);

}

$5 + 1 °CHF = $10, если курс обмена 2:1

$5 + $5 = $10

Операция $5 + $5 возвращает объект Money

Bank.reduce(Money)

Приведение объекта Money с одновременной конверсией валют

Reduce(Bank,String)

Sum.plus

Expression.times

Все заработало.

Осталось провести эксперимент для случая, когда в результате выполнения операции $5 + $5 получается объект Money. Вот соответствующий тест:

public void testPlusSameCurrencyReturnsMoney() {

Expression sum = Money.dollar(1). plus(Money.dollar(1));

assertTrue(sum instanceof Money);

}

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

Money

public Expression plus(Expression addend) {

return new Sum(this, addend);

}

$5 + 1 °CHF = $10, если курс обмена 2:1

$5 + $5 = $10

Операция $5 + $5 возвращает объект Money

Bank.reduce(Money)

Приведение объекта Money с одновременной конверсией валют

Reduce(Bank,String)

Sum.plus

Expression.times

Не существует очевидного и ясного способа проверить валюту аргумента, если этот аргумент является объектом класса Money (по крайней мере, я не могу найти такого способа, однако вы можете над этим подумать). Эксперимент окончился неудачей, мы удаляем тест (который нам все равно не нравился).

Подводим итог. Мы

• написали тест так, чтобы его смысл легко был понят другими программистами, которые в будущем будут читать разработанный нами код;

• наметили эксперимент, призванный сравнить эффективность TDD по отношению к обычному стилю программирования, используемому вами на текущий момент;

• снова столкнулись с необходимостью изменения множества объявлений в разрабатываемом коде и снова воспользовались услугами компилятора, чтобы исправить все неточности;

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

<p>17. Ретроспектива денежного примера</p>

Давайте еще раз окинем взглядом пример реализации мультивалютных вычислений и попробуем оценить использованный нами подход и полученные результаты. Вот несколько тезисов, которых хотелось бы коснуться:

 Что дальше? Как определить дальнейшее направление разработки?

 Метафора. Впечатляющий эффект, который метафора оказывает на структуру дизайна.

 Использование JUnit. Как часто мы запускали тесты и как мы использовали JUnit?

 Метрики кода. Численные характеристики получившегося кода.

 Процесс. Мы говорим: «красный – зеленый – рефакторинг». Как много усилий прикладывается на каждом из этих этапов?

 Качество тестов. Каким образом характеристики тестов TDD соотносятся с характеристиками обычных методик тестирования?

Что дальше?

Можно ли считать код завершенным? Нет. Методы Sum.plus() и Money.plus() во многом дублируют друг друга. Если мы преобразуем интерфейс Expression в класс (не совсем обычное преобразование – чаще классы становятся интерфейсами), мы получим возможность переместить общий код в единый общий метод.

Перейти на страницу:

Все книги серии Библиотека программиста

Программист-фанатик
Программист-фанатик

В этой книге вы не найдете описания конкретных технологий, алгоритмов и языков программирования — ценность ее не в этом. Она представляет собой сборник практических советов и рекомендаций, касающихся ситуаций, с которыми порой сталкивается любой разработчик: отсутствие мотивации, выбор приоритетов, психология программирования, отношения с руководством и коллегами и многие другие. Подобные знания обычно приходят лишь в результате многолетнего опыта реальной работы. По большому счету перед вами — ярко и увлекательно написанное руководство, которое поможет быстро сделать карьеру в индустрии разработки ПО любому, кто поставил себе такую цель. Конечно, опытные программисты могут найти некоторые идеи автора достаточно очевидными, но и для таких найдутся темы, которые позволят пересмотреть устоявшиеся взгляды и выйти на новый уровень мастерства. Для тех же, кто только в самом начале своего пути как разработчика, чтение данной книги, несомненно, откроет широчайшие перспективы. Издательство выражает благодарность Шувалову А. В. и Курышеву А. И. за помощь в работе над книгой.

Чед Фаулер

Программирование, программы, базы данных / Программирование / Книги по IT

Похожие книги