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

Извлечение класса.

Проблема

Один класс работает за двоих.

Решение

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

##Пример

До
class Person {
  private String name;
  private String officeAreaCode;
  private String officeNumber;

  String getTelephoneNumber() {
    return "(" + officeAreaCode + ") " + officeNumber;
  }
}
После
class Person {
  private String name;
  private TelephoneNumber officeTelephone = new TelephoneNumber();

  String getTelephoneNumber() {
    return officeTelephone.getTelephoneNumber();
  }
}
class TelephoneNumber {
  private String areaCode;
  private String number;

  String getTelephoneNumber() {
    return "(" + areaCode + ") " + number;
  }
}

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

Классы всегда изначально выглядят чёткими и понятными. Они выполняют свою работу и не лезут в обязанности других классов. Однако, с течением жизни программы добавляется один метод  — тут, одно поле  — там. В результате некоторые классы получают массу дополнительных обязанностей.

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

  • Этот рефакторинг призван помочь в соблюдении принципа единственной обязанности класса. Это делает код ваших классов очевиднее и понятнее.

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

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

Перед началом рефакторинга обязательно определите, как именно следует разделить обязанности класса.

  1. Создайте новый класс, который будет содержать выделенную функциональность.

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

  3. Используйте перемещение поля и перемещение метода для каждого поля и метода, которые вы решили переместить в новый класс. Для методов имеет смысл начинать с приватных, таким образом вы снижаете вероятность допустить массу ошибок. Старайтесь двигаться понемногу и тестировать результат после каждого перемещения, это избавит вас от необходимости исправлять большое число ошибок в самом конце.

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

  4. Ещё одним нюансом является доступность нового класса извне. Вы можете полностью спрятать его от клиента, сделав приватным, управляя при этом его полями из старого класса. Либо сделать его публичным, предоставив клиенту возможность напрямую менять значения. Решение зависит от того, насколько безопасны для поведения старого класса будут неожиданные прямые изменения значений в новом классе.