Дублювання видимих даних - (англ. duplicate observed data) це один з прийомів рефакторингу, який застосовується у випадках, коли потрібно розділити дані наприклад GUI та предметної області.
Проблема Дані предметної області програми зберігаються в класах, що відповідають за призначений для користувача інтерфейс (GUI).
Рішення Має сенс виділити дані предметної області в окремі класи і, таким чином, забезпечити зв'язок і синхронізацію між класом предметної області і GUI. Причини рефакторингу Ви хочете мати декілька видів інтерфейсу для однакових даних (наприклад, у вас є додаток не лише для десктопа, але також для телефонів і планшетів). В цьому випадку вам буде дуже складно уникнути великої кількості помилок і дублювання коду, якщо ви не розділите GUI і предметну область.
Переваги Ви розділяєте відповідальність між класами бізнес-логіки і представлення (принцип єдиного обов'язку), що спрощує читабельність і розуміння програми в цілому. Якщо потрібно буде додати новий вид інтерфейсу, вам треба буде створити нові класи представлення, при цьому код бізнес-логіки чіпати немає ніякої нужди (принцип відкритості/закритості). Над бізнес-логікою і призначеними для користувача інтерфейсами тепер можуть працювати різні люди.
Коли його не можна застосувати Цей рефакторинг, який в класичному виконанні здійснюється з введенням шаблону Спостерігач, практично не застосовується для вебдодатків, де всі класи перестворюються при кожному запиті до вебсервера.
Проте, загальний принцип відокремлення бізнес-логіки в окремі класи має сенс, у тому числі, і для вебдодатків. Але реалізується він за допомогою інших рефакторингів, які обираються з урахуванням дизайну вашої системи.
Порядок рефакторингу Необхідно приховати прямий доступ до даних предметної області в класі GUI, для чого найкраще використати самоінкапсуляцію поля. Таким чином, ви створите геттери і сеттери до цих даних. У обробниках подій класу GUI використайте сеттери для установки нових значень полів. Це дасть можливість передавати нові значення в пов'язаний об'єкт предметної області. Створіть клас предметної області і скопіюйте в нього необхідні поля з класу GUI. Для всіх цих полів створіть геттери і сеттери. Застосуйте патерн Спостерігач до цих двох класів: В класі предметної області створіть масив для зберігання об'єктів спостерігачів (об'єктів GUI), а також методи їх реєстрації, видалення і сповіщення. В класі GUI створіть поле для зберігання посилання на об'єкт предметної області, а також метод update(), який реагуватиме на зміни в цьому об'єкті та буде оновлювати значення полів в класі GUI. Зверніть увагу, в методі оновлення значення повинні встановлюватися безпосередньо, щоб уникнути рекурсії. У конструкторі класу GUI створіть екземпляр класу предметної області і збережіть його в створеному полі. Зареєструйте об'єкт GUI як спостерігач в об'єкті предметної області. У сеттерах полів класу предметної області викликайте метод сповіщення спостерігача (тобто метод оновлення в класі GUI), щоб передати нові значення в призначений для користувача інтерфейс. Змініть сеттери полів класу GUI так, щоб вони тепер встановлювали нові значення в об'єкті предметної області, причому безпосередньо. Будьте уважні, якщо значення встановлюватимуться через сеттер класу предметної області, це приведе до нескінченної рекурсії.
Схожі в групі методів рефакторингу "Організація даних" Самоінкапсуляція поля Заміна простого поля об'єктом Заміна значення посиланням Заміна посилання значенням Заміна поля-масиву об'єктом Дублювання видимих даних Заміна одностороннього зв'язку двонаправленим Інкапсуляція поля Інкапсуляція колекції Заміна кодування типу класом Заміна кодування типу підкласами Заміна кодування типу станом/стратегією Заміна підкласу полями
Посилання Duplicate Observed Data Прийоми рефакторингу