2011-01-08 4 views
6

При реализации событий домена, если обработчики событий будут использоваться только для проблем с чисто доменными именами; что вы обсудите с бизнес-специалистами, или они открыты для использования тем, что заинтересовано в модели домена?Обработчики событий домена. Должны ли они использоваться для проблем приложений?

Это, скорее всего, лучше всего объясняется простым примером, рассмотрите приложение «Календарь» для планирования работы сотрудников.

Мы могли бы иметь следующие события домена ...

AppointmentAdded AppointmentRemoved AppointmentContentChanged AppointmentMoved

У нас есть обработчики этих событий, например, когда назначение перемещается в то время за пределами сотрудников мы установили предупреждающий флаг.

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

Должны ли эти приложения быть потребителями событий домена, или же мы должны поднимать и обрабатывать отдельные системные события вместо этого?

ответ

5

Существует 2 установленных способа использования событий в решении DDD.

Первый основан на Udi Dahan's articles about events. Если вы еще не прочитали их, я настоятельно рекомендую это. В итоге говорится, что вы публикуете свои события с использованием статического класса в дополнение к нормальному поведению в стиле ORM. Таким образом, вы добавляете заказ в коллекцию заказов клиентов и, вы публикуете мероприятие. Поскольку поведение вашего домена выполняется внутри области транзакции, то есть обработчики событий. Вы также можете найти там и совет не вручную прикреплять объекты к Единице работы. Новые совокупные корни должны быть созданы путем вызова поведения на существующих.

Существует еще один вариант, который пропагандирует Грег Янг. Он основан на поиске событий, который в основном использует события как средство сохранения состояния. В этом подходе ваши совокупные корни обычно используют некоторую инфраструктуру (например, базовый агрегатный корневой класс) для применения событий. Применить вызывает вызов обработчика событий в агрегированном корневом классе и публикует это событие на шине (независимо от используемой вами реализации шины).

+3

Я сомневаюсь, что они способствуют обработке событий в той же транзакции, что и агрегат, который запускает это событие. Насколько я помню, Udi указывает, что лучше «загорать и забывать» outsite агрегированную транзакцию, особенно в тех случаях, когда обработчики событий не имеют никакого отношения к домену (например, сообщения электронной почты). Чтобы «стрелять и забывать» означает, что вас не волнует, получил ли слушатель сообщение, но вы должны заботиться о том, когда нужно отправить сообщение (отправьте сообщение). Вы отправляете сообщение после того, как агрегат завершил работу: state change + persistence. Поэтому я стараюсь уволить событие после настойчивости. – Tudor

+2

P.S. Событие может быть запущено агрегированием в любое время, но фактическая доставка сообщения должна обрабатываться после сохранения совокупности (или после завершения определенной команды, которая вызвала событие). – Tudor

2

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

Но если вам нужно сделать несколько самостоятельных вещей, когда произошло событие вашего домена, чем вам лучше использовать отдельные обработчики событий (см. Принцип «Разделение проблем»).

В первом случае, кстати, постарайтесь избежать смешивания логики домена с логикой обработки событий (инфраструктуры). Левая инфраструктура/межсекторальная обработка касается кода в обработчиках событий, вызывающих методы домена. Переместить код домена внутри методов объектов домена.

+0

это звучит разумно, но это приводит к новому вопросу о том, когда нужно поднимать события домена. Предположим, что добавление встречи в календарь выполняется в транзакции, добавление объекта в UnitOfWork должно выполняться в транзакции, но обновление пользовательского интерфейса должно выполняться вне транзакции. В этом случае, должно ли событие домена быть поднято внутри транзакции?и обновление пользовательского интерфейса должно выполняться в другом обработчике событий домена, что делает его работу Async. – Andronicus

+1

Событие домена представляет собой нечто, что уже произошло. Таким образом, не должно быть возможности отката транзакции в обработчике событий. Затем совершите транзакцию и вызовите обработчики событий для всех событий, отправленных во время транзакции. –

Смежные вопросы