DDD: Where to raise "created" domain event
Asked Answered
S

2

13

I struggle to find and implement the best practise for the following problem: where is the best location to raise create domain event (the event that notifies for the creation of an aggregate). For example if we have Order aggregate in our bounded context we would like to notifie all interested parties when order is create. The event could be OrderCreatedEvent.

What I tried in first place is to raise this event in the constructor (I have a collection of domain events in each aggregate). This way it is okay only when we create the order. Because when we would like to do anything with this aggregate in the future we are going to create new instance of it through the constructor. Then OrderCreatedEvent will be raised again but it is not true.

However, I thought it would be okey to raise the event in the application layer but it is an anti-pattern (the domain events should live only in the domain). Maybe to have a method Create that will just add the OrderCreatedEvent to its domain events list and call it in the application layer when order is created is an option.

Interesting fact I found on the internet is that it is an anti-pattern to raise domain events in the contructor which means the last described option (to have Create method) would be the best approach.

I am using Spring Boot for the application and MapStruct for the mapper that maps the database/repository Entity to the domain model aggregate. Also, tried to find a way to create a mapper that is going to skip the contructor of the target class but as all properties of the Order aggregate are private seems impossible.

Shoeblack answered 5/11, 2020 at 22:27 Comment(1)
I have run into the very same question. What solution did you end up with?Exorcise
A
10

Usually constructor are used only to make assignations on object's fields. This is not the right place to trigger behaviours, especially when they throw exceptions or have side effects

DDD theorists (from Eric Evans onwards) suggest implementing factories for aggregates creation. A factory method, for example, can invoke aggregate constructor (and wire up the aggregate with child domain objects as well) and also register an event.

Publishing events from the application layer is not an anti-pattern per se. Application services can depend from the domain events publisher, the important thing is that it's not application layer to decide which event to send

To summarize, with a stack like Java Spring Boot and domain events support, your code could look like

public class MyAggregate extends AbstractAggregateRoot {
    public static MyAggregate create() {
        MyAggregate created = new MyAggregate();
        created.registerEvent(new MyAggregateCreated());
        return created;
    }
}

public class MyApplicationService {
    @Autowired private MyAggregateRepository repository;

    public void createAnAggregate() {
        repository.save(MyAggregate.create());
    }
}

notice that event publishing happens automagically after calling repository.save(). The downside here is that, when you use db-generated identifiers, aggregate id is not avaliable in the event payload since it's associated after persisting the aggregate. If i will change the application service code like that:

public class MyApplicationService {
    @Autowired private MyAggregateRepository repository;
    @Autowired private ApplicationEventPublisher publisher;


    public void createAnAggregate() {
        repository.save(MyAggregate.create()).domainEvents().forEach(evt -> {
            publisher.publish(evt);
        });
    }
}

Application layer is in charge to decide what to do to fulfill this workflow (create an aggregate, persist it and send some event) but all the steps happen transparently. I can add a new property to the aggregate root, change DBMS or change event contract, this won't change these lines of code. Application layer decides what to do and domain layer decides how to do it. Factories are part of the domain layer, events are a transient part of the aggregate state and the publishing part is transparent from domain standpoint

Archiplasm answered 26/12, 2020 at 23:44 Comment(0)
M
2

Check out this question! Is it safe to publish Domain Event before persisting the Aggregate?. However, I thought it would be okey to raise the event in the application layer but it is an anti-pattern (the domain events should live only in the domain). - Domain events live in Domain layer, but Application layer references Domain layer and can easily emit domain events.

Moreland answered 7/11, 2020 at 18:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.