Autumn SALE

Заміна змінної викликом методу

Також відомий як: Replace Temp with Query

Проблема

Ви розміщуєте результат якогось виразу в локальній змінній, щоб використати її далі в коді.

Рішення

Виділіть цей вираз в окремий метод і повертайте результат з нього. Замініть використання вашої змінної викликом методу. Новий метод може бути використаний і в інших методах.

До
double calculateTotal() {
  double basePrice = quantity * itemPrice;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  }
  else {
    return basePrice * 0.98;
  }
}
Після
double calculateTotal() {
  if (basePrice() > 1000) {
    return basePrice() * 0.95;
  }
  else {
    return basePrice() * 0.98;
  }
}
double basePrice() {
  return quantity * itemPrice;
}
До
double CalculateTotal() 
{
  double basePrice = quantity * itemPrice;
  
  if (basePrice > 1000) 
  {
    return basePrice * 0.95;
  }
  else 
  {
    return basePrice * 0.98;
  }
}
Після
double CalculateTotal() 
{
  if (BasePrice() > 1000) 
  {
    return BasePrice() * 0.95;
  }
  else 
  {
    return BasePrice() * 0.98;
  }
}
double BasePrice() 
{
  return quantity * itemPrice;
}
До
$basePrice = $this->quantity * $this->itemPrice;
if ($basePrice > 1000) {
  return $basePrice * 0.95;
} else {
  return $basePrice * 0.98;
}
Після
if ($this->basePrice() > 1000) {
  return $this->basePrice() * 0.95;
} else {
  return $this->basePrice() * 0.98;
}

...

function basePrice() {
  return $this->quantity * $this->itemPrice;
}
До
def calculateTotal():
    basePrice = quantity * itemPrice
    if basePrice > 1000:
        return basePrice * 0.95
    else:
        return basePrice * 0.98
Після
def calculateTotal():
    if basePrice() > 1000:
        return basePrice() * 0.95
    else:
        return basePrice() * 0.98

def basePrice():
    return quantity * itemPrice
До
 calculateTotal(): number {
  let basePrice = quantity * itemPrice;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  }
  else {
    return basePrice * 0.98;
  }
}
Після
calculateTotal(): number {
  if (basePrice() > 1000) {
    return basePrice() * 0.95;
  }
  else {
    return basePrice() * 0.98;
  }
}
basePrice(): number {
  return quantity * itemPrice;
}

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

Застосування цього рефакторингу може бути підготовчим етапом для застосування виділення методу для якоїсь частини дуже довгого методу.

Крім того, іноді можна знайти цей же вираз і в інших методах, що змушує замислитися над створенням спільного методу для його отримання.

Переваги

  • Покращує читабельність коду. Набагато простіше зрозуміти, що робить метод getTax(), ніж рядок orderPrice() * -2.

  • Допомагає прибрати дублювання коду, якщо замінюваний рядок використовується більш ніж в одному методі.

Корисні факти

Питання швидкодії

При використанні цього рефакторингу може виникнути питання, чи не позначиться результат рефакторингу погано на швидкодії програми. Чесна відповідь — так, результуючий код може отримати додаткове навантаження за рахунок виклику нового методу. Проте в наш час швидких процесорів і хороших компіляторів таке навантаження навряд чи буде помітне. Натомість ми отримуємо кращу читабельність коду і можливість використати новий метод в інших місцях програми.

Проте, якщо ваша тимчасова змінна служить для кешування результату дійсно важкого і великого виразу, має сенс зупинити цей рефакторинг після виділення виразу в новий метод.

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

  1. Переконайтеся, що змінній в межах методу присвоюється значення тільки один раз. Якщо це не так, використайте розділення змінної для того, щоб гарантувати, що змінна буде використана тільки для зберігання результату вашого виразу.

  2. Використайте відокремлення методу для того, щоби перемістити вираз, що цікавить вас, в новий метод. Переконайтеся, що цей метод тільки повертає значення і не міняє стан об’єкта. Якщо він якось впливає на видимий стан об’єкта, використайте розділення запиту і модифікатора.

  3. Замініть використання змінної викликом вашого нового методу.