Say I have a "Directory" bounded context with 2 aggregate roots. Company and Person. Company has a collection of child entities "Position" that hold the IDs of a person aggregate with some extra value data.
All good.
Now we go and add a "Article" bounded context with an aggregate root JobAriticle. This needs a Contact value object which is mapped from a company position.
So knowing that you should only reference aggregate roots what should I do? Assume there are invariants on the Company to Position relationship so I don't want to split the aggregate. Is it OK to map a Position through the anti corruption layer with both the company and position ids? Or do I need to try and break apart the company aggregate.
If Position
is a meaningful concept in the Ubiquitious Language of the "Article" bounded context then Position
should be either a ValueObject or Entity in the "Article" bounded context.
If you're saying that Contact
is the meaningful concept in the "Article" bounded context, but that it needs to somehow correlate with a Position
in the "Directory" bounded context, then you need to think about what is the purpose of that correlation:
JobArticle
?Position
and a Contact
?If you need to verify that a Position
exists before creating an associated Contact, then implicitly Position plays a role in the responsibilities of the Article context - so I would be tempted to create a new Position
entity in the Article context and keep it in sync.
Either way, to correlate something in the Article context with a corresponding entity in the Directory context, you could create a ValueObject in the "Article" context called PositionCorrelation
which would have two properties:
The rule that aggregates should only reference other aggregate roots doesn't mean that you can't also provide information with which to identify entities within the aggregate. It just means that if you want to interract with the other entity, you should do it via the aggregate root, which means you must at least have the aggregate root Id. If you then use a local Id to ask the Company to do something to one of it's positions, that's fine.
But - be aware, that by following this approach, you are introducing the term "Position" into the "Article" bounded context, which may introduce a name collision if the word "Position" means something else in the "Article" context - e.g. perhaps it means the position within an article (paragraph number etc.). If this is the case, you need to think carefully about what to call the cross-context identifier.
One approach could be that if Position
has a one to one map with Contact
, then you could have your two properties be:
And when keeping in sync at the Anti-Corruption layer (ACL) when integrating between the contexts, define CompanyContactId and PositionId (local within Company) values as being synonomous. This keeps each UL internally consistent and defines the correlation between the two in an ACL.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With