Также известен как Replace Parameter with Explicit Methods

Рефакторинг Замена параметра набором специализированных методов

Проблема

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

Решение

Извлеките отдельные части метода в собственные методы и вызывайте их вместо оригинального метода.
До
void setValue(String name, int value) {
  if (name.equals("height")) {
    height = value;
    return;
  }
  if (name.equals("width")) {
    width = value;
    return;
  }
  Assert.shouldNeverReachHere();
}
После
void setHeight(int arg) {
  height = arg;
}
void setWidth(int arg) {
  width = arg;
}
До
void SetValue(string name, int value) 
{
  if (name.Equals("height")) 
  {
    height = value;
    return;
  }
  if (name.Equals("width")) 
  {
    width = value;
    return;
  }
  Assert.Fail();
}
После
void SetHeight(int arg) 
{
  height = arg;
}
void SetWidth(int arg) 
{
  width = arg;
}
До
function setValue($name, $value) {
  if ($name == "height") {
    $this->height = $value;
    return;
  }
  if ($name == "width")) {
    $this->width = $value;
    return;
  }
  assert("Should never reach here");
}
После
function setHeight($arg) {
  $this->height = $arg;
}
function setWidth($arg) {
  $this->width = $arg;
}
До
def output(self, type):
    if name == "banner"
        # Print the banner.
        # ...
    if name == "info"
        # Print the info.
        # ...
После
def outputBanner(self):
    # Print the banner.
    # ...

def outputInfo(self):
    # Print the info.
    # ...

Причины рефакторинга

Метод, содержащий варианты выполнения, разросся до грандиозных размеров. В каждой из таких цепочек выполняется нетривиальный код. При этом новые варианты добавляются очень редко.

Достоинства

  • Улучшает читабельность кода. Куда очевидней, что делает метод startEngine() чем setValue("engineEnabled", true).

Когда нельзя применить

  • Не стоит применять замену параметра явными методами, если метод редко меняется, а новые вариации внутри него не добавляются.

Порядок рефакторинга

  1. Для каждого варианта исполнения метода создайте свой метод. Запускайте эти методы в зависимости от значения параметра в основном методе.

  2. Найдите все места, где вызывается оригинальный метод. Подставьте туда вызов одного из новых методов в зависимости от передающегося параметра.

  3. Когда не останется ни одного вызова оригинального метода, его можно будет удалить.

Устали читать?

Сбегайте за подушкой, у нас тут контента на 7 часов чтения.

Или попробуйте наш новый интерактивный курс по рефакторингу. Он более информативный и гораздо более интересный, чем банальный текст.

Узнать больше...

Живой пример

Первый раз здесь? Ничего страшного!

У нас здесь всё просто – интерактивный пример очень похож на видео (но выглядит гораздо круче).

  1. После начала проигрывания, вам показываются разнообразные подсказки и сообщения. Вы продвигаетесь дальше, кликая на них.
  2. Вы можете перематывать шаги, используя стрелки слева.
  3. Кроме того, вы можете посмотреть разницу между первоначальным и получившимся кодом, нажав кнопку с глазом ().
  4. Кнопка компиляции () позвоялет проверить текущий код на наличие ошибок.