Читать «Рефакторинг с использованием шаблонов» онлайн - страница 209

Джошуа Кериевски

Рефакторинг Unify Interfaces зачастую представляет собой просто временный шаг на пути другого рефакторинга. Например, после этого рефакторинга вы можете выполнить последовательность рефакторингов, которая позволит вам удалить методы, добавленные при унификации интерфейсов. Иногда после применения Extract Interface [15] может отпасть необходимость в реализации по умолчанию метода абстрактного базового класса.

Механика

Найдите отсутствующий метод, т.е. открытый метод подкласса, который не объявлен в надклассе и/или интерфейсе.

1. Добавьте копию отсутствующего метода в надкласс/интерфейс. Если вы добавляете отсутствующий метод в надкласс, измените его тело так, чтобы он не выполнял никаких действий.

S Скомпилируйте.

Повторяйте эти действия до тех пор, пока надкласс/интерфейс и подкласс не будут иметь одинаковые интерфейсы.

Проверьте, чтобы весь код, имеющий отношение к надклассу, работал, как ожидается.

Пример

Мне необходимо унифицировать интерфейсы подкласса StringNode и его надкласса AbstractNode. Подкласс StringNode наследует большинство своих открытых методов от AbstractNode, за исключением единственного метода.

public class StringNode extends AbstractNode...

public void accept(textExtractor: TextExtractor) {

// Детали реализации...

}

}

1. Я добавляю копию метода accept (...) к классу AbstractNode, изменяя ее тело так, чтобы оно не выполняло никаких действий.

public abstract class AbstractNode...

public void accept(textExtractor: TextExtractor) { }

Теперь интерфейсы AbstractNode и StringNode унифицированы. Я компилирую программу и убеждаюсь, что все работает как следует. Все так

и есть.

Extract Parameter

Метод или конструктор присваивают полю локально инстанцируемое значение.

Присваивайте полю значение параметра, передаваемого клиентом, для чего выделите половину присвоения в параметр.

Мотивация

Иногда требуется присвоить полю внутри объекта значение, предоставляемое другим объектом. Если этому полю уже присвоено локальное значение, вы можете выделить половину инструкции присвоения в параметр, чтобы это значение мог передавать клиент.

Этот рефакторинг требовался мне после выполнения Replace Inheritance with Delegation [15]. В конце этого рефакторинга делегирующий класс содержал поле с объектом, которому он делегировал функциональность. Делегирующий класс присваивал этому полю новый экземпляр делегата. Мне же требовалось, чтобы делегат указывался клиентским объектом. Рефакторинг Extract Parameter позволил мне просто вынести код инстанцирования делегата в значение параметра, передаваемого клиентом.

Механика

1. Перед тем как вы сможете приступить к рефакторингу, присвоение значения полю должно находиться в конструкторе или методе. Если это не так, переместите присвоение в конструктор или метод.

2. Примените рефакторинг Add Parameter [15] для передачи значения в качестве параметра, используя в качестве типа параметра тип поля. Сделайте значением параметра значение поля, присваиваемое внутри объекта. Измените инструкцию присвоения так, чтобы поле получало значение нового параметра.