Весняний РОЗПРОДАЖ

Відокремлення змінної

Також відомий як: 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. Повторіть це для всіх складних частин виразу.