silverfighter
silverfighter

Reputation: 6882

Event Sourcing organization of streams and Aggregates

what would be the best way to organize my event streams in ES. With event stream I mean all events to an aggregate.

Given I have a project with some data and a list of tasks.

Right now I have a Guid as AggregateID as my streamID. So far I can -> recreate the state for a given project with that ID -> I can assemble a list of projects with a custom projection

The question would be how to handle todos? should this also be handled below the project stream id or should it have it's own todo stream id?

If a todo has it's separate stream how would one link it to the owning project. How is the project aware of all the todo streams for a given project. Meaning all changes to the todo list should be also recognized as Commands and Events (more Events) in the project.

And if I also want to allow free todo's without a relation to a project. Does it require to have its own type and stream to handle freeTodo on top. And the list of all todos whether project related or not would be a projection of all todo and freeTodo related streams?

So I guess the main question is how do I handle nested aggregates and how would one define the event store streams and the linking for that?

Any tips, tricks, best practises or resources will be highly appreciated.

// EDIT Update

First of all thank you @VoiceOfUnreason for taken your time to answer this question in great detail. I added the tag DDD because I got that strange feeling it correlates with the bounded context question which is most of the times no black or white decision. Obviously the domain has more depth and details, I simplified the exampled. Down below I shared some more details which got me questioning.

In my first thought I defined an aggregate for todo as well with a property for the project id. I defined this project property as option type (Nullable) to cover the difference between project related and free todo's. But following use cases/ business rules got me rethinking.

c) Have some sort of service which provides todo infos for project validation which somehow refers to point a.).

And all feels really coupled =-/

It would be great if you or someone finds the time to share some more details and opinions here. Thanks a million.

Upvotes: 1

Views: 777

Answers (1)

VoiceOfUnreason
VoiceOfUnreason

Reputation: 57214

Reminder: the tactical patterns in are primarily an enumeration of OO best practices. If it's a bad idea in OO, it's probably a bad idea in DDD.

the main question is how do I handle nested aggregates

You redesign your model.

Nested aggregates are an indication that you've completely lost the plot; aggregate boundaries should never overlap. Overlapping boundaries are analogous to an encapsulation violation.

If a todo has it's separate stream how would one link it to the owning project.

The most likely answer is that the Todo would have a projectId property, the value of which usually points to a project elsewhere in the system.

How is the project aware of all the todo streams for a given project.

It isn't. You can build read models that compose the history of a project and the history of the todos to produce a single read-only structure, but the project aggregate -- which is responsible for insuring the integrity of the state within the boundary -- doesn't get to look inside the todo objects.

Meaning all changes to the todo list should be also recognized as Commands and Events (more Events) in the project.

No, if they are separate aggregates, then the events are completely separate.

Under some circumstances, you might use the values written in an event produced by the todo as arguments in a command dispatched to the project, or vice versa, but you need to think of them as separate things having a conversation that may, or may not, ever come to agreement.

Possibilities: it might be that free standing todo items are really a different thing from the todo items associated with a project. Check with your domain experts -- they may have separate terms in the ubiquitous language, or in discussing the details you may discover that they should have different terms in the UL.

Alternatively, todo's can be separate aggregates, and the business adapts to accept the fact that sometimes the state of project and the state of the todo don't agree. Instead of trying to prevent the model from entering a state where the aggregates disagree, you detect the discrepancy and mitigate the problem as necessary.

Upvotes: 7

Related Questions