Переміщення методу
Перемі́щення ме́тоду (англ. Move Method) - це прийом рефакторингу, який базується на принципі перенесення методу з одного класу в інший, який більше його використовує.
Проблема[ред. | ред. код]
Певний створений метод після його створення, почав використовуватися іншим класом більше, ніж у власним.
Рішення[ред. | ред. код]
Потрібно створити новий метод в класі, який використовує його більше за інших, в який перенесться код із старого методу. При цьому код оригінального методу потрібно перетворити на звернення до нового методу в іншому класі або прибрати його взагалі.
Причини рефакторингу[ред. | ред. код]
- Рішення перемістити метод до класу, де знаходяться дані, з якими, в основному, і працює цей метод. Це призводить до підвищення пов'язаності всередині класів.
- Рішення перемістити метод, щоб прибрати або зменшити залежність класу, що викликає цей метод, від класу, в якому він знаходився. Це може бути корисно у випадку, коли клас, що викликає, вже має залежність від того класу, куди планується його перенести. Таким чином, зменшується зв'язаність між класами.
Порядок проведення[ред. | ред. код]
- Перевіряємо властивості, які використовував метод до початку рефакторингу. Якщо вони використовуються тільки самим методом, то потрібно перемістити і їх. Якщо ця властивість використовується ще якимось методами, то бажано перенести і ці методи. Адже налаштовувати зв’язок між цими методами у різних класах може бути проблематично.
- Перевірити наявність інших оголошень вихідного методу у базових і похідних класах. Якщо вони є, то потрібно або відмовитися від ідеї перенесення, або реалізувати в цільовому класі (клас, до якого переносимо метод) подібність поліморфізму для забезпечення різної функціональності методу.
- Оголосити метод, який переміщуємо в цільовому класі. За потреби змінити ім’я методу для кращої відповідності цільовиму класу.
- Копіюємо код вихідного методу в цільовий, після чого пристосовуємо скопійований код під нове місце.
- Якщо метод містить обробники виключних ситуацій, то слід визначити, в якому з класів - цільовому або вихідному - логічніше буде обробляти виключення.
- Визначити як буде виконуватися звернення до переміщеного методу.
- За наявності поля чи методу, які повертають об’єкт, не вносимо додаткових змін. За відсутності – потрібно написати новий метод або поле, в якому б зберігався об’єкт класу з переміщеним методом.
- Можливо зробити з вихідного методу делегуючий, який не буде містити код, а просто буде викликати цільовий метод. Можливо залишити метод як делегуючий у вихідному класі або видалити, попередньо замінивши всі звернення до нього зверненнями до створеного в іншому класі методу.
Приклад використання прийому[ред. | ред. код]
Виконано мовою 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
- Паралельні ієрархії наслідування
- Ланцюжок викликів
- Недоречна близькість
- Клас даних
Прийоми рефакторингу, яким допомагає переміщення методу[ред. | ред. код]
- Відокремлення класу
- Вбудовування класу
- Заміна параметрів об'єктом
Схожі рефакторинги[ред. | ред. код]
- Відокремлення методу
- Переміщення поля
Посилання[ред. | ред. код]
- Move Method(англ.) Сайт "Sourcemaking"
- Move Method(англ.) Сайт "Se Habla Code".
- Переміщення методу Сайт "Refactoring.guru"