14

When following Domain-driven design (DDD), is it correct for a root aggregate to hold a reference to an internal entity that happens to be the root entity on a separate aggregate?

I believe this is not correct, mainly because of this rule on the blue book:

Nothing outside the AGGREGATE boundary can hold a reference to anything inside, except to the root ENTITY. The root ENTITY can hand references to the internal ENTITIES to other objects, but those objects can use them only transiently, and they may not hold on to the reference. The root may hand a copy of a VALUE OBJECT to another object, and it doesn't matter what happens to it, because it's just a VALUE and no longer will have any association with the AGGREGATE.

If a root aggregate holds a reference to another root aggregate the boundary of the former is violated and the whole concept of an aggregate is corrupted, so I believe if a root aggregate looks like needing to hold a reference to another root aggregate, then I need to create a different entity, that will probably share some of the same members as the other root entity, but will not have a global identity, as this other rule in the book states:

Root ENTITIES have global identity. ENTITIES inside the boundary have local identity, unique only within the AGGREGATE.

I believe this would be the correct way to go, but since it feels repetitive and redundant (when taken off the context of DDD, with pure OOP) I am asking for some feedback.

  • What do you mean by "internal entity (that happens to be the root entity on a separate aggregate)"? – Erik Eidt Aug 17 '16 at 1:01
  • 2
    FWIW, Anything may refer to an aggregate root entity as these are the things having global identity; whether the referrer is itself a root entity or not is immaterial. – Erik Eidt Aug 17 '16 at 1:15
  • As Erik said. Also, it doesn't matter if you reference it using ID or reference in your model. It both will convert to ID on the DB level and having a reference gives ORM ability to lazy-load the entity on demand. – Euphoric Aug 17 '16 at 12:19
20

You might be overinterpreting the book. It basically says : anything outside an Aggregate cannot hold a reference to anything inside it except the root. Therefore, holding a reference to a root is legit. Holding a reference to a root doesn't mean it's part of your own aggregate and that you can control its invariants. It keeps its own invariants and autonomy.

However,

  • A commonly accepted good practice is to refer to an AR by storing its ID, not a full reference.
  • More modern approaches to aggregate design (see the Red Book) advocate a cleaner separation between Aggregates. A business transaction should only change the state of a single Aggregate. Under this assumption, the need to store a reference to another Aggregate tends to disappear because you're not going to modify 2 aggregates at the same time.

is it correct for a root aggregate to hold a reference to an internal entity that happens to be the root entity on a separate aggregate?

This never happens. A Value Object can be part of multiple Aggregates, but not an Entity. The reason is, nothing would then prevent you from sharing the same entity instance between Aggregates. Let's say that entity instance E belongs to both aggregate instances A and B. Since the premise of DDD is that the Aggregate is the entry point, you would be able to load A, modify entity E through it, all the while silently violating invariants from B (that you didn't load).

See the answer from Greg Young here : http://domain-driven-design.3010926.n2.nabble.com/Can-an-Entity-be-Shared-across-many-Aggregates-td7579277.html

  • Thank you Guillaume for the clear, concise and insightful answer. True DDD connoisseur's savoir-faire. This is what I was looking for. Chapeau! – Lesair Valmont Aug 17 '16 at 23:49
  • I know it may be a silly question, But could I ask what's the meaning of holding a reference in this context ? because I confused when you said that : holding a reference to a root is legit then after that you said:This never happens. A Value Object can be part of multiple Aggregates, but not an Entity. The reason is, nothing would then prevent you from sharing the same entity instance between Aggregates. – Anyname Donotcare Aug 31 '18 at 10:52
  • 1
    Hold a reference = keep it internally/durably, as a member of the class. The dichotomy here is root vs non-root. You can hold on to a root reference but not a non-root reference. – guillaume31 Aug 31 '18 at 11:05
  • @guillaume31 thanks a lot, but Could I ask if Is it okay to keep an id of internal entity(not-root) in to another aggregate or this violates whether (root or not) ? – Anyname Donotcare Sep 3 '18 at 19:08
  • What would you do with that ID? Even repositories only give you roots, not internal entities. – guillaume31 Sep 3 '18 at 20:18
1

Your aggregate root object should (generally) only have properties which are part of its domain.

If you have an AR object with a property which is not in the aggregate then you are immediately faced with the question. 'Why not?'

You could add the Id of the other object perhaps? Or inject a repository?

But it sounds like you should add a cross domain service which references both root objects and performs the required logic

  • Ewan, I was thinking more of reusing a class between two different aggregations in the sense of OOP, rather than having a domain service acting as a business script that will be doing some work with the two different DDD aggregates. In conclusion I concur with you, my aggregate root should only have properties which are part of its domain. – Lesair Valmont Aug 17 '16 at 23:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.