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

Матеріал з Вікіпедії — вільної енциклопедії.
Перейти до навігації Перейти до пошуку

Перемі́щення ме́тоду (англ. 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;
      }
  }

Бореться з запахами[ред. | ред. код]

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

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

Схожі рефакторинги[ред. | ред. код]

Посилання[ред. | ред. код]