Экстремальное программирование. Разработка через тестирование | страница 29
Franc
private String currency;
Franc(int amount) {
this.amount = amount;
currency = "CHF";
}
String currency() {
return currency;
}
То же самое сделаем в классе Dollar:
Dollar
private String currency;
Dollar(int amount) {
this.amount = amount;
currency = "USD";
}
String currency() {
return currency;
}
Теперь мы можем переместить объявление переменной и реализацию метода currency() в базовый класс Money, так как в обоих подклассах они одинаковые:
Money
protected String currency;
String currency() {
return currency;
}
Если переместить строковые констаны «USD» и «CHF» в статические фабричные методы, конструкторы двух производных классов станут идентичными, в результате мы сможем создать общую реализацию.
Вначале добавим в конструктор дополнительный параметр:
Franc
Franc(int amount, String currency) {
this.amount = amount;
this.currency = "CHF";
}
При этом возникают ошибки в двух местах при обращении к конструктору:
Money
static Money franc(int amount) {
return new Franc(amount, null);
}
Franc
Money times(int multiplier) {
return new Franc(amount * multiplier, null);
}
Постойте-ка! Почему это метод Franc.times() вызывает конструктор вместо фабричного метода? Будем ли мы заниматься этим сейчас или отложим любые связанные с этим модификации на более позднее время? В рамках догмы мы должны оставить посторонние дела на потом – не следует прерывать то, чем мы сейчас занимаемся. Однако на практике я иногда позволяю себе отвлечься, но лишь ненадолго, и ни в коем случае я не разрешаю себе прерывать прерывание (этому правилу научил меня Джим Коплаен – Jim Coplien). В данном случае будет лучше, если мы подчистим метод times(), прежде чем продолжить:
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 за один большой шаг: