RE: Re: When and where to raise AggregateRootAddedEvent
Mauro Servienti <[email protected]>
| Newsgroups | gmane.comp.programming.domain-driven-design |
|---|---|
| Message-ID | <0D71C042265E7B4D871B59569C7774D75E098F8C@AMXPRD0310MB390.eurprd03.prod.outlook.com> |
We use the following approach and we are quite happy, no issues at all.
C# code
using( var repository = repositoryFactory.OpenSession() )
{
var aggregate = repository.Get<MyAggregate>( aggregate-id );
aggregate.DoSomethingInteresting();
repository.CommitChanges();
}
At "CommitChanges" stuff is saved to the storage and events raised by the aggregate are propagated to the infrastructure by the repository, within a transaction boundary.
.m
From: [email protected] [mailto:[email protected]] On Behalf Of Johan Haleby
Sent: martedì 25 giugno 2013 07.52
To: [email protected]
Subject: Re: [domaindrivendesign] Re: When and where to raise AggregateRootAddedEvent
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]<mailto:[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]<mailto:domaindrivendesign%40yahoogroups.com>, Wim van Gool <vangool.w@...<mailto: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?
>