top | item 25493655

(no title)

alex-lawrence | 5 years ago

Without Event Sourcing, I would say there is almost no boilerplate code for aggregates themselves or their root Entities. After all, an Entity can be implemented as plain old class or object. For event-sourced aggregates, it depends on the implementation style. With OOP, there might the typical AggregateRoot base class. With a more functional style, there can even be less of boilerplate code.

About the Domain Event publishing, I'm afraid I don't understand the question. What challenges did you face? Is it about event-sourced aggregates?

discuss

order

AWebOfBrown|5 years ago

If you have an aggregate root, it is responsible for knowing when changes to the aggregate have occurred, and thus making those visible.

What is the mechanism for it to do so? Does the aggregate root retain the events and decide when to dispatch them (likely after successful persistence to a datastore)?

Once ready for dispatch, what do you use to handle the events? Some kind of DomainEvents class ala https://udidahan.com/2009/06/14/domain-events-salvation/ ?

This is the boilerplate I'm referring to.

alex-lawrence|5 years ago

The Aggregate Root must track all Domain Events that occur upon executing an action and make them accessible somehow. Only after the successful persistence of the associated state change (and/or the events), they can be published via an Event Bus. The Aggregate itself only expresses that Domain Events occurred, but does not deal with publishing.

The article from Udi Dahan shows Domain Event handlers that "will be run on the same thread within the same transaction". This implementation is not suitable for handlers that affect other transactions. Udi explains that "you should avoid performing any blocking activities, like using SMTP or web services. Instead, prefer using one-way messaging to communicate to something else which does those blocking activities." What he is referring to as "one-way messaging" is the actual event publishing in my opinion and must guarantee event delivery.

In my book, the example implementations store all occurred Domain Events together with the Aggregate state. This is because it resembles the later use of Event Sourcing. There is a separate component that watches for changes in Aggregate data and publishes new Domain Events. After publishing, the events are marked accordingly.

Regardless of where newly occurred Domain Events are retained, it should be persistent. Many times, the events are stored in a separate table inside the same store as the affected Aggregate. Later, they are retrieved, published and either marked or deleted. This is called a Transactional Outbox: https://microservices.io/patterns/data/transactional-outbox.... The approach ensures that both the Aggregate change and the request to publish an event happen within the same transaction. The actual publishing happens in a separate one. This way, you get guaranteed event delivery or more specifically "at least once" delivery.