Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git! Привет! Глянь мой новый курс по Git на GitByBit.com! Привет! Хочешь круто подтянуть Git? Глянь мой новый курс на GitByBit.com!

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

Также известен как: 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, name):
    if name == "banner"
        # Print the banner.
        # ...
    if name == "info"
        # Print the info.
        # ...
После
def outputBanner(self):
    # Print the banner.
    # ...

def outputInfo(self):
    # Print the info.
    # ...
До
 setValue(name: string, value: number): void {
  if (name.equals("height")) {
    height = value;
    return;
  }
  if (name.equals("width")) {
    width = value;
    return;
  }
  
}
После
setHeight(arg: number): void {
  height = arg;
}
setWidth(arg: number): number {
  width = arg;
}

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

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

Достоинства

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

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

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

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

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

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

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