We continue talking about domain events, and we will focus of the way to process them from the domain to the outside world ( who is shy here ? π )
A - The forbidden way β
WE KNOW π we are in DDD, so that simple rule is a must to know :
Avoid exposing the domain model to any kind of middleware messaging infrastructure. Those kinds of components live only in the infrastructure. And while the domain model might at times use such infrastructure indirectly, it would never explicitly couple to it.
B - The way to go PUBLISH - SUBSCRIBE β
Because we want a decoupling between the domain and the processing of the domain events, the way to go is the observer design pattern.
One of the simplest and most effective ways to publish Domain Events without coupling to components outside the domain model is to create a lightweight Observer [Gamma et al.]. For the sake of naming I use Publish- Subscribe, which is acknowledged by [Gamma et al.]
B - 1 - Publisher π
The publisher of the events created inside the aggregate is a service that notifies all the subscribers and this service lives in a module(DDD) !
Perhaps the most common use of Domain Events is when an Aggregate creates an Event and publishes it. The publisher resides in a Module of the model, but it doesnβt model some aspect of the domain. Rather, it provides a simple service to Aggregates that need to notify subscribers of Events
In the figure below , we see clearly the role of the Publisher next to the aggregate :
Explanation : When publish() is executed on DomainEventPublisher, it iterates through all registered subscribers. Invoking subscribedToEventType() on each subscriber allows it to filter out all subscribers not subscribed to the specific Event type. Subscribers answering DomainEvent.class to this filter query will receive all Events. All qualified subscribers are sent the published Event by way of their handleEvent() method. After all subscribers have been either filtered or notified, the publisher completes.
B - 1 - Subscribers π§
If you have seen correctly the pucture above , you should now understand that subscribers are registered inside application service or VERY SPECIFIC CASES inside domain services
What components register subscribers to Domain Events? Generally speaking, Application Services (14), and sometimes Domain Services, will. The subscriber may be any component that is running on the same thread as the Aggregate that publishes the Event, and that can subscribe prior to the Event being published. This means that the subscriber is registered in the method execution path that uses the domain model.
And here is an example
public class BacklogItemApplicationService ... {
public void commitBacklogItem(
Tenant aTenant,
BacklogItemId aBacklogItemId,
SprintId aSprintId) {
DomainEventSubscriber subscriber =
new DomainEventSubscriber<BacklogItemCommitted>() {
@Override
public void handleEvent(BacklogItemCommitted aDomainEvent) {
// handle event here ...
}
@Override
public Class<BacklogItemCommitted> subscribedToEventType() {
return BacklogItemCommitted.class;
}
}
DomainEventPublisher.instance().subscribe(subscriber);
BacklogItem backlogItem =
backlogItemRepository
.backlogItemOfId(aTenant, aBacklogItemId);
Sprint sprint = sprintRepository.sprintOfId(aTenant, aSprintId);
backlogItem.commitTo(sprint);
}
}
The Application Service task coordinator then registers the subscriber with the DomainEventPublisher....What the subscriber does with the Event is not shown in this example. It could send an e-mail about the fact that a BacklogItemCommitted, if that made any sense. It might store the Event in an Event Store. It could forward the Event via a messaging infrastructure.
Hope you enjoyed it, See yoouuu in the next one π

Top comments (0)