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

Извлечение переменной

Также известен как: Extract Variable

Проблема

У вас есть сложное для понимания выражение.

Решение

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

До
void renderBanner() {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
       (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // do something
  }
}
После
void renderBanner() {
  final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  final boolean isIE = browser.toUpperCase().indexOf("IE") > -1;
  final boolean wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // do something
  }
}
До
void RenderBanner() 
{
  if ((platform.ToUpper().IndexOf("MAC") > -1) &&
       (browser.ToUpper().IndexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // do something
  }
}
После
void RenderBanner() 
{
  readonly bool isMacOs = platform.ToUpper().IndexOf("MAC") > -1;
  readonly bool isIE = browser.ToUpper().IndexOf("IE") > -1;
  readonly bool wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) 
  {
    // do something
  }
}
До
if (($platform->toUpperCase()->indexOf("MAC") > -1) &&
     ($browser->toUpperCase()->indexOf("IE") > -1) &&
      $this->wasInitialized() && $this->resize > 0)
{
  // do something
}
После
$isMacOs = $platform->toUpperCase()->indexOf("MAC") > -1;
$isIE = $browser->toUpperCase()->indexOf("IE")  > -1;
$wasResized = $this->resize > 0;

if ($isMacOs && $isIE && $this->wasInitialized() && $wasResized) {
  // do something
}
До
def renderBanner(self):
    if (self.platform.toUpperCase().indexOf("MAC") > -1) and \
       (self.browser.toUpperCase().indexOf("IE") > -1) and \
       self.wasInitialized() and (self.resize > 0):
        # do something
После
def renderBanner(self):
    isMacOs = self.platform.toUpperCase().indexOf("MAC") > -1
    isIE = self.browser.toUpperCase().indexOf("IE") > -1
    wasResized = self.resize > 0

    if isMacOs and isIE and self.wasInitialized() and wasResized:
        # do something
До
renderBanner(): void {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
       (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // do something
  }
}
После
renderBanner(): void {
  const isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  const isIE = browser.toUpperCase().indexOf("IE") > -1;
  const wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // do something
  }
}

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

Главная мотивация этого рефакторинга — сделать более понятным сложное выражение, разбив его на промежуточные части. Это может быть:

  • Условие оператора if() или части оператора ?: в C-подобных языках.

  • Длинное арифметическое выражение без промежуточных результатов.

  • Длинное склеивание строк.

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

Достоинства

  • Улучшает читабельность кода. Постарайтесь дать выделенным переменным хорошие названия, которые будут отражать точно суть выражения. Так вы сделаете код читабельным и сумеете избавиться от лишних комментариев. Например, customerTaxValue, cityUnemploymentRate, clientSalutationString и т. д.

Недостатки

  • Появляются дополнительные переменные. Но этот минус компенсируется простотой чтения кода.

  • При рефакторинге выражений условных операторов помните о том, что программа обычно оптимизирует выполнение условных выражений и не выполняет дальнейшие проверки, если уже понятен финальный результат выражения. Например, если в выражении if (a() || b()) ... метод a вернет true, то программа не станет выполнять b — что бы он ни вернул, результирующее выражение всё равно будет истинным.

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

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

  1. Вставьте новую строку перед интересующим вас выражением и объявите там новую переменную. Присвойте этой переменной часть сложного выражения.

  2. Замените часть вынесенного выражения новой переменной.

  3. Повторите это для всех сложных частей выражения.