.net реализация связи между агрегатными корнями в разных ограниченных контекстах
Я впервые применяю концепции DDD к реальной проблеме.
Я начал только с 1 ограниченного контекста, так как проект относительно небольшой. Однако я оказался с классами, которые почти идентичны, то есть очень похожи, очень похожи, но отличаются поведением. Я начинаю думать, что они на самом деле принадлежат к различным ограниченным контекстам, поскольку сущности одинаковы и просто имеют разное значение в другом контексте. Это подтверждается тем фактом, что приложение в основном имеет две совершенно разные группы пользователей.
Я немного читал о том, как два объекта в разных ограниченных контекстах могут общаться друг с другом. Я думаю, что я понимаю концепцию... но понятия не имею, как реализовать? Где-нибудь есть пример.net? т. е. агрегатный корень в одном ограниченном контексте, публикующий событие в агрегированном корне в другом ограниченном контексте? а также совокупный корень, вызывающий совокупный корень в другом ограниченном контексте.
И должен ли каждый ограниченный контекст иметь свой собственный уровень обслуживания? хранилище и слой данных?
2 ответа
Так что у меня есть 4 возможности для вас.
Перейдите к модели вашего домена. Тот факт, что вам нужно общаться между агрегатами, может указывать на проблему с моделью. Ключевым моментом здесь является то, что все в ограниченном контексте остается согласованным, но между агрегатами нет никаких гарантий.
Использование диспетчера процессов (или SAGA). Подобно ответу выше, вы можете отвечать на события домена и координировать перекрестную агрегацию связи из диспетчера процессов.
Внедрить сервис: будьте осторожны с этим, так как вы хотите добавить премиум нет или несколько зависимостей в свой домен. Сказав, что это все еще может быть правильным или, если не самым прагматичным способом решения проблемы.
Измените свою точку зрения: у вас уже есть информация из другого агрегата до взаимодействия? Если это так, можно ли это передать любой командой, устраняющей необходимость в общении?
Я подробно расскажу в своем посте на эту тему. В случае, если вы найдете это полезным, вы можете получить его здесь: 4 секрета межагрегатного взаимодействия в системе источников событий
В этом может помочь цитата из "Реализация доменного дизайна" Вона Вернона.
"Возможно, наиболее распространенное использование событий домена - это когда агрегат создает событие и публикует его. Издатель находится в модуле модели, но не моделирует какой-либо аспект. Скорее, он предоставляет простой сервис агрегатам, который нужно уведомить подписчиков о событиях. "
События публикуются с использованием службы, и реализация обработчика зависит от приемлемого времени для согласования остальной части модели. С Моими особыми требованиями это приемлемо для небольшой задержки во времени. События моего домена публикуются в очередь с использованием MSMQ, а затем во внешнем процессе я читаю из очереди и выполняю работу. Этот дизайн позволяет мне перенести эту работу на внешний хост и освободить IIS. Я использую тот же механизм, чтобы сохранить изменения в хранилище. Когда транзакция в моем агрегате завершена, я публикую зафиксированное событие в MSMQ и имею 2 очереди в многоадресной рассылке. Одна очередь для обработки дополнительной работы, а другая для сохранения.
Если вы еще не читали это, я настоятельно рекомендую эту книгу. Я уверен, что мой дизайн вызовет некоторую критику, но ваша реализация будет зависеть от ваших требований и от того, насколько вам удобно использовать конечную согласованность.
Надеюсь, что это поможет, и если вы решите использовать MSMQ, вот ссылка для начала. http://msdn.microsoft.com/en-us/library/aa480407.aspx
Вот моя реализация издателя событий домена.
public class DomainEventPublisher
{
string DomaineEventMessageQueue = @"FormatName:MULTICAST=234.1.1.1:8001";
public void PublishEvent(DomainEvent domainEvent, string correlationId)
{
MessageQueue eventQueue;
eventQueue = new MessageQueue(DomaineEventMessageQueue);
Message message = DomainEventMessage.CreateDomainEventMessage(domainEvent);
message.CorrelationId = correlationId;
eventQueue.Send(message);
}
}