Найкращі практики серіалізації агрегатів DDD


23

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

Тож як ви серіалізуєте або картографуєте стан агрегатів, не публікуючи їх через геттери та сетери? Я бачив чимало прикладів, наприклад, реалізацій репозиторію, але практично всі вони покладалися на публічні аксесуари для об'єктів та цінні об'єкти для відображення.

Ми могли б використовувати роздуми, щоб уникнути публічних доступу, але IMO ці об'єкти домену все одно неявно залежатимуть від проблеми серіалізації. Наприклад, ви не змогли перейменувати або видалити приватне поле, не налаштовуючи конфігурацію серіалізації / відображення. Таким чином, ви повинні розглянути питання про серіалізацію, де вам слід зосередитись на логіці домену.

То який найкращий компроміс слід дотримуватися тут? Живете з громадськими доступними користувачами, але уникаєте використовувати їх для чого-небудь іншого, крім коду зіставлення? Або я просто пропустив щось очевидне?

Мене явно цікавить серіалізація стану об’єктів домену DDD (агрегатів, що складаються з об'єктів та об'єктів цінності). Йдеться НЕ про серіалізацію в цілому або сценарії сценаріїв трансляції, коли служби без апарату працюють на простих об'єктах контейнерів даних.

Відповіді:


12

Види предметів

Для нашої дискусії давайте розділимо наші об’єкти на три різні види:

Логіка бізнес-домену

Це ті об’єкти, які отримують роботу. Вони переміщують гроші з одного чекового рахунку на інший, виконують замовлення та всі інші дії, які ми очікуємо здійснити.

Логічні об'єкти домену зазвичай не потребують аксесуарів (геттерів і сетерів). Швидше, ви створюєте об'єкт, передаючи йому залежності через конструктор, а потім маніпулюєте об'єктом методами (скажіть, не запитуйте).

Об'єкти передачі даних

Об'єкти передачі даних у чистому стані; вони не містять жодної логіки бізнесу. Вони завжди матимуть аксесуари. Вони можуть мати, а можуть і не мати сеттерів, залежно від того, пишете ви їх незмінно чи ні . Ви або встановите свої поля в конструкторі, і їх значення не змінюватимуться протягом життя об’єкта, або ваші аксесуари будуть прочитані / записані. На практиці ці об'єкти, як правило, можна змінювати, щоб користувач міг їх редагувати.

Перегляд об'єктів моделі

Об'єкти View Model містять представлення даних, що можна відображати / редагувати. Вони можуть містити ділову логіку, як правило, обмежену перевірку даних. Прикладом об’єкта «Перегляд моделі» може бути InvoiceViewModel, що містить об’єкт «Клієнт», об’єкт заголовка рахунків-фактур та рядки-позиції рахунків-фактур. Об'єкти View Model завжди містять аксесуари.

Таким чином, єдиним видом об'єкта, який буде "чистим", в тому сенсі, що він не містить польових аксесуарів, буде об'єкт "Логіка домену". Серіалізація такого об'єкта зберігає його поточний "обчислювальний стан", щоб його можна було пізніше отримати для завершення обробки. Моделі перегляду та DTO можна вільно серіалізувати, але на практиці їх дані зазвичай зберігаються в базі даних.

Серіалізація, залежності та зв'язок

Хоча це правда, що серіалізація створює залежності, в тому сенсі, що вам доведеться десеріалізувати до сумісного об'єкта, це не обов'язково випливає, що вам потрібно змінити конфігурацію серіалізації. Хороші механізми серіалізації мають загальне призначення; їм все одно, якщо ви зміните ім'я власності чи члена, доки він все ще може відображати значення для членів. На практиці це означає лише, що ви повинні повторно серіалізувати примірник об'єкта, щоб зробити представлення серіалізації (xml, json та інше) сумісним з вашим новим об'єктом; не потрібно змінювати конфігурацію серіалізатора.

Це правда, що об'єкти не повинні стосуватися того, як вони серіалізуються. Ви вже описали один із способів, як подібні проблеми можна від'єднати від класів доменів: рефлексія. Але серіалізатор повинен дбати про те, як він серіалізує та десеріалізує об'єкти; це, зрештою, його функція. Те, як ви відключаєте об'єкти від процесу серіалізації, - це зробити серіалізацію функцією загального призначення , здатною працювати для всіх типів об'єктів.

Одне з тих, що людей плутають, - це те, що розв'язка має відбуватися в обох напрямках. Це не; воно має працювати лише в одному напрямку. На практиці ніколи не можна повністю роз'єднатись; завжди є якась муфта. Мета розшарування зв'язку - полегшити технічне обслуговування коду, а не усунути всі залежності.


Я згоден з вашим поглядом на розв'язку. Серіалізатор залежить від об’єкта домену, і це все в порядку. Але не навпаки. Однак я не погоджуюся з вашим поглядом на загальнодоступні доступні об'єкти домену. На практиці їх часто є, так. Але IMO було б бажано реалізувати логіку домену в чистому об'єктно-орієнтованому дизайні: Скажіть, не питайте . Але все ж потрібні аксесуари для цілей відображення (ORM, серіалізація, GUI ...). І саме цього я хотів би уникнути, якщо це можливо.
EagleBeak

Як ви плануєте отримати доступ до своїх полів, якщо у вас немає доступу?
Роберт Харві

Насправді я маю на увазі не один із трьох видів об'єктів, які ви описуєте, а "агрегати" в термінології DDD та їх підпредметів (сутності, об'єкти цінності). Зараз я усвідомлюю, що моє запитання з цього приводу було недостатньо явним. Вибачте! Будь ласка, дивіться мою редакцію вище.
EagleBeak

1
Це в основному невирішена проблема - ви не можете мати інкапсуляцію, роз'єднання та серіалізацію \ кодування одночасно, виставляючи DTO, є одним із способів досягти компромісу. Однак є набагато менш нав'язливі способи: yegor256.com/2016/07/06/data-transfer-object.html
Василевс

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

-1

Основна мета серіалізації - забезпечити можливість даних, що виробляються однією системою, споживатися однією або кількома сумісними системами.

Найпростіший і надійний підхід до серіалізації - це переведення даних у типовий агностичний формат, який підтримує структуру у простому та простому для споживання форматі. Наприклад, найбільш поширені формати серіалізації (наприклад, JSON, XML) використовують чітко визначений текстовий формат. Текст простий у виробництві, передачі та споживанні.

Є 2 причини, чому використання одного з цих форматів може бути не ідеальним.

  1. Ефективність

    Для перекладу всіх даних у їх текстові еквіваленти є властива вартість. Типи даних не існували, якби текст був найбільш ефективним способом вираження всіх різних форм даних. Крім того, структура цих форматів не ідеальна для отримання підмножини даних асинхронно або по частинах.

    Наприклад, XML та JSON припускають, що використовувані дані будуть записуватися та читатись від початку до кінця. Для обробки дуже великих наборів даних, де пам'яті мало, системі, що споживає дані, може знадобитися можливість обробляти дані по частинах. У цьому випадку для обробки даних може знадобитися реалізація серіалізації / десеріалізації спеціального призначення.

  2. Точність

    Кастинг, необхідний для серіалізації / десеріалізації даних від призначеного типу до типу агностичного типу, призводить до втрати точності.

Можна стверджувати, що створення двійкового представлення об'єктів і даних, очевидно, є найбільш ефективним і точним рішенням. Основним недоліком є ​​те, що впровадження всіх систем, які споживають та виробляють дані, повинні залишатися сумісними. Це просто обмеження в теорії, але це кошмар, який слід підтримувати на практиці, оскільки виробничі системи мають тенденцію змінюватися / розвиватися з часом.

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


Вибачте, але це не відповідає на моє запитання. Йдеться про роз’єднання об’єктів домену від серіалізації, а не про причини серіалізації чи плюси та мінуси різних форматів. Як я серіалізую об’єкти домену, не публічно відкриваючи їх приватний стан?
EagleBeak

@EagleBeak О, я не розумів, що ваше занепокоєння стосується лише приватних членів. У вашому випадку ви можете серіалізувати у двійковій формі (припускаючи, що система прийому дотримується тих самих правил / структури, під якими були створені об’єкти домену) або написати певну логіку, яка витягує лише загальнодоступні дані перед серіалізацією.
Еван Плейс

Я думаю, що «звичайне» припущення полягає в тому, що дані, що серіалізуються у форматі загального призначення (наприклад, xml, json), будуть загальнодоступними, і ця привілей контролюється через API через ACL або інший еквівалент. Серіалізація / дезаріалізація загального призначення більшою мірою спадає на лінію деблокування даних від бізнес-логіки, що йде від однієї системи до іншої.
Еван Плейс

Я погоджуюсь із тим, що загальнодоступних приєднувачів зазвичай передбачають об'єкти, які підлягають серіалізації. Але я все ж хотів би дізнатися більше про те, як це стосується DDD та його сильної уваги до інкапсуляції логіки домену. Чи всі практикуючі в області DDD просто розкривають стан доменної моделі через публічні аксесуари для серіалізації (і ніколи це не згадують у своїх прикладах)? Я сумніваюся в цьому. Будь ласка, не зрозумійте мене неправильно. Я дуже ціную ваш внесок. Просто мене цікавить інший аспект. (Поки я не думаю, що моє запитання є надто розпливчастим, але відповідь Роберта Харві, і ваше змусило мене подумати про це.)
EagleBeak
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.