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

public boolean equals(Object object) {

Money money = (Money) object;

return amount == money.amount

&& currency(). equals(money.currency());

}

Теперь метод Franc.times() может возвращать значение Money, и все тесты будут по-прежнему успешно выполняться:

Franc

Money times(int multiplier) {

return new Money(amount * multiplier, currency);

}

Сработает ли этот трюк для метода Dollar.times()?

Dollar

Money times(int multiplier) {

return new Money (amount * multiplier, currency);

}

Да! Теперь две реализации абсолютно идентичны, и мы можем переместить их в базовый класс.

Money

Money times(int multiplier) {

return new Money(amount * multiplier, currency);

}

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

$5 * 2 = $10

Сделать переменную amount закрытым (private) членом

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

5 CHF * 2 = 1 °CHF

Дублирование Dollar/Franc

Общие операции equals()

Общие операции times()

Сравнение франков (Franc) и долларов (Dollar)

Валюта?

Нужен ли тест testFrancMultiplication()?

Метод умножения там, где ему следует быть, теперь мы готовы удалить ненужные нам производные классы.

В данной главе мы

• сделали идентичными две реализации метода times(), для этого мы избавились от вызовов фабричных методов в них, и заменили константы переменными;

• добавили в класс отладочный метод toString() без теста;

• попробовали модифицировать код (заменили тип Franc возвращаемого значения на Money) и обратились к тестам, чтобы узнать, сработает ли это;

• отменили изменения и написали еще один тест, добились успешного выполнения теста и вновь применили изменения.

<p>11. Корень всего зла</p>

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

$5 * 2 = $10

Сделать переменную amount закрытым (private) членом

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

5 CHF * 2 = 1 °CHF

Дублирование Dollar/Franc

Общие операции equals()

Общие операции times()

Сравнение франков (Franc) и долларов (Dollar)

Валюта?

Нужен ли тест testFrancMultiplication()?

Два производных класса, Dollar и Franc, обладают только конструкторами, однако конструктор – это недостаточная причина для создания подкласса. Мы должны избавиться от бесполезных подклассов.

Ссылки на подклассы можно заменить ссылками на суперкласс, не изменив при этом смысл кода. Начнем с класса Franc:

Franc

static Money franc(int amount) {

return new Money (amount, «CHF»);

}

Затем перейдем к классу Dollar:

Dollar

static Money dollar(int amount) {

return new Money (amount, «USD»);

}

Ссылок на класс Dollar больше нет, поэтому мы можем удалить этот класс. Однако в только что написанном нами тесте есть одна ссылка на класс Franc:

public void testDifferentClassEquality() {

assertTrue(new Money(10, "CHF"). equals(new Franc(10, "CHF")));

}

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

public void testEquality() {

assertTrue(Money.dollar(5). equals(Money.dollar(5)));

assertFalse(Money.dollar(5). equals(Money.dollar(6)));

assertTrue(Money.franc(5). equals(Money.franc(5)));

assertFalse(Money.franc(5). equals(Money.franc(6)));

assertFalse(Money.franc(5). equals(Money.dollar(5)));

}

Похоже, что все возможные случаи определения равенства достаточно полно охвачены другими тестами. Я даже сказал бы, что тестов слишком много. Мы можем удалить третье и четвертое выражение assert, так как они дублируют первое и второе:

public void testEquality() {

assertTrue(Money.dollar(5). equals(Money.dollar(5)));

assertFalse(Money.dollar(5). equals(Money.dollar(6)));

assertFalse(Money.franc(5). equals(Money.dollar(5)));

}

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

$5 * 2 = $10

Сделать переменную amount закрытым (private) членом

Побочные эффекты в классе Dollar?

Округление денежных величин?

equals()

hashCode()

Равенство значению null

Равенство объектов

5 CHF * 2 = 1 °CHF

Дублирование Dollar/Franc

Общие операции equals()

Общие операции times()

Сравнение франков (Franc) и долларов (Dollar)

Валюта?

Нужен ли тест testFrancMultiplication()?

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

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

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

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

Чед Фаулер

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

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