Переміщення методу

Перемі́щення ме́тоду (англ. Move Method) - це прийом рефакторингу, який базується на принципі перенесення методу з одного класу в інший, який більше його використовує.

Проблема

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

Рішення

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

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

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

Порядок проведення

  1. Перевіряємо властивості, які використовував метод до початку рефакторингу. Якщо вони використовуються тільки самим методом, то потрібно перемістити і їх. Якщо ця властивість використовується ще якимось методами, то бажано перенести і ці методи. Адже налаштовувати зв’язок між цими методами у різних класах може бути проблематично.
  2. Перевірити наявність інших оголошень вихідного методу у базових і похідних класах. Якщо вони є, то потрібно або відмовитися від ідеї перенесення, або реалізувати в цільовому класі (клас, до якого переносимо метод) подібність поліморфізму для забезпечення різної функціональності методу.
  3. Оголосити метод, який переміщуємо в цільовому класі. За потреби змінити ім’я методу для кращої відповідності цільовиму класу.
  4. Копіюємо код вихідного методу в цільовий, після чого пристосовуємо скопійований код під нове місце.
  5. Якщо метод містить обробники виключних ситуацій, то слід визначити, в якому з класів - цільовому або вихідному - логічніше буде обробляти виключення.
  6. Визначити як буде виконуватися звернення до переміщеного методу.
    1. За наявності поля чи методу, які повертають об’єкт, не вносимо додаткових змін. За відсутності – потрібно написати новий метод або поле, в якому б зберігався об’єкт класу з переміщеним методом.
    2. Можливо зробити з вихідного методу делегуючий, який не буде містити код, а просто буде викликати цільовий метод. Можливо залишити метод як делегуючий у вихідному класі або видалити, попередньо замінивши всі звернення до нього зверненнями до створеного в іншому класі методу.

Приклад використання прийому

Виконано мовою C#:

  public class BankAccount
  {
      public BankAccount(int accountAge, int creditScore, AccountInterest accountInterest)
      {
          AccountAge = accountAge;
          CreditScore = creditScore;
          AccountInterest = accountInterest;
      }
      public int AccountAge { get; private set; }
      public int CreditScore { get; private set; }
      public AccountInterest AccountInterest { get; private set; }
  
      public double CalculateInterestRate()
      {
          if (CreditScore > 800)
              return 0.02;
   
          if (AccountAge > 10)
              return 0.03;
   
          return 0.05;
      }
  }
   
   public class AccountInterest
   {
       public BankAccount Account { get; private set; }
    
       public AccountInterest(BankAccount account)
       {
          Account = account;
       }
   
       public double InterestRate
       {
           get { return Account.CalculateInterestRate(); }
       }
    
       public bool IntroductoryRate
       {
           get { return Account.CalculateInterestRate() < 0.05; }
       }
   }

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

   public class BankAccount
   {
      public BankAccount(int accountAge, int creditScore, AccountInterest accountInterest)
      {
        AccountAge = accountAge;
        CreditScore = creditScore;
        AccountInterest = accountInterest;
      }
      public int AccountAge { get; private set; }
      public int CreditScore { get; private set; }
      public AccountInterest AccountInterest { get; private set; }
   }
   
  public class AccountInterest
  {
      public BankAccount Account { get; private set; }
   
      public AccountInterest(BankAccount account)
      {
          Account = account;
      }
   
      public double InterestRate
      {
          get { return CalculateInterestRate(); }
      }
   
      public bool IntroductoryRate
      {
          get { return CalculateInterestRate() < 0.05; }
      }
   
      public double CalculateInterestRate()
      {
          if (Account.CreditScore > 800)
              return 0.02;
   
          if (Account.AccountAge > 10)
              return 0.03;
   
          return 0.05;
      }
  }

Бореться з запахами

  • Стрільба дробом
  • Заздрісні функції
  • Оператори switch
  • Паралельні ієрархії наслідування
  • Ланцюжок викликів
  • Недоречна близькість
  • Клас даних

Прийоми рефакторингу, яким допомагає переміщення методу

  • Відокремлення класу
  • Вбудовування класу
  • Заміна параметрів об'єктом

Схожі рефакторинги

Посилання

This article is issued from Wikipedia. The text is licensed under Creative Commons - Attribution - Sharealike. Additional terms may apply for the media files.