Також відомий як Duplicate Observed Data

Рефакторинг Дублювання видимих даних

Проблема

Дані предметної області програми зберігаються в класах, що відповідають за призначений для користувача інтерфейс (GUI).

Рішення

Має сенс виділити дані предметної області в окремі класи і, таким чином, забезпечити зв'язок і синхронізацію між класом предметної області і GUI.

До
Duplicate Observed Data - Before
Після
Duplicate Observed Data - After

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

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

Переваги

  • Ви розділяєте відповідальність між класами бізнес-логіки і представлення (принцип єдиного обов'язку), що спрощує читабельність і розуміння програми в цілому.

  • Якщо потрібно буде додати новий вид інтерфейсу, вам треба буде створити нові класи представлення, при цьому код бізнес-логіки чіпати немає ніякої нужди (принцип відкритості/закритості).

  • Над бізнес-логікою і призначеними для користувача інтерфейсами тепер можуть працювати різні люди.

Коли не слід застосовувати

  • Цей рефакторинг, який в класичному виконанні здійснюється з введенням патерну Спостерігач, практично не застосовується для веб-додатків, де всі класи перестворюються при кожному запиті до веб-сервера.

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

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

  1. Необхідно приховати прямий доступ до даних предметної області в _класі GUI _, для чого краще за всього використати самоінкапсуляцію поля. Таким чином, ви створите геттери і сеттери до цих даних.

  2. У обробниках подій _класу GUI _ використайте сеттери для установки нових значень полів. Це дасть можливість передавати нові значення в пов'язаний об'єкт предметної області.

  3. Створіть клас предметної області і скопіюйте в нього необхідні поля з _класу GUI _. Для всіх цих полів створіть геттери і сеттери.

  4. Застосуйте патерн Спостерігач до цих двох класів:

  • В класі предметної області створіть масив для зберігання об'єктів спостерігачів (_об'єктів GUI _ ), а також методи їх реєстрації, видалення і сповіщення.
  • В _класі GUI _ створіть поле для зберігання посилання на об'єкт предметної області, а також метод update(), який реагуватиме на зміни в цьому об'єкті та буде оновлювати значення полів в _класі GUI _. Зверніть увагу, в методі оновлення значення повинні встановлюватися безпосередньо, щоб уникнути рекурсії.
  • У конструкторі _класу GUI _ створіть екземпляр класу предметної області і збережіть його в створеному полі. Зареєструйте об'єкт GUI як спостерігач в об'єкті предметної області.
  • У сеттерах полів класу предметної області викликайте метод сповіщення спостерігача (тобто метод оновлення в класі GUI), щоб передати нові значення в призначений для користувача інтерфейс.
  • Змініть сеттери полів _класу GUI _ так, щоб вони тепер встановлювали нові значення в об'єкті предметної області, причому безпосередньо. Будьте уважні, якщо значення встановлюватимуться через сеттер класу предметної області, це приведе до нескінченної рекурсії.

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

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

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

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