Можно ли создавать огромные события в Event Sourcing?
Мы используем источник событий и создаем агрегаты из потока событий. У меня 2 агрегата - А1 и А2. A1 используется в качестве шаблона для создания A2. Размер А1 может быть довольно большим. Основная идея Event Sourcing заключается в том, чтобы гарантировать, что каждое изменение в состоянии приложения фиксируется в объекте события. Таким образом, чтобы сохранить A2, мы должны хранить много информации в первом событии.
Это обычная ситуация или создание из шаблона не очень хорошая идея? Есть ли лучший способ решить это?
2 ответа
Это помогло бы больше, если бы вы опубликовали более конкретные примеры ваших агрегатов и событий. В общем, вы можете создавать более детальные события, если это имеет смысл в вашей ситуации. Тогда вместо отношения 1-1 между Командой и Событием у вас будет отношение 1-N, которое полностью соответствует теории CQRS.
Итак, чтобы дать вам пример:
CreateInvoice : Command
- InvoiceId
- Customer (10 fields)
- Address (5 more fields)
- InvoceLine[] (where each InvoiceLine also have 10 fields or so)
- Rest of 100 or so fields
InvoiceCreated : Event
- InvoiceId
- Customer (10 fields)
- Address (5 more fields)
- InvoceLine[] (where each InvoiceLine also have 10 fields or so)
- Total
- Rest of 100 or so fields
И в командном обработчике:
void Handle(CreateInvoce cmd)
{
var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address, cmd.Lines ....)
uow.Register(invoice);
}
где будет создано только одно событие InvoceCreated.
Вместо этого вы можете иметь более детализированные события:
InvoiceCreated : Event
- InvoiceId
- Customer
- Address
InvoiceLineAdded
- InvoiceId
- Item
- Vat
- Subtotal
- Etc
Затем в командном обработчике:
void Handle(CreateInvoce cmd)
{
var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address);
foreach (var line in cmd.Lines)
{
invoice.AddLine(line.Item, line.Quantity, line.Price, ...);
}
uow.Register(invoice);
}
Здесь ctor будет вызывать событие InvoiceCreated, а метод AddLine будет вызывать событие InvoiceLineAdded. Затем вы можете иметь такие события, как InvoiceLineChanged/InvoiceLineRemoved, которые вы можете использовать с обновлениями.
Это позволит вам иметь более детализированные события, в то же время позволяя выполнять более грубые команды.
Большие команды в порядке, когда они представляют атомарные действия от пользователя / системы PoV.
PS Об использовании агрегата в качестве шаблонов я бы не стал беспокоиться, а вместо этого создам структуру данных, которая будет служить аккумулятором для сбора промежуточного состояния. Затем он может быть просто сериализован / десериализован. Если за заполнением шаблона нет поведения - вам не нужны агрегаты. Это просто блок данных, который впоследствии будет использоваться для создания совокупности и запуска бизнес-правил. Вы, вероятно, используете этот "шаблонный" объект для хранения введенного пользователем состояния между несколькими запросами, например, состояния сеанса, верно;)?
Надеюсь, это поможет.
У меня был похожий вопрос: насколько гранулированным должно быть доменное событие?
Обычно огромный класс означает, что вы должны проверить его обязанности и разделить его на более мелкие классы в соответствии с SRP. По агрегатам, событиям домена и т. Д. Вы можете следовать тому же подходу. При слишком большом количестве классов вы можете думать о нескольких ограниченных контекстах и так далее...
Другая часть проблемы в том, что команда и гранулярность события - это бизнес-решение. Если ваше огромное событие имеет смысл в вашей доменной модели, используйте его. В противном случае вы (или эксперт по доменам) должны спросить себя, каковы намерения пользователя и выражает ли это текущее событие? Просто очень простой пример, вы можете иметь даже очень маленькие доменные события: PhoneNumberChanged
или даже меньше: PhoneNumberCorrected
, PhoneNumberMigrated
(все они содержат только одно свойство, новый номер телефона). В соответствии с этим, вы можете иметь огромные события. Ofc. поддерживать их намного сложнее, через некоторое время вы, вероятно, начнете создавать версии или перенести все хранилище событий в другую структуру домена.
Трудно помочь больше, не зная ничего о проблеме. Вероятно, вы должны рассказать нам кое-что о том, что произошло за последние годы с вашим огромным событием в области доменов.