Marian Bäuerle
Marian Bäuerle

Reputation: 371

Event Sourcing: where to put business logic

I can think of two places where to put the domain logic in an event sourced system either one has a drawback.

Example: Calculating a metric from some data.
Either I have to calculate the metric twice (one time in the domain model, one time in the projection)
or I have to calculate it before sending the event and including it there.

Upvotes: 11

Views: 2764

Answers (2)

Alexey Zimarev
Alexey Zimarev

Reputation: 19630

The flow of control is usually like this:

  • Command is sent to a command handler and properties in the command are pre-validated, like identities are pointing to existing entities and all mandatory information is present and is in correct format
  • Command handler retrieves an aggregate from repository (by reading the event stream, but this is not important) and calls the aggregate method(s) based on what needs to be done by this command
  • Aggregate methods must ensure that their parameters and the aggregate state mutually allow the operation to be performed.

  • Aggregate method then creates an event and calls this When or Apply method to handle the event

  • The event handler only mutates the aggregate state, no logic there!

  • Control flow is then returned to the command handler and it persist all new events in the store

Further actions are related to projections.

The reason to put invariant protection aka business logic into aggregate events, before applying events is because when event is generated there is no turning back. This thing has already happened. You cannot deny applying an event. Think about replaying events when recovering the aggregate from the event stream (reading from repository), how would this possibly work if one day you decide to have an if-throw combination there?

So, in short:

  • Initial logic is applied before the command is sent
  • Some additional logic is in the command handler
  • Aggregate protection in aggregate methods (could very well be also in the command handler)
  • No logic in the event handler, only state mutation

No one ever said that event sourcing would help you fixing issues in your calculations. To make an extra safety net you might want to save commands but then you will have to issue compensating events or truncate streams, which is not really what you would want to do.

Upvotes: 13

hellxcz
hellxcz

Reputation: 76

I suppose you have some state in your Aggregate Root. This should contain the logic about your business. So it should have enough data to create the event based on command.
The consumer of this event (query model), does the computation. So if the intent is to compute averages, it has to manage to store itself in given manner.
I did similar thing. Once it was a part of business logic, so it was in Aggregate and once it was in Query model, because it was not part of business logic, but more the metric computation.
Don't be afraid to have data stored on multiple places. The responsibility of consistency should be delegated to events distribution, not to your business logic.

Upvotes: 0

Related Questions