Reputation: 1443
I have a question regarding what best practice is when it comes to verifying existence of entities across bounded contexts. Is this even a valid approach in DDD? BC are supposed to be self-contained deployments essentially (i.e. you should not depend on another BC possibly being unavailable).
I have 2 BC in my project - Ingredients and Recipes. The business sells bulk ingredients but also pre-configured recipes using said ingredients. Now these are separate BC each with their own ingredient entity.
Recipe is an aggregate root that has a child entity of a list of ingredients. Does it make sense to verify that an ingredient exists in the Ingredient BC before adding it to the list of ingredients in the Recipe BC?
Ingredients can only be modified through the ingredient BC where events will be published and the recipe BC will subscribe and update its own ingredients for any changes (i.e. price/name). In order for this to be valid, the ingredient needs to be a valid one. So how do I maintain consistency between these BC? Do I inject a domain service into the recipe BC and validate ingredient existence before adding them? I am using CQRS as well so I could inject the service directly into the handler instead of a factory for creating Recipes (or would that be the right approach to using domain services?).
Sort of lost on this and if this is a valid concern.
Upvotes: 5
Views: 1856
Reputation: 1210
Feels like you BCs boundaries are wrong. Try to find business capabilities they are performing for your business. Don't map 1 to 1 name of the entity with the name of the Bounded Context. Between aggregates you cant guarantee transnational consistency. Even if you check your ingredient, it may be there, but after 1 ms its gone, and you will continue executing your logic, thinking its in there. I don't see why Ingredient should be a separate BC with Recipe. What value does it give.
Upvotes: 1
Reputation: 28016
Generally speaking, your Recipe should only care about the unique identifier of the Ingredient, and not its details. The details of the Ingredient are not required for the Recipe to be consistent.
I would assume that some action (e.g. a user interacting with a UI) will add ingredients to a recipe. I would also assume that the ingredients that can be added come from a query that only returns valid ingredients. Unless you have reason to be concerned that something/someone is going to subvert this process, you are likely spending time solving a concern that is unlikely to be a real problem.
If this is, in fact, a real concern, then yes, you could validate that the ingredients exists before adding them. However, this would probably be best done near the boundary of the Recipe BC, in a command validator.
A Bounded Context is conceptual--it is (usually) not represented by a single class. I mention this because you ask
Do I inject a domain service into the recipe BC . . . ?
You don't really "inject" into a BC. Again, if you do need this validation, you would likely have a validation class that queries the Ingredient BC via an API or the database to ensure it exists.
the recipe BC will subscribe and update its own ingredients for any changes (i.e. price/name).
This should not be necessary. The recipe has a reference to each of its ingredients, so when you query for a recipe, you query both the list of ingredients and the details of those ingredients. Depending on your setup, this could be a SQL join or something else (there are many different ways this can be done depending on your setup). You should generally avoid caching Ingredient details in the Receipt BC unless you have specific concerns about performance. Caching always adds complexity.
One of the things you will discover as you continue to do CQRS is that a lot of problems you typically think of as "Command Problems" are actually much more easily solved on the query side.
Upvotes: 8