Обробники команд та DDD


11

У мене є програма ASP.NET MVC, яка використовує сервіс запитів для отримання даних та службу команд для відправки команд. Моє запитання щодо командної частини.

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

Конкретний приклад: AddCommentToArticleCommandHandler отримує AddCommentToArticleCommand, який має ArticleId, CommentText та EmailAddress.

Спочатку; має відбутися перевірка, як-от: - перевірити, чи існує стаття - перевірити, чи не закрита стаття, - перевірити, чи заповнений текст коментаря, та від 20 до 500 символів - перевірити, чи електронна адреса заповнена та чи має правильний формат.

Мені цікаво, куди поставити цю перевірку?

1 / у самому оброблювачі команд. Але потім його не можна повторно використовувати в інших обробниках команд.

2 / в об'єкті домену. Але оскільки доменний суб'єкт не знає про сховища чи послуги, він не може здійснити необхідну перевірку (не може перевірити, чи існує стаття). Але з іншого боку, якщо сутність не містить логіки, вона стає простим контейнером даних, який не відповідає принципам DDD.

3 / обробник команд використовує валідатори, так що перевірка може бути повторно використана в інших обробниках команд.

4 / Інші механізми?

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

Чи є у вас ідеї, як би ви реалізували це, починаючи від обробника команд і закінчуючи сховищами?


"Але оскільки доменний суб'єкт не знає про сховища чи послуги, він не може здійснити необхідну перевірку"? Чому ні? Який принцип DDD вимагає цього?
С.Лотт

Я всюди читав, що суб'єкт господарювання не повинен знати про сховища чи щось інше.
L-Four

Чи можете ви надати цитату, посилання чи приклад того, що конкретно - ви прочитали? Ми не знаємо, які описи DDD ви читаєте.
S.Lott


Джиммі Богард поділився деякими поглядами на цю тему ... lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world
травня,

Відповіді:


4

Я думаю, що в цьому випадку потрібно розділити два типи перевірки; перевірка домену та перевірка додатків .

Перевірка програми - це те, що ви маєте під час перевірки того, що властивість команди 'текст' становить від 20 до 200 символів; таким чином, ви підтверджуєте це за допомогою графічного інтерфейсу та за допомогою валідатора виду перегляду, який також виконується на сервері після POST. Те саме стосується електронної пошти (btw, я сподіваюся, ви зрозуміли, що така електронна пошта, як `32.d +" Hello World .42 "@ mindomän.local" є дійсною згідно з RFC).

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

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

Отже, зараз ми обговорили:

  • Перевірка програми

    • З JavaScript у графічному інтерфейсі
    • З MVC-валідацією на веб-сервері
  • Відсутній сукупний корінь + черги з отрутою

Що з командами, які не синхронізовані з доменом? Можливо, у вашій логіці домену є правило, яке говорить про те, що після 5 коментарів до статті допускаються лише коментарі нижче 400 символів, але один хлопець запізнився з 5-м коментарем і став 6-м - GUI не впіймав його, тому що він не відповідав домену в момент, коли він надсилає свою команду - у цьому випадку у вас є "помилка перевірки" як частина вашої доменної логіки, і ви повернете відповідну подію помилки.

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

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

У системі, над якою ми працюємо, ми робимо відповідь на запит з командами / подіями через протокол повідомлень MassTransit + RabbitMQ + брокер, і у нас є подія в даному конкретному домені (частково моделює робочий процес), який названий InvalidStateTransitionError. Більшість команд, які намагаються переміститися по краю графіка стану, можуть спричинити цю подію. У нашому випадку ми моделюємо GUI після послідовної послідовної парадигми, і тому ми відправляємо користувача на сторінку "команда прийнята", а потім дозволяємо поглядам веб-сервера пасивно оновлюватись через підписки на події. Слід зазначити, що ми також проводимо пошук подій у сукупних коренях (і будемо робити це також для саг).

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

Я можу рекомендувати переглянути дві презентації DDD з Норвезької конференції розробників 2011 року, а також презентацію Грега в Оредеві 2010 року .

Ура, Хенке


Дякую! Одне про перевірку: на даний момент ця перевірка ініціюється користувальницьким інтерфейсом (шляхом надання сервісу запиту Validate (команда)), який використовує Validate () самого об'єкта Коментар. Потім, якщо команда є дійсною, клієнт видає команду Execute, яка знову виконає Validate (), щоб бути впевненою, а якщо дійсно виконана фактична команда. Тож основну перевірку проводить суб'єкт коментаря, оскільки в будь-якому контексті перевірка буде однаковою (електронна пошта завжди має бути дійсною, текст коментаря не надто довгий тощо).
L-Four

Перевірка, яку ви, здається, описуєте, не здається мені підставою для моделювання її за допомогою двофазного протоколу перевірки - обов'язково, валідайте параметри виклику методу на об'єкті, як ви б протестували в одиничному тесті, але крім цього; рівень програми / GUI може легко перевірити правила, які ви описуєте, не надсилаючи команди домену. Імо. Якщо клієнт не злий, команда повинна працювати. Якщо клієнт зловмисний, команда не вдається, і ваша модель читання ніколи не отримує відповідну подію, і ви можете перевірити проблемну команду в черзі помилок.
Генрік

У користувальницькому інтерфейсі (ASP.NET MVC) я використовую атрибути перевірки, щоб зробити всю перевірку. Тож якщо ця перевірка успішна, мені не доведеться знову перевіряти домен, а просто виконувати команду?
L-Four

1
Так, ви виконуєте команду, але переконайтеся, що команда не є недійсною як у рівні програми, так і в домені.
Генрік

0

EDIT: Посилання WaybackMachine: http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

Немає жодної відповіді.

Є два чіткі сценарії проекту, які приходять до тями, коли я намагаюся відповісти, де має жити перевірка. Перший полягає в тому, що шар DTO використовується для передачі інформації між рівнями перегляду та домену. Наприклад, у вас може бути об’єкт "Клієнт" у вашому доменному шарі та пов'язаний з ним DTO клієнта в іншому шарі, на який ви переказуєте інформацію про Замовника, щоб потім надати представлення для представлення інформації про клієнта користувачеві.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.