domain-driven-designbounded-contexts

Domain Driven Design how to connect two contexts?


How do you connect one bounded context with another one?

For example I have a Cart context and Product context, and when I add a product to the cart first I want to check if the product even exists so my question is how do you connect contexts in a monolith project?

DISCLAIMER
I know that in microservice architecture you can request certain API endpoint to recover that exact object you need and map it to value object. But what to do in a monolith? Create a bridge class or create a database repository which will retrieve value object from certain table of the database?

I'm looking forward to your ideas, thanks for help.


Solution

  • There're at least 2 different ways to manage this.

    Data cloning between contexts

    In this solution you work with multiple similar tables for each context, where data is partially copied between each context.

    Hence, to support your request, you have to maintain a copy of the Product data in the context that you use for the Cart. To support this you can use:

    1. with an event handler, each time something change in the Product context you update the Cart context .
    2. a timed job that clones the information from one context to the other
    3. a mix of the two
    4. others solutions...

    Anyway, whatever you choose, the most important thing is that you MUST accept the concept of eventually consistency: you always work with stale data (maybe just some seconds old, but it's anyway stale), hence you have to manage the problems that could arise due to this. For example, what would you do if your Product in the Cart context contains an item that isn't anymore in the warehouse?

    You can (must...) implement this support code in the infrastructure layer of each context, hence you leave all the other layers unaware of what is going on with the data that they manage. At the end this solution is similar to have a bunch of microservices, just everything is build in a single big project.

    Note: this would be the purist solution, each bounded context is separated from the other, even if they are all build together in a single project.

    Reuse of persistence object (db tables) in several contexts

    I put the hands in from before writing anything: this solution is possible, but only if you really have great control of each aspect of you project. Some would scream that is an aberration, others would say that in the real world you have always to accept compromises.

    With this preamble, I explain what I mean: instead of having several (almost) clones of a table in each context where its data is used, with a (lot, maybe) of code to support this, the original table is directly used in several contexts. Hence, whenever you need a Product within the Cart context, while you still access it with the implementation of the Product repository that comes from that context (the Cart context), in reality you take the data always from the same table.

    This has its own drawbacks: it could be that a context requires extra data, hence the table should be extended (polluted, someone would say), with extra fields; every change in the table could require to check the code that use it, because the table is shared.

    But, a lot of extra code that should be written to manage the clones goes away. And, my opinion, in a controlled context, with a monolith project, with the code anyway build together, is a big plus compared to the extra work required by the first solution. Moreover, when the code that accesses the tables is deeply tested (no test, no gain), some problems are also simpler to manage.


    Note (personal experience): I use the second solution. We have a big monolith, with a lot of tables wich data is shared between several context. The process to clone the data for each context was not viable: too much time just for this, without considering all the fallback situations. Sharing the tables was much faster, and let to develop nice split bounded contexts. I don't use the JPA (Java ORM) so I control the SQL code that loads the domain entities. Everything about the persistence access is tested, so whenever something changes, I get reported immediately.