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

Компилятор вежливо сообщает, что plus() не является методом интерфейса Expression. Добавим этот метод в интерфейс:

Expression

Expression plus(Expression addend);

Теперь мы должны добавить этот метод в классы Money и Sum. Money? Да, этот метод должен быть открытым (public) в классе Money:

Money

public Expression plus(Expression addend) {

return new Sum(this, addend);

}

Что касается класса Sum, просто добавим заглушку и отметим необходимость реализации этого метода в списке задач:

Sum

public Expression plus(Expression addend) {

return null;

}

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

$5 + $5 = $10

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

Bank.reduce(Money)

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

Reduce(Bank,String)

Sum.plus

Expression.times

Теперь программа компилируется и все тесты выполняются успешно.

Мы готовы завершить обобщение класса Money до Expression, но прежде, как всегда, подведем краткий итог. В этой главе мы

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

• выполнили обобщение (использовали более абстрактное объявление);

• воспользовались подсказками компилятора, чтобы внести изменения (Expression fiveBucks), которые привели к необходимости дополнительных изменений (добавление метода plus() в интерфейс Expression и т. п.).

<p>16. Абстракция, наконец-то!</p>

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

$5 + $5 = $10

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

Bank.reduce(Money)

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

Reduce(Bank,String)

Sum.plus

Expression.times

Чтобы завершить добавление метода Expression.plus, мы должны реализовать метод Sum.plus(). Затем нам останется добавить метод Expression.times(), и мы сможем считать пример завершенным. Вот тест для метода Sum.plus():

public void testSumPlusMoney() {

Expression fiveBucks = Money.dollar(5);

Expression tenFrancs = Money.franc(10);

Bank bank = new Bank();

bank.addRate("CHF", "USD", 2);

Expression sum = new Sum(fiveBucks, tenFrancs). plus(fiveBucks);

Money result = bank.reduce(sum, "USD");

assertEquals(Money.dollar(15), result);

}

Мы могли бы создать объект Sum путем сложения fiveBucks и tenFrancs, однако приведенный код, который явно создает объект Sum, выглядит более понятным. Ведь мы пишем эти тесты не только ради удовольствия от программирования, но также для того, чтобы будущие поколения программистов могли оценить нашу гениальность. Однако они не смогут сделать этого, если код будет непонятным. Поэтому, разрабатывая любой код, думайте о тех, кто будет его читать.

В данном случае код теста длиннее, чем сам тестируемый код. Код точно такой же, как код в классе Money (кажется, я уже предвижу необходимость создания абстрактного класса):

Sum

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

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

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

$5 + $5 = $10

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

Bank.reduce(Money)

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

Reduce(Bank,String)

Sum.plus

Expression.times

Если мы получили работающий метод Sum.times(), значит, объявление Expression.times() не составит для нас труда. Вот соответствующий тест:

public void testSumTimes() {

Expression fiveBucks = Money.dollar(5);

Expression tenFrancs = Money.franc(10);

Bank bank = new Bank();

bank.addRate("CHF", "USD", 2);

Expression sum = new Sum(fiveBucks, tenFrancs). times(2);

Money result = bank.reduce(sum, "USD");

assertEquals(Money.dollar(20), result);

}

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

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

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

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

Чед Фаулер

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

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