Логотип ConstructiCat
CodeBust.
Навигация по разделу ▾

Замена метода объектом методов.

Проблема

У вас есть длинный метод, в котором локальные переменные так сильно переплетены, что это делает невозможным применение «извлечения метода».

Решение

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

##Пример

До
class Order {
  // ...
  public double price() {
    double primaryBasePrice;
    double secondaryBasePrice;
    double tertiaryBasePrice;
    // Выполнить длинные вычисления.
    return 0;
  }
}
После
class Order {
  // ...
  public double price() {
    return new PriceCalculator(this).compute();
  }
}

class PriceCalculator {
  private double primaryBasePrice;
  private double secondaryBasePrice;
  private double tertiaryBasePrice;
  
  public PriceCalculator(Order order) {
    // Скопировать нужные данные из объекта заказа.
  }
  
  public double compute() {
    // Выполнить длинные вычисления.
    return 0;
  }
}

##Зачем делать рефакторинг

Метод слишком длинный, и вы не можете его разделить из-за хитросплетения локальных переменных, которые сложно изолировать друг от друга.

Первым шагом к решению проблемы будет выделение всего этого метода в отдельный класс и превращение его локальных переменных в поля.

Во-первых, это позволит вам изолировать проблему в пределах этого класса, а во-вторых, расчистит дорогу для разделения большого метода на методы поменьше, которые, к тому же, не подходили бы к смыслу оригинального класса.

##Преимущества

  • Изоляция длинного метода в собственном классе позволяет остановить бесконтрольный рост метода. Кроме того, даёт возможность разделить его на подметоды в рамках своего класса, не засоряя служебными методами оригинальный класс.

##Как делать рефакторинг

  1. Создайте новый класс. Дайте ему название, основываясь на предназначении метода, который рефакторите.

  2. В новом классе создайте приватное поле для хранения ссылки на экземпляр класса, в котором раньше находился метод. Эту ссылку потом можно будет использовать, чтобы брать из оригинального объекта нужные данные, если потребуется.

  3. Создайте отдельное приватное поле для каждой локальной переменной метода.

  4. Создайте конструктор, который принимает в параметрах значения всех локальных переменных метода, а также инициализирует соответствующие приватные поля.

  5. Объявите основной метод и скопируйте в него код оригинального метода, заменив локальные переменные приватным полями.

  6. Замените тело оригинального метода в исходном классе созданием объекта-метода и вызовом его основного метода.