Search code examples
domain-driven-designddd-repositories

How to implement references beetwen aggregates in ddd?


In ddd an entity can reference entities of the same aggregate, or another aggregate root (but not entities inside another aggregate).

  1. How would such a reference be implemented?
  2. How would a method of the entity get access to the referenced aggregate root?
  3. What is the method of the entity allowed to do with the other aggregate root?

For 1. and 2. my problem is, that an entity should not have access to repositories. Also magic lazy load mechanisms are not always available and I think should be avoided for the same reasons. So when the aggregate is loaded by the repository, should all references of every entity in it be resolved (and all referenced other aggregates be loaded) by the repository? Or is the "reference" just an id and someone outside the entity (the commandhandler or whoever loads the aggregate from the repository and invokes a method) uses this id to load the other aggregate too and gives it then into the method as a parameter as in the following example?

agg1 = repo1.Load(id);
agg2 = repo2.Load(agg1.refId);
agg1.mymethod(agg2);

For 3. I think the only methods that should be called on the other aggregate would be query methods (in the cqs sense) that do not alter the other aggregate because only one aggregate per transaction should be changed. Right?


Solution

  • As for questions 1. and 2. what you said is fine and most of the time it's done that way. You reference other aggregate by ids and retrieve them outside of domain logic, in application service. Reason why you should not load other aggregates in aggregates (except for SRP violation) is that you have no control of what is going on, same with lazy loading. You can easly make code that will load the same aggregate from DB dozen of times when it could be loaded once. You can use cache, but there will be also problem with stale data etc.

    However, sometimes, you need to do "Performance Driven Design" over "DDD", and then you load aggregates in another aggregates, but it is rare.

    For your answer to 3. In Query from CQRS you don't even use repositories, nor aggregates, because you just want to get data, no domain logic is involved there.