Чи повинні об'єкти домену в дизайні, керованому доменом, лише для запису?


13

Я читав про дизайн, керований доменом майже два роки, і обережно вводив деякі поняття в свою щоденну роботу або принаймні створював плани того, як все, що я роблю регулярно, можна робити в рамках дизайну, керованого доменом.

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

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

  1. Як можна виконувати одиничні тести на об'єкті, який має сеттери або методи, що змінюють стан об'єкта, але не надають зовнішнього загальнодоступного інтерфейсу для зчитування стану з таких, як одержувачі властивостей у C #? Чи добре піддавати стан виключно для того, щоб зробити цей об'єкт перевіряючим?
  2. Як можна показувати користувачеві результати обчислень або операцій, виконаних у домені, без необхідності їх зберігати, а потім витягувати результати з зберігання магазину поза контекстом домену? Чи добре піддавати стан виключно з метою показу результатів.

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

Схожі матеріали:

  1. TDD, DDD та інкапсуляція

Відповіді:


9

Не впевнений, що існує "єдиний вірний шлях" для дизайнерського підходу, який, справедливо кажучи, все ще розвивається. По-перше, DDD і CQRS - це не одне і те ж, хоча, здається, люди CQRS походять від початкової точки, що впливає на DDD.

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

Можливо, ви бачите дебати навколо того, чи слід змінювати об'єкти домену та як функція доменного об'єкта в системі в цілому. CQRS розбиває систему на шляхи читання і запису, тому розумно зробити висновок, що вам на ділі не потрібен доступ для читання, коли ви знаходитесь на шляху запису. Читання потім стає чимось, що ви робите проти подій, викликаних деякими об’єктами домену та споживаними (обробленими) іншими. Якщо ви трохи повернетесь до історії CQRS, ви знайдете аргументи, згідно з якими об’єкти домену не повинні мати сеттерів, лише getters та єдиний метод обробника. Логіка тут полягає в тому, що тільки споживаючі події повинні призводити до зміни стану, і ці зміни повністю обробляються внутрішньо об'єктом домену.

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

Якщо ви експериментуєте з цим стилем, майте на увазі, що інші програмісти, ймовірно, не знайомі з цим підходом, і що існує порівняно мало (але цікавих) сценаріїв, де це виправдано як проектний підхід.

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

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

Знову ж таки, ви заплутані, бо ці підходи заплутані. Якщо ви хочете прийняти кілька хороших ідей у ​​своєму програмуванні, спершу візьміть соковиті шматочки. Межі DDD і чіткість ролей - це зміни у вашому мисленні про спілкування зі своїм кодом. Як мінімум, CQRS говорить про те, що зчитування даних і запис даних - це операції, що відокремлюються. Це розуміння змушує вас дуже чітко подумати про те, яка роль даних, які вам потрібно представити, полягає у тому, скільки вам насправді потрібно, хто їх споживає, наскільки свіжим він повинен бути і т. Д. ... Вам не потрібно повноцінна реалізація подій Sourcing для прийняття кращої інкапсуляції у вашому кодуванні. Ви можете почати, зосередившись на атомних операціях у вашому об’єкті, "Скажи, не питай" підходи до дизайну об'єктного інтерфейсу


1
+1 для початку з соковитими шматочками. Окрім того, відкусити лише CQS (поки пропустити частину «подій») може бути гарним місцем для початку.
cottsak

1

Чи повинні об'єкти домену в дизайні, керованому доменом, лише для запису?

Ні. CQRS може використовуватися поряд з DDD.


Але чи частина запиту CQRS стосується даних запитів, які використовується доменною моделлю для внесення змін до моделі, або вони можуть бути використані для запиту даних для рівня додатків, який може сказати, показує значення користувачеві? Я чую від деяких, що DDD - це все, що стосується узгодження змін, і його не слід використовувати для читання з будь-якої іншої мети, ніж для узгодження змін до іншого об'єкта в доменній моделі. Рішення так чи інакше означало б кардинально інший дизайн моделі, бачачи, що експоновані дані про об'єкти домену будуть різними, якщо вони використовуються лише в домені.
jpierson

0

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

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

Щоб відповісти на ваше друге запитання, щоб відобразити результати команд, вам слід домовитись про те, щоб події домену були «опубліковані» у вашій моделі читання.


Не могли б ви трохи розібратися, чи це все ще застосовується, коли ви не використовуєте джерела подій?
jpierson

1
Без пошуку подій, можливо, моя пропозиція не вийде; Я не знаю способів вашого коду. Для об’єкта домену, який в ідеалі не виявляє жодних властивостей, можливо, ви можете явно реалізувати тестовий інтерфейс, який розкриває властивості, які ви хочете перевірити. Лише ваш тестовий код буде «знати» для передачі таких об’єктів домену до тестового інтерфейсу.
Ед Джеймс

Дякую за цю пропозицію. Я відчуваю трохи занепокоєння щодо ідеї зміни моїх доменних класів спеціально для перевірки, але я вважаю, що це може бути однією з тих сірих областей, які все ще знаходяться в дизайні, керованому доменом, якщо ви хочете, щоб це було перевірено. Інша думка полягає в тому, що якщо можна було б виставити стабілізацію та перевірку через один і той же інтерфейс, то, принаймні, ви ввели лише одну залежність від інфраструктури замість двох. Що думають про це інші?
jpierson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.