Reputation: 4515
Is it ok for a member entity of an aggregate root to point toward the root entity (not the other way around) ?
Suppose I have Population AR (where the Population is the root entity, and PopulationMembership is one of the member entities).
I'm evaluating the direction of the association between Population and PopulationMembership. There is another entity at the other end, Person (an AR of its own, and PopulationMembership has a reference to Person).
In the ER (database) world, we would normally make an association pointing from PopulationMembership toward Population (population_membership being the connecting table in many-to-many relationship between Population and Person).
But I think in DDD world, I should break that habit, and make the association to point from Population (in the conceptual model) toward PopulationMembership instead.
Anyway, before that, I'd like to confirm if (in some other situation maybe) we are allowed to have association from member entity toward root entity.
Any thoughts?
Upvotes: 1
Views: 561
Reputation: 771
Ok, let's split this question into two parts:
Let's start from 1:
No, generally child entities should not hold reference to aggregate roots. Aggregate root is the entry point to the entire aggregate and must maintain its consistency boundaries. This means, that every change to the aggregate must be forwarded through the root entity (in oop by calling methods of root entity). Aggregate root can return references to child entities, but they must be transient. Also, client should not perform changes to child entities outside of aggregate root - otherwise consistency can be violated. Having that in mind, I don't really see a reason for child entities to hold references to their root (from the client's perspective - you already have access to the root, don't you?). The only exception I see right now, is when you need to translate the model to some specific needs (e.g. presentation layer requires root entity id to produce meaningful JSON output). However, even in such case you would probably create a separate read model or provide specialized assemblers to build required DTOs.
Ok, now to the second point:
It seems you are trying to model your domain entities the same way you would build your database model. In DDD, we should focus first on business requirements and behavior of our model. Data relations are not so important when building a meaningful domain model (we refine that a bit later). So, first of all you should focus on collecting business case scenarios from your domain experts. Aggregates should be build upon real business invariants. You should create a common model together with your team (including business members). It's very probable that your design will look completely different after several knowledge crunching sessions. Maybe Person is not really an aggregate root but simply a value object? Maybe you don't even need PopulationMembership entity? The most common design for aggregates, is just a single (root) entity with multiple value objects. Besides of that - I often create completely separate database model, almost without connection (except of id) to the domain model. I use a translation layer (mapper components) to convert between domain<->dbmodel. In my recent project, my db model was extremely different from the domain layer (it was adjusted specifically to the needs of the persistence layer - so, for instance a lot of flat properties were used - not full objects but simple primitive values). In case of relational db you might even provide bidirectional relation explicitly (in fact, you don't even need to use any orm). There are a lot of advantages in separating your db model from domain model. The design is definitely more supple. However, the mapping cost (developer work) between db <-> domain layer can be too huge for simple projects. In such case, I usually start with common model and then refactor to separable layers.
Oh, another important thing - it's generally a good idea to refer to other aggregate roots by id only. This way, you don't have a problem with complex object graph and you don't need to worry about modifying other aggregates within a single transaction (the aggregate root should not modify other roots). If you need to communicate between aggregates - use events instead.
Please, refer to the great series of articles by Vaughn Vernon:
http://dddcommunity.org/library/vernon_2011/
I think these articles can help you to understand the aggregate modeling concepts.
Upvotes: 1