Arter Cadelanne
Arter Cadelanne

Reputation: 17

DDD: Choosing aggregate root

In my case I have two main concepts: User (main citizen of the system) and Group. Group has two sub-collections: ranks and roles. Without a group, ranks and roles have no meaning. When User is assigned to the Group, we also have to pick 1 Role and 1 Rank and assign them to this relationship between User and the Group.

Diagram

Question:

How much aggregate roots do I have here? From the user side its obviously a user (main concept of the system), but what about its relationship with group? AFAIK its forbidden by rules of DDD to reference entities outside of aggregate root.

Upvotes: 1

Views: 1598

Answers (3)

Eben Roux
Eben Roux

Reputation: 13256

I'm going to change some of the words and we'll see if it helps (hypothetical):

I have an Order and a Product. When I add a Product to an Order I have to choose a Store and a Colour.

How would you model this?

Colour may very well be a Value Object but Store is not. I would opt for an OrderItem Value Object which contains a Colour Value Object and a StoreId value to capture the relationship. An Order would contain a list of OrderItem entries.

Removing Colour entries is fine since we have denormalized that bit into the OrderItem. We could have another Value Object represent the Store but typically we would not delete the store or have some processing to handle a deletion or, even more typical, use referential integrity constraints to prevent deleting a used Store.

If you consider ever deleting the Order only the OrderItem association is also deleted.

In your case User and Group are probably Aggregate Roots and I'd add a UserGroup (or UserAssignment as Constantin used). The UserGroup contains the association and related bits. You would have to identify the real domain structure though.

Upvotes: 0

Constantin Galbenu
Constantin Galbenu

Reputation: 17683

You have at least the following options, depending on your business requirements regarding consistency:

  1. You have 5 aggregate roots: User, Group, Rank, Role and UserAssignment. The last one must protect the invariant "we also have to pick 1 Role and 1 Rank". For lifetime management you use eventual consistency between ARs. For example, when you delete a Group you must delete also the orphan Ranks, Roles and UserAssignments.

  2. You have User (with UserAssignment as nested entity) and Group (with Role and Rank as nested entities). You have strong consistency inside ARs (when you delete a user all its asignments are also deleted) and eventual consistency between User and Group.

What should you use? Only you could decide. For example, if you choose the first option and delete a user then there could be a delay of seconds/minutes/hours before its assignments are also deleted.

Strong consystency should be used to protect only real business invariants because it is not cheap.

P.S. if you need to hold a reference to a nested entity from another AR then you should reconsider your aggregate roots boundaries because your design is most probable wrong.

Upvotes: 0

Rafael Soares - tuelho
Rafael Soares - tuelho

Reputation: 410

AFAIK its forbidden by rules of DDD to reference entities outside of aggregate root.

Well, I would't say it's "forbidden by rules of DDD"... Some times you have no choice. I have to consider the size of the "entities' collection" associated to the Root's Aggregate. Sometime you can maintain the association in the same aggregation and use some kind of "lazy load" to avoid resource consumption. The Vernon's iDDD book[1] has some advises and use cases around this specific case. Take a look on his blog post[2]

[1] https://www.amazon.com.br/Implementing-Domain-Driven-Design-Vaughn-Vernon/dp/0321834577 [2] https://vaughnvernon.co/?p=838

Upvotes: 0

Related Questions