Також відомий як Introduce Foreign Method

Рефакторинг Введення зовнішнього методу

Проблема

Службовий клас не містить методу, який вам потрібен, при цьому у вас немає можливості додати метод в цей клас.

Рішення

Додайте метод в клієнтський клас і передавайте в нього об'єкт службового класу в якості аргументу.
До
class Report {
  //...
  void sendReport() {
    Date nextDay = new Date(previousEnd.getYear(),
      previousEnd.getMonth(), previousEnd.getDate() + 1);
    //...
  }
}
Після
class Report {
  //...
  void sendReport() {
    Date newStart = nextDay(previousEnd);
    //...
  }
  private static Date nextDay(Date arg) {
    return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1);
  }
}
До
class Report 
{
  //...
  void SendReport() 
  {
    DateTime nextDay = previousEnd.AddDays(1);
    //...
  }
}
Після
class Report 
{
  //...
  void SendReport() 
  {
    DateTime nextDay = NextDay(previousEnd);
    //...
  }
  private static DateTime NextDay(DateTime date) 
  {
    return date.AddDays(1);
  }
}
До
class Report {
  //...
  void sendReport() {
    $previousDate = clone $this->previousDate;
    $paymentDate = $previousDate->modify('+7 days');
    //...
  }
}
Після
class Report {
  //...
  void sendReport() {
    $paymentDate = $this->nextWeek($this->previousDate);
    //...
  }
  /**
   * Foreign method. Should be in Date.
   */
  private static function nextWeek(DateTime $arg) {
    $previousDate = clone $arg;
    return $previousDate->modify('+7 days');
  }
}
До
class Report:
    #...
    def sendReport(self):
        nextDay = Date(self.previousEnd.getYear(),
            self.previousEnd.getMonth(), self.previousEnd.getDate() + 1);
        #...
Після
class Report:
    #...
    def sendReport(self):
        newStart = self._nextDay(self.previousEnd)
        #...
        
    def _nextDay(self, arg):
        return Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1)

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

У вас є код, який використовує дані і методи певного класу. Ви робите висновок, що цей код набагато краще буде виглядати і працювати всередині нового методу в цьому класі. Проте можливості додати такий метод в клас у вас немає (наприклад, тому що клас знаходиться в сторонній бібліотеці).

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

Оскільки ви передаєте об'єкт службового класу в параметри нового методу, у вас є доступ до всіх його полів. Ви можете робити всередині цього методу практично все, що вам може бути потрібно, начебто метод є частиною службового класу.

Переваги

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

Недоліки

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

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

  1. Створіть новий метод в клієнтському класі.

  2. У цьому методі створіть параметр, в який передаватиметься об'єкт службового класу. Якщо цей об'єкт може бути отриманий з клієнтського класу, параметр можна не створювати.

  3. Витягніть ділянки коду, які вам потрібні, в цей метод і замініть їх викликами методу.

  4. Обов'язково залиште в коментарі до цього методу мітку Foreight method і заклик перенести цей метод в службовий клас, якщо така можливість з'явиться надалі. Це полегшить розуміння того, чому метод знаходиться в цьому класі для тих, хто підтримуватиме програмний продукт в майбутньому.

Замучились читати?

Збігайте за подушкою, в нас тут контенту приблизно на 7 годин читання.

Або спробуйте наш новий інтерактивний курс з рефакторингу. Він більш інформативний та набагато цікавіший за банальний тест.

Дізнатися більше...

Живий приклад

Перший раз у нас? Нічого страшного!

У нас тут все просто – цей інтерактивний приклад дуже схожий на відео (хоча й виглядає набагато крутіше).

  1. Натискаєте велику кнопку "Почати", а далі слідуєте усім підказкам.
  2. Ви можете перемотувати програвання, використовуючи стрілки зліва.
  3. Окрім того, ви можете подивитися різницю між стартовим та отриманим кодом, натиснувши кнопку ока ().
  4. Кнопка компіляції та тестування () дає змогу перевірити код на наявність помилок.