Я работаю над полученной событием реализацией CQRS, с помощью DDD в приложении / доменный слой. У меня есть объектная модель, которая похожа на это:
public class Person : AggregateRootBase
{
private Guid? _bookingId;
public Person(Identification identification)
{
Apply(new PersonCreatedEvent(identification));
}
public Booking CreateBooking() {
// Enforce Person invariants
var booking = new Booking();
Apply(new PersonBookedEvent(booking.Id));
return booking;
}
public void Release() {
// Enforce Person invariants
// Should we load the booking here from the aggregate repository?
// We need to ensure that booking is released as well.
var booking = BookingRepository.Load(_bookingId);
booking.Release();
Apply(new PersonReleasedEvent(_bookingId));
}
[EventHandler]
public void Handle(PersonBookedEvent @event) { _bookingId = @event.BookingId; }
[EventHandler]
public void Handle(PersonReleasedEvent @event) { _bookingId = null; }
}
public class Booking : AggregateRootBase
{
private DateTime _bookingDate;
private DateTime? _releaseDate;
public Booking()
{
//Enforce invariants
Apply(new BookingCreatedEvent());
}
public void Release()
{
//Enforce invariants
Apply(new BookingReleasedEvent());
}
[EventHandler]
public void Handle(BookingCreatedEvent @event) { _bookingDate = SystemTime.Now(); }
[EventHandler]
public void Handle(BookingReleasedEvent @event) { _releaseDate = SystemTime.Now(); }
// Some other business activities unrelated to a person
}
С моим пониманием DDD до сих пор, и Человек и Заказ являются отдельным агрегатом, поддерживает две причины:
Еще одно бизнес-требование состоит в том, что Заказ никогда не может происходить для Человека несколько раз за один раз. Из-за этого, я обеспокоен запросами базы данных запроса по стороне чтения, поскольку могло потенциально быть некоторое несоответствие там (из-за использования CQRS и наличия в конечном счете последовательной базы данных чтения).
Совокупным корням нужно позволить запросить полученное событием запоминающее устройство идентификатором для объектов (ленивая загрузка их по мере необходимости)? Есть ли какие-либо другие пути реализации, которая имела бы больше смысла?
Прежде всего, действительно ли вам нужен источник событий в вашем случае? Мне это кажется довольно простым. Поиск событий имеет как преимущества, так и недостатки. Хотя это дает вам бесплатный контрольный журнал и делает модель вашей предметной области более выразительной, это усложняет решение.
Хорошо, я предполагаю, что на этом этапе вы обдумали свое решение и полны решимости придерживаться источников событий. Я думаю, что вам не хватает концепции обмена сообщениями как средства связи между агрегатами.Лучше всего он описан в статье Пэта Хелланда (которая, кстати, касается не DDD или поиска событий, а масштабируемости).
Идея состоит в том, что агрегаты могут отправлять друг другу сообщения, чтобы вызвать какое-то поведение. Между агрегатами не может быть синхронного (также известного как вызов метода) взаимодействия, потому что это приведет к проблемам с согласованностью.
В вашем примере человек AR отправит сообщение о резервировании в Booking AR. Это сообщение будет передаваться асинхронным и надежным способом. Booking AR обработает это сообщение и, если оно уже забронировано другим человеком, ответит сообщением ReservationRejected. В противном случае он отправит ReservationConfirmed. Эти сообщения должны обрабатываться персоналом AR. Возможно, они сгенерируют еще одно событие, которое будет преобразовано в электронное письмо, отправленное заказчику, или что-то в этом роде.
Нет необходимости получать данные запроса в модели. Просто обмен сообщениями. Если вам нужен пример, вы можете скачать исходники ветки «Сообщения» проекта Ncqrs и взглянуть на класс ScenarioTest. Он демонстрирует обмен сообщениями между AR с использованием примера Cargo и HandlingEvent из Синей книги.
Это ответ на ваш вопрос?