Командные обработчики и DDD


10

У меня есть приложение ASP.NET MVC, которое использует службу запросов для получения данных и службу команд для отправки команд. Мой вопрос о командной части.

Если поступает запрос, служба команд использует диспетчер команд, который направит команду в назначенный ей обработчик команд. Этот обработчик команд сначала проверяет команду и, если все приемлемо, выполняет команду.

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

Первый; проверка должна происходить, например: - проверить, существует ли статья; - проверить, не закрыта ли статья; - проверить, заполнен ли текст комментария и содержит ли он от 20 до 500 символов; - проверить, заполнен ли адрес электронной почты и имеет ли он правильный формат.

Мне интересно, где поставить эту проверку?

1 / в самом обработчике команд. Но тогда его нельзя использовать в других обработчиках команд.

2 / в доменном объекте. Но поскольку объект домена не знает о репозиториях или сервисах, он не может выполнить необходимую проверку (не может проверить, существует ли статья). Но с другой стороны, если объект не содержит логики, он становится простым контейнером данных, который не следует принципам DDD.

3 / обработчик команд использует валидаторы, так что валидация может быть повторно использована в других обработчиках команд.

4 / Другие механизмы?

Я ищу цепочку обязанностей для этого конкретного примера и какие объекты (сущности, репозитории, ...) играют в этом роль.

У вас есть идеи, как бы вы это реализовали, начиная от командного обработчика и заканчивая репозиториями?


«Но поскольку субъект домена не знает о репозиториях или службах, он не может выполнить необходимую проверку»? Почему бы нет? Какой принцип DDD требует этого?
С.Лотт

Я везде читал, что сущность не должна знать о репозиториях или о чем-либо еще.
L-Four

Можете ли вы предоставить цитату, ссылку или пример того, что конкретно вы прочитали? Мы не знаем, какие описания DDD вы читаете.
С.Лотт


Джимми Богард поделился некоторыми взглядами на эту тему ... lostechies.com/jimmybogard/2009/02/15/validation-in-a-ddd-world
Майо

Ответы:


4

Я думаю, что вам нужно разделить два типа проверки в этом случае; Проверка домена и проверка приложений .

Проверка приложения - это то, что у вас есть, когда вы проверяете, что свойство команды 'text' содержит от 20 до 200 символов; таким образом, вы проверяете это с помощью графического интерфейса и с помощью средства проверки модели представления, которое также выполняется на сервере после процедуры POST. То же самое касается электронной почты (кстати, я надеюсь, вы понимаете, что электронная почта, такая как `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, а также презентацию Грега на Öredev 2010 .

Ура, Хенке


Спасибо! Одна вещь о проверке: на данный момент эта проверка запускается пользовательским интерфейсом (путем отправки запроса на проверку (команду) службе), который использует Validate () самой сущности Comment. Затем, если команда действительна, клиент выдает команду «Выполнить», которая снова выполнит Validate (), чтобы убедиться, и если она действительна, то фактическая команда будет выполнена. Таким образом, основная проверка выполняется сущностью Comment, поскольку в каждом контексте проверка будет одинаковой (адрес электронной почты всегда должен быть действительным, текст комментария не слишком длинным и т. Д.). Это хороший подход?
L-Four

Мне кажется, что валидация, которую вы описываете, не оправдывает ее моделирование с помощью двухфазного протокола валидации - конечно, проверяйте параметры вызова метода на объекте, как если бы вы тестировали в модульном тесте, но помимо этого; прикладной уровень / GUI может легко проверить правила, которые вы описываете, без отправки команд в домен. Имо. Если клиент не является вредоносным, команда должна работать. Если клиент является вредоносным, то команда не выполняется, и ваша модель чтения никогда не получает соответствующее событие, и вы можете проверить проблемную команду в очереди ошибок.
Хенрик

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

1
Да, вы выполняете команду, но убедитесь, что она не является недействительной как на уровне приложения, так и в домене.
Хенрик

0

РЕДАКТИРОВАТЬ: WaybackMachine ссылка: http://devlicio.us/blogs/billy_mccafferty/archive/2009/02/17/a-response-to-validation-in-a-ddd-world.aspx

Ответа нет.

Есть два ясных сценария проекта, которые приходят на ум, когда я пытаюсь ответить, где должна проходить валидация. Во-первых, уровень DTO используется для передачи информации между уровнями представления и домена. Например, у вас может быть объект Customer в вашем доменном слое и связанный с ним Customer DTO в другом слое, в который вы отображаете информацию о Customer, чтобы затем предоставить представление для представления информации о клиенте пользователю.

Второй сценарий - это проект, в котором объекты в доменном уровне совместно используются с представлением для представления данных пользователю. Например, вместо того, чтобы поддерживать отдельный уровень DTO и отображать объект домена в DTO, которые будут предоставлены представлению, представление может быть передано непосредственно объекту Customer. Таким образом, вместо того, чтобы говорить через отдельно поддерживаемый DTO, чтобы показать имя Клиента, представление просто запросит информацию у самого объекта Customer.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.