Reputation: 17
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.
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
Reputation: 13256
I'm going to change some of the words and we'll see if it helps (hypothetical):
I have an
Order
and aProduct
. When I add aProduct
to anOrder
I have to choose aStore
and aColour
.
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
Reputation: 17683
You have at least the following options, depending on your business requirements regarding consistency:
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.
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
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