Franc
Money times(int multiplier) {
return Money.franc(amount * multiplier);
}
Теперь фабричному методу можно передать значение «CHF»:
Money
static Money franc(int amount) {
return new Franc(amount, «CHF»);
}
Наконец, мы можем присвоить значение параметра полю класса:
Franc
Franc(int amount, String currency) {
this.amount = amount;
this.currency = currency;
}
Может показаться, что я снова перемещаюсь вперед слишком маленькими шажками. Действительно ли я рекомендую вам работать в таком же темпе? Нет. Я рекомендую вначале научиться работать в таком темпе, а затем самостоятельно определять скорость работы, которая покажется вам наиболее эффективной. Я всего лишь попробовал двигаться вперед большими шагами и на половине дороги допустил глупую ошибку. Запутавшись, я вернулся назад на несколько минут, перешел на пониженную передачу и сделал работу заново, более мелкими шажками. Сейчас я чувствую себя уверенней, поэтому мы можем попробовать внести такие же изменения в класс Dollar за один большой шаг:
Money
static Money dollar(int amount) {
return new Dollar(amount, «USD»);
}
Dollar
Dollar(int amount, String currency) {
this.amount = amount;
this.currency = currency;
}
Money times(int multiplier) {
return Money.dollar(amount * multiplier);
}
И это сработало с первого раза. Классно!
Подобная настройка скорости весьма характерна для TDD. Вам кажется, что слишком маленькие шажки ограничивают вас? Попробуйте двигаться быстрее. Почувствовали неуверенность? Переходите на короткий шаг. TDD – это процесс плавного управления – немного в одну сторону, немного в другую сторону. Не существует одного-единственного наиболее правильного размера шага, ни сейчас, ни в будущем.
Теперь два конструктора выглядят абсолютно одинаково, и мы можем переместить реализацию в базовый класс:
Money
Money(int amount, String currency) {
this.amount = amount;
this.currency = currency;
}
Franc
Franc(int amount, String currency) {
super(amount, currency);
}
Dollar
Dollar(int amount, String currency) {
super(amount, 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() в базовый класс, но прежде вспомним, что в данной главе мы
• на некоторое время заблудились в крупномасштабных идеях дизайна и, чтобы разобраться в проблеме, решили начать с решения небольшой задачи, на которую мы уже обратили внимание ранее;
• сделали одинаковыми два конструктора, переместив отличающийся код в вызывающий (фабричный) метод;
• на короткое время отвлеклись от рефакторинга, чтобы добавить в метод times() вызов фабричного метода;
• выполнили аналогичный рефакторинг в отношении класса Dollar за один большой шаг;
• получили два абсолютно идентичных конструктора и переместили код в базовый класс.
10. Избавление от двух разных версий times()
$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()?
В конце данной главы мы должны получить единый класс Money, соответствующий понятию «деньги». Две реализации метода times() близки друг к другу, однако они не идентичны:
Franc
Money times(int multiplier) {
return Money.franc(amount * multiplier);
}
Dollar
Money times(int multiplier) {
return Money.dollar(amount * multiplier);
}
Увы, я не вижу простого способа добиться идентичности этих методов, однако в некоторых ситуациях, для того чтобы продвинуться дальше, требуется вернуться немного назад, – это напоминает кубик Рубика. Что будет, если мы заменим вызовы фабричных методов операторами new? (Я отлично понимаю, что совсем недавно мы выполнили обратную процедуру – заменили new вызовами фабричных методов. Но что я могу поделать – сейчас мы решаем несколько иную задачу. Понимаю, что это может показаться обескураживающим, однако потерпите немного.)
Franc
Money times(int multiplier) {
return new Franc(amount * multiplier, "CHF");
Читать дальше
Конец ознакомительного отрывка
Купить книгу