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

Разделение запроса и модификатора.

Проблема

У вас есть метод, который возвращает какое-то значение, но при этом в процессе работы он изменяет что-то внутри объекта.

Решение

Разделите метод на два разных метода. Один из них пускай возвращает значение, а второй модифицирует объект.

##Пример

До
String foundMiscreant(String[] people) {
  for (String person : people) {
    if (person.equals("Don") || person.equals("John")) {
      sendAlert();
      return person;
    }
  }
  return "";
}
После
void checkSecurity(String[] people) {
  sendAlert(people);
  String found = foundPerson(people);
  someLaterCode(found);
}
void sendAlert(String[] people) {
  if (!foundPerson(people).isEmpty()) notifySecurity();
}
String foundPerson(String[] people) {
  for (String person : people) {
    if (person.equals("Don") || person.equals("John")) return person;
  }
  return "";
}

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

Этот рефакторинг является реализацией принципа разделения команд от запросов данных. Суть принципа сводится к тому, чтобы отделять код получения каких-то данных от кода, который изменяет что-то внутри объекта.

Код получения данных называют запросами, а код изменения видимого состояния объекта — модификаторами. Когда запрос и модификатор совмещены, у вас нет способа получить данные из объекта без того, чтобы не внести изменения в его состояние. Другими словами, вы задаёте вопрос и можете изменить ответ прямо в процессе его получения. Усугубляется эта проблема тем, что человек, вызывающий запрос, может не знать о «побочных действиях» такого метода, что нередко приводит к ошибкам выполнения программы.

Однако стоит подчеркнуть, что «побочными действиями» опасны только те модификаторы, которые меняют видимое состояние объекта. Это, например, поля, которые доступны из публичного интерфейса объекта, записи в базе данных, в файлах и т. д. Если какой-то модификатор всего лишь кеширует какую-то сложную операцию и сохраняет её внутри приватного поля класса, он вряд ли приведёт к «побочным действиям».

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

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

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

  1. Создайте новый метод-запрос, который бы возвращал то, что возвращал оригинальный метод.

  2. Сделайте так, чтобы оригинальный метод возвращал только результат вызова нового метода-запроса.

  3. Замените все обращения к оригинальному методу вызовом метода-запроса. Непосредственно перед этой строкой нужно вставить вызов метода-модификатора. Это убережёт вас от побочных действий в случае, если оригинальный метод использовался в описании условных операторов и циклов.

  4. Избавьтесь от кода возврата значения в оригинальном методе. После этого он станет правильным методом-модификатором.