Pergunta

We are using event sourcing and construct aggregates from stream of events. I have 2 aggregates - A1 and A2. A1 is used as a template in order to create A2. The size of A1 can be pretty big. The fundamental idea of Event Sourcing is that of ensuring every change to the state of an application is captured in an event object. So to save A2 we have to store a lot of information in the first event.

Is this situation common or creating from template is not good idea? Is there any better way to solve it?

Foi útil?

Solução

It would help more if you post more concrete examples of your aggregates and events. In general you can create more granular events if it make sense in your situation. Then instead of having 1-1 relationship between Command and Event you will have 1-N relationship, which is completely in-line with the CQRS theory.

So to give you an example:

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

And in Command Handler:

void Handle(CreateInvoce cmd)
{
  var invoice = new Invoice(cmd.InvoiceId, cmd.Customer, cmd.Address, cmd.Lines ....)
  uow.Register(invoice);
}

where only one InvoceCreated event will be raised.

Instead you can have more granular events:

InvoiceCreated : Event
- InvoiceId
- Customer
- Address

InvoiceLineAdded
- InvoiceId
- Item
- Vat
- Subtotal
- Etc

Then in Command Handler:

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);
}

Here ctor will raise InvoiceCreated event and AddLine method will raise InvoiceLineAdded event. You can then have events like InvoiceLineChanged/InvoiceLineRemoved, which you can use with updates.

That will allow you to have more granular events while still allowing more coarse-grained commands to be issued.

Big commands are ok, when they represent atomic actions from user/system PoV.

P.S. About using aggregate as templates, I wouldn't bother with that and instead will create data structure to serve as an accumulator to collect intermediate state. It could then be simply serialized/de-serialized. If there is no behavior behind filling a template - then you don't need aggregates at all. It's just a blob of data that will later be used to create an aggregate and run business rules. You're probably using this "template" object to store user entered state between multiple requests, like a session state, right ;)?

Hope that helps.

Outras dicas

I had a similar question here: How granular should a domain event be?

Usually a huge class indicates that you have to check its responsibilities and split it up into smaller classes according to SRP. By aggregates, domain events, etc... you can follow the same approach. By too many classes you can think about multiple bounded contexts, and so on...

Another part of the problem, that the command and the event granularity is a business decision. If your huge event makes sense by your domain model, then use it. Otherwise you (or the domain expert) should ask yourself, what is the user intent, and does the current event express it? Just a very simple example, you can have even very small domain events: PhoneNumberChanged or even smaller: PhoneNumberCorrected, PhoneNumberMigrated (all of them contains just a single property, the new phone number). According to this, you can have huge events as well. Ofc. maintaining those are much harder, after a while you probably start to version them, or migrate the entire event storage under another domain structure.

It is hard to help more without knowing anything about the problem. You should probably tell us something about what happened in the last years with your huge domain event, did you have issues later?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top