Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDDD: Event data

I'm trying to get my head around DDDD in Greg Young's style.

There is much talk about how to implement DDDD with CQRS+EventSourcing and there are some sample implementations ... and altogether it can be quite confusing...

In Gregs view aggregates don't have getters or setters - just state-changing methods which emit an corresponding event.

Basicly a event decribes a state-transitions that happend in the past. It's data describes what changed.

Some say, that this data can be "enriched" by additional data.
Where can this additional data come from?

i.e. I have User and Usergroup - both aggregate roots (can exist independently, have identity). User has a method called AddToUsergroup.

public class User : AggregateRoot
{
    // ...
    public void AddToUsergroup(Usergroup usergroup)
    {
        // validate state
        RaiseEvent(new UserJoinedUsergroup(this.Id, usergroup.Id));
    }
    // ...
}

public class Usergroup : AggregateRoot
{
    private string _displayName;
    // ...
    public void ChangeDisplayName(string displayName)
    {
        // validate state
        RaiseEvent(new DisplayNameChanged(this.Id, displayName));
    }
    public void Apply(DisplayNameChanged e)
    {
        this._displayName = e.DisplayName;
    }
    // ...
}

If I would like to "enrich" the event with the name of the Usergroup (for debug reasons or something like this), how would I do that?

  • getters are nonexistent
  • internal state of usergroup is inaccessible

Injecting such things as repositories into User is not allowed (am I right here?!?), like

  • Read-side repository
  • Event-store repository

Bottomline questions:

  • Can Should something like repositories be injected to aggregate roots?
  • Should a event only use data available through parameters and internal state of the aggregate?
  • Should events only contain the minimum data describing the state-change?

And (little off-topic but the sample is here)

  • Should AddToUsergroup take an Guid instead of an full aggregate root?

Looking forward to your answers!

Lg
warappa

like image 331
David Rettenbacher Avatar asked Apr 23 '13 11:04

David Rettenbacher


People also ask

What is an event DDD?

A Domain Event is an event that is spawned from this model that is a result of a decision within the domain. Within the model our Aggregates have the role of maintaining business rules and this is where we implement decision points in our model, so the Aggregates are also responsible for creating the Domain Events.

What are domain events used for?

A domain event is, something that happened in the domain that you want other parts of the same domain (in-process) to be aware of. The notified parts usually react somehow to the events. An important benefit of domain events is that side effects can be expressed explicitly.

What is DDD in database?

Domain-Driven Design(DDD) is a collection of principles and patterns that help developers craft elegant object systems. Properly applied it can lead to software abstractions called domain models. These models encapsulate complex business logic, closing the gap between business reality and code.

What is aggregate in event sourcing?

An aggregate is a cluster of associated objects that we treat as a unit for the purpose of data changes. Each aggregate has a root and a boundary. The boundary defines what is inside the aggregate. The root is a single, specific entity contained in the aggregate.


1 Answers

Should something like repositories be injected to aggregate roots?

No and there is no need to in this case. It can be appropriate to pass a domain service to a behavioral method on an aggregate, but again, not needed in this case.

Should a event only use data available through parameters and internal state of the aggregate?

Yes, the original domain event should be such that it can be easily built by the aggregate and can be replayed in a deterministic fashion.

Should events only contain the minimum data describing the state-change?

Yes. However, to address requirements of external subscribers, this is where content enricher comes into play. To dispatch a domain event externally, it is first committed to the event store then you can dispatch in the same tx or have an out of process mechanism which publishes events externally. At the point of publishing externally, you will normally use a different contract for the message since subscribers may need more than what is on the domain event itself. In this case, you need the user group name. The publisher, then, can pull up the user group name and place that data into the enriched event. This publisher can have access to a read-model repository for user groups which would allow it to retrieve the name.

Should AddToUsergroup take an Guid instead of an full aggregate root?

Yes. Passing the entire aggregate may not be possible and also creates the illusion that something other than the ID may be used, which should not be the case.

like image 86
eulerfx Avatar answered Sep 17 '22 19:09

eulerfx