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




Dollar

class Dollar extends Money {

private int amount;

}


Работают ли тесты? Работают. Можем двигаться дальше. Перемещаем переменную amount в класс Money:


Money

class Money {

protected int amount;

}


Dollar

class Dollar extends Money {

}


Режим видимости переменной amount потребовалось изменить: теперь вместо private используем модификатор доступа protected. В противном случае подкласс не сможет обратиться к этой переменной. (Если бы мы хотели двигаться еще медленнее, мы могли бы на первом шаге объявить переменную в классе Money, а на втором шаге удалить ее объявление из класса Dollar, однако я решил действовать смело и решительно.)

Теперь можно переместить код метода equals() вверх по иерархии классов, то есть в класс Money. Прежде всего мы изменим объявление временной переменной:


Dollar

public boolean equals(Object object) {

Money dollar = (Dollar) object;

return amount == dollar.amount;

}


Все тесты по-прежнему работают. Теперь попробуем изменить приведение типа.


Dollar

public boolean equals(Object object) {

Money dollar = (Money) object;

return amount == dollar.amount;

}


Чтобы исходный код получился более осмысленным, изменим имя временной переменной:


Dollar

public boolean equals(Object object) {

Money money = (Money) object;

return amount == money.amount;

}


Теперь переместим метод из класса Dollar в класс Money:


Money

public boolean equals(Object object) {

Money money= (Money) object;

return amount == money.amount;

}


Теперь настало время удалить метод Franc.equals(). Прежде всего мы обнаруживаем, что у нас до сих пор нет теста, проверяющего равенство двух объектов класса Franc, – когда мы, особо не раздумывая, дублировали код класса Dollar, мы нагрешили еще больше, чем думали. Поэтому, прежде чем модифицировать код, мы должны написать все необходимые тесты.

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

Прежде чем что-либо менять в коде, вы должны написать все тесты, которые кажутся вам необходимыми. Если этого не сделать, рано или поздно, выполняя рефакторинг, вы чего-нибудь поломаете. Код перестанет работать так, как должен. Вы потратите кучу времени на поиск ошибки и сформируете предубеждение против рефакторинга. Если подобный инцидент повторится, вы можете вообще перестать делать рефакторинг. Дизайн начнет деградировать. Вас уволят с работы. От вас уйдет ваша любимая собака. Вы перестанете мыться и чистить зубы. У вас начнется кариес. Чтобы сохранить зубы здоровыми, всегда сначала пишите тесты и только после этого выполняйте рефакторинг.