Re: Re: When and where to raise AggregateRootAddedEvent
Johan Haleby <[email protected]>
| Newsgroups | gmane.comp.programming.domain-driven-design |
|---|---|
| Message-ID | <CAK3tncKt6B9bUCYRB_7sYvjZoNnyKJS2UESt+CVsLpc60EVU1A@mail.gmail.com> |
I think one interesting approach is to return events from your aggregates instead of publishing them as described by this blog<http://www.jayway.com/2013/06/20/dont-publish-domain-events-return-them/> . Regards, /Johan On Mon, Jun 24, 2013 at 9:35 PM, Moran Lefler <[email protected]> wrote: > ** > > > The point that you are raising bugs me as well. > I see it as a more general concern, since the same question can be asked > about any change of state within the domain model - Do we raise the domain > event as soon as the model changes, or only when the change is actually > committed to the store? As you mention, triggering the event from the > domain model may cause other handlers to act upon that knowledge, querying > stale data from the db, and even may in turn trigger other events and so on > - think of all the compensation logic that have to rollback all of that > action, in case of a e.g. a transaction failure. > > I would very much like to hear the group's opinion on that matter. > > Cheers, > Moran > > > --- In [email protected], Wim van Gool <vangool.w@...> > wrote: > > > > 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? > > > > >