12
votes

I am currently beginning my first real attempt at a DDD/CQRS/ES system after studying a lot of material and examples.

1) I have seen event sourcing examples where the Aggregates are Event Handlers and their Handle method for each event is what mutates the state on the object instance (They implement an IHandleEvent<EventType> interface for events that would mutate the state)

2) I have also seen examples where the Aggregates would just look like plain classic Entity classes modelling the domain. Another Event Handler class is involved in mutating the state.

State, of course, is mutated on an aggregate by the event handlers in both cases when rebuilding the aggregate from a repository call that gets all the previous events for that aggregate, and when a command handler calls methods on an aggregate. Although in the latter I've seen examples where the events are published in the command handler rather than by the aggregate, which I'm convinced is wrong.

My question is what are the pros and cons between method (1) and (2)

2
I wonder what the execution flow looks like in approach 2). How does the separate Event Handler change state in the Aggregate ? Do you need to expose all of the state to it ? Is that done through a method on the Aggregate ? What should the name of such a method be, vs. the name of the method that is called by the Command Handler and produces the event ? Isn't that a bit contrived ?guillaume31
On further review of the example code for 2 and what I thought it was doing, I have come to conclusion that it is a very strange approach and as you say contrived and over-engineered. I feel like I should edit the question to just ask if approach (1) is the common approach for an event sourcing pattern with aggregates, or is there another way that I have not had exposure to? (however no need to discuss snapshotting as I feel I understand its place when it is required)Mark Kennedy
I've only seen method 1) so far, with functional variants where part of the command handler behavior goes into the Aggregate itself.guillaume31

2 Answers

12
votes

The job of receiving/handling a command is different from actioning it. The approach I take is to have a handler. It's job is to receive a command. The command hold the AggregateId which it can then use to get all the events for the aggregate. It can then apply those events to the aggregate via a LoadFromHistory method. This brings the aggregate up to date and makes it ready to receive the command. So my the short version is option 2.

I have some posts that you find helpful, the first is a overview of the flow of a typical CQRS/ES application. It's not how it should be just how they often are. You can find that at CQRS – A Step-by-Step Guide to the Flow of a typical Application!

I also have a post on how to build an aggregate root for CQRS and ES if thats helpful. You can find that at Aggregate Root – How to Build One for CQRS and Event Sourcing

Anyway, I hope that helps. All the best building your CQRS/ES app!

2
votes

While I agree with Codescribler , I need to go a bit further into details. ES is about expressing an entity state as a stream of events (which will be stored). A message handler is just a service implementation which will tell an Entity what to do.

With ES the entity implements its changes by generating one or more events and then applying them to itself. The entity doesn't know that its changes come from a command or event handler (it should be 'always' a command handler but well.. sometimes it doesn't matter), however it modifies state via its own events that will be published by a service (or the event store itself).

But... in a recent app, for pragmatic reasons my ES entity accepted the commands directly, although the entity itself wasn't an implementation of a command handler. The handler would just relay the command to the entity.

So, you can actually handle messages directly with an entity but only as an implementation detail, I wouldn't recommend to designate an entity to be a command/event handler, as it's a violation of the Separation of Concerns.