When and where to raise AggregateRootAddedEvent

Wim van Gool <[email protected]>
Newsgroups gmane.comp.programming.domain-driven-design
Message-ID <CAKqMafy3eg2tTbkg3w6YOx0EV9aRG1H3TidM9p3YB+_tdzG-CQ@mail.gmail.com>
While implementing my example DDD-project, there's one thing that's still
not very clear to me at this point, mainly because I see so many samples
and advise that contradict each other or sometimes raise more questions
than they answer. Yet, ironically, it's actually core to implementing a
DDD-application, IMHO.

Suppose I must add/create a new aggregate, what thing is responsible for
raising the *NewAggregateAddedEvent*, and when to raise it? Note that I'm
not applying event-sourcing; I just use plain state-based aggregates and
repositories.

*Option 1: Let your ApplicationService/MessageHandler take care of it*
One way of doing this is the most simple thing, something like this:

public sealed class AddNewCarHandler : IMessageHandler<AddNewCarCommand>
{
    private readonly ICarRepository _repository;

    ....

    public void Handle(AddNewCarCommand command)
    {
         // Create the new Car somehow
         Car newCar = _carFactory.AssembleNewCar(...);

         _repository.Add(newCar);

         DomainEventBus.Publish(new ...());
    }
}

This is the way I have been doing it so far. The advantage of doing it this
way is that it's pretty straightforward and simple. The downside is that I
now my application-layer is raising domain events, which is not something
that it's 'supposed to do' I guess. That's why I'm questioning this
approach.

*Option 2: Let your factory-method publish the event*
This is the way Vaughn Vernon explains it is his book (paragraph on
creating Discussion instances), which basically means that, in my own
example, method AssembleNewCar() would call DomainEventBus.Publish(..)
inside before returning.

The advantage of doing it this way is that domain events are only raised
inside the domain, but there's a caveat that I see here: the domain event
is now raised *before* the aggregate (Car in this case) is actually added
to the repository. If you have hooked up any handlers that get invoked
within the same transaction, they might expect the new aggregate to be
present in the repository and attempt to retrieve it. If having such
handlers in the first place is a smell in itself I'd like to here this
though... Moreover, this problem could be tackled by attaching the newly
created aggregate to the created event, but I'd like to avoid this if
possible and only communicate using id's where I can.

*Option 3: Create a domain-service.*
Another option that tackles both 'problems' of the two above is to create a
separate domain service like AddNewCarService to your domain and let the
application-service basically delegate it's work to this service - with the
exception of translating the command to appropriate domain-values/objects
of course. Needless to say, this does require extra domain services to be
created for the sole purpose of adding new aggregates, which I haven't seen
much in code samples and so makes me think this is not a typical
(desirable?) way of doing things.

So, how are you guys doing this?
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.