Экстремальное программирование. Разработка через тестирование | страница 31



Валюта?

Нужен ли тест 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");

}


Dollar

Money times(int multiplier) {

return new Dollar(amount * multiplier, "USD");

}


Мы абсолютно уверены, что в экземплярах класса Franc значение поля currency всегда будет равно «CHF», поэтому можем написать:


Franc

Money times(int multiplier) {

return new Franc(amount * multiplier, currency);

}


Сработало! Теперь тот же трюк можно проделать и в отношении класса Dollar:


Dollar

Money times(int multiplier) {

return new Dollar(amount * multiplier,currency);

}


Мы почти закончили. Имеет ли значение, что мы используем в данном случае – Franc или Money? Об этом можно рассуждать в течение некоторого времени исходя из имеющихся знаний о внутреннем устройстве нашей системы, однако у нас есть чистый код и тесты, которые дают нам уверенность в том, что код работает так, как надо. Вместо того чтобы тратить несколько минут на рассуждения, мы можем спросить об этом компьютер. Для этого достаточно внести интересующие нас изменения в код и запустить тесты. Обучая методике TDD, я наблюдаю подобную ситуацию постоянно – опытные умные программисты тратят от 5 до 10 минут на обсуждение вопроса, на который компьютер может дать ответ в течение 15 секунд. Если у вас нет тестов, вам остается только размышлять и предполагать. Если же у вас есть тесты, вместо того, чтобы напрасно тратить время, вы можете провести быстрый эксперимент. Как правило, если у вас есть тесты, быстрее спросить компьютер.

Чтобы провести интересующий нас эксперимент, модифицируем код так, чтобы метод Franc.times() возвращал значение типа Money: