CQRS how to create a new record in multiple bounded contexts - domain-driven-design

How to create a new record (for example product) when the product exists in multiple bounded contexts and the client enters all the data for the product at once?

You need to have one bounded context that owns the product, probably amongst other bits of the model. This bounded context becomes the "system of record", this is important in the scenario in which data is inconsistent/corrupted in one of the other bounded contexts.
When a product is created/updated/deleted, that bounded context can emit an event that the other bounded contexts use to create their own representation of a product.
I would suggest you to get a copy of Implementing Domain-Driven Design. It's a great book and does explains similar scenarios.

Related

Bounded context and sharing business logic (DDD)

We are trying to apply DDD at work, and i'm confused with the way they defined bounded contexts.
They are defining bounded contexts as stakeholders, so in our case we have Customer,Seller, Admin, Sales.
Their argument is, each bounded context has one reason to change (reason as person or a group and thus stakeholders).
The problem is we are duplicating business rules since our bounded contexts are loosely coupled.
So let's say we have a refund use case, Sellers can refund their customers while Admins can refund any customers on behalf of the Seller.
The way we defined our bounded contexts, we are now duplicating the refund business rules.
I don't have a better approach of dealing with this, i'm new to DDD, would like to have some help/clarifications on:
Are bounded contexts supposed to be stakeholders ?
Is business rules duplication an indication of bad design ?
How can we model our bounded contexts to better design Admin refund / Seller refund use cases ?
P.S: it's a monolith app
I'm no DDD-guru but I have some experience with it so I'll give it a shot.
A bounded context is just what the name suggests, a context which is bounded, to a specific domain. It has a specific well-defined language and is designed for specific tasks. It often have aggregates of de-normalized state representing use-cases.
A bounded context in your case may be "RefundHandling" or something like that, with aggregates for perhaps "SellerRefundProcess", and entities or just values for "Seller" etc depending on each use-case.
Bounded contexts should be loosely coupled as you write. That's a big reason for dividing a complex domains into more specific domains focusing on specific tasks/use-cases. But if you have business rules you have to share between these domains, then yes perhaps they are not so different after all. Perhaps your domain could be divided in other ways, if any.
An easier approach would be to share the common rules you have with shared kernel assembly. Not as clean but sometimes it's unavoidable.
Just some thoughts and ideas, for what it's worth.

Why do I need different bounded contexts

I've read that the reason to split the application in different bounded contexts is because of the ubiquitous Language and also to split big entities. For example, I can have a Product entity with logic for Support and Sales and I can split the model into two Product models in different bounded contexts - Support and Sales bounded contexts, but I can also just create two different entities SupportProduct and SalesProduct and achieve the same result? So why also do I need different bounded contexts?
Bounded contexts don't really have anything to do with the application or code, they're for problem decomposition and a means of recording the fact that sales domain experts and support domain experts mean different things when they talk about a product entails.
So SupportProduct and SalesProduct are valid encodings of the fact that "product" exists in two different bounded contexts; you might choose this encoding if you're aiming for a more monolithic implementation in a language which doesn't support modules/packages/namespaces (in a language which does have such support you might have something like sales.Product and support.Product).
Bounded contexts don't imply anything about code structure, or deployment into different (possibly micro-)services, although that decomposition does suggest some natural seams with which to structure code/deployment.

DDD - Multiple Bounded Contexts because of differing aggregate data?

We try to split up our domain into bounded contexts with the goal to have a modular application design/architecture.
We did an enlightening EventSorming session which helped us a lot to identify bounded contexts and its aggregates. After the workshop every participant agreed on the bounded contexts we identified.
Nevertheless we feel uncomfortable as we fear our bounded contexts are still too large. EventStomring focusses on the domain events / process and that's the major building block we used to identify our bounded contexts.
We also identified aggregates like "Contract". Every contract nearly follows the same process, but the amount of data these contracts contain can differ massively. There are very simple contract types and contract types which include a lot of additional data and attachments.
Is it meaningful to declare another bounded context just because the aggregate's data is more complex?
Both approaches have their drawbacks:
Implementing all contract types in one bounded context might lead to a lot of if-Statements in the code in order to handle the differing data.
Extracting a new bounded context might lead to a lot of duplicate code just because some data differs.
Any suggestions / best practices how to handle this?
...domain events / process and that's the major building block we used
to identify our bounded contexts
BCs are not identified by processes, BCs are related to the language. Each BC has its own ubiquitous language (UL). A BC is the context in which a concept has meaning. Anyway BCs belong to the solution space. First of all you should explore the domain (problem space) and split it in subdomains, distilling the core domain. Then you model each subdomain. A BC is the context where a model lives. Ideally the relationship between subdomains and BCs is 1:1.
The process of discovering subdomains is iterative, and you will find them as you know the domain better, talking to experts. When you find a word that may have different meanings, or when two different words have the same meaning, then it means that you are crossing a boundary between BCs.
So, subdomains identification is not about processes, but about concepts and UL.
Is it meaningful to declare another bounded context just because the
aggregate's data is more complex?
No, you shouldn't create BCs arbitrary just because aggregates are complex. BCs are based on the UL.
Any suggestions / best practices how to handle this?
You should learn more about the domain (contract, types, etc) by talking to domain experts, and study your aggregate (transactional consistency)... Anyway, if you split your aggregate into anothers, it doesn't mean that they belong to different BCs, they still can belong to the same BC. A BC can have more than one aggreagate. It all depends on your concrete domain.
Bounded contexts have little to do with if-statements, so I'm not sure what you mean.
Bounded contexts are a semantically closed set of business functionalities. Basically your bounded context is well defined if it can execute its functions in complete isolation, even if the other contexts are not available.
Other than that, you can have any design inside of the context. I feel the amount of if-statements depends more on your class/code-design, like whether you use polymorphism correctly, interfaces, things like that.
But, to your point: You don't need to have everything perfect the first time. If you identified some valid contexts, you already did the hard part. If any context can be further divided, that could happen later anytime with little impact on others (since contexts are more or less isolated).
No specific business teams for different kinds of contracts
No dedicated dev team for specific kinds of contracts
Same ubiquitous language is used for all contracts
Every contract nearly follows the same process
These to me are signs that all contracts belong to the same business subdomain and should ideally be in the same Bounded Context - unless legacy or third party systems force you otherwise.

Breaking application to bounded contexts

How do you plan and divide your application into bounded contexts? On the one hand it's very handy having all this decoupling, but on the other hand too much granularity can lead to a very cumbersome development. Where is this thin line? What factors do you take under consideration when designing your bounded contexts and context maps? Are they technical, strategic maybe?
In a lot of examples you see e-commerce app as a set of bounded contexts: catalog, shopping, invoicing, delivery etc.
Where are those coming from?
Technical, definitely not...
Did you heard about Event Storming ? I think it is a good way to found your boundaries...
Bounded context is about language, it is not technical or architectural think, but more about your domain and the words used by your Domain Expert : Greg Young explain-it well in the beginning of this talk
When you are modelling your Domain Model, you have to define your boundaries (for eCommerce, Product is not the same concept with the same attributes in different contexts : catalog, shopping... The same thing about customer... And you don't have to use the same entity for each context, so every context have its specific Ubiguitous language), think about this activity iteratively (sometime Bounded Contexts emerge and are not clearly visible first)
As soon as you use both same words to define distinct concepts, you are faced to both bounded contexts.
Suppose an application dealing with movies rental.
If your team (business/developers) talk about "Users" to define users in terms of identity and access, and "Users" too to in terms of Renters, then you would have both bounded context:
IdentityAndAccessContext (managing authentication, roles etc.. technical)
MovieRentalContext (unaware of Users, but Renters)
Bounded context is the reflection of the chosen ubiquitous language.
For modeling domain from scratch I think is good decision to start from one bounded context and one module. Than concepts start to conflict or look strange keeped in one module, it's time to separate some concepts into distinct module (or reorganize between modules).
Same approach for separating modules into distinct bounded contexts.

Bounded context find the boundary?

In my current project (e-commerce website), we have different Bounded Context like: billing, delivery or payment in our checkout process.
On top of this, depending on what the customer will buy, the checkout process will be different. So depending on the content of her cart the number of steps in the checkout process can be different, or we won't/will ask her for certain informations.
So should one create a different bounded context for each different type of checkout process ?
For example, the Order aggregate root will be different depending on the checkout process
EticketsOrder (in this context we don't need a delivery address so we won't ask one to the user)
Ticket BillingAddress
ClothesOrder (in this context we need a delivery address and there will be an additional step in the checkout process to get this)
Clothes BillingAddress DeliveryAddress
This separation will imply to create two different domain entities even thought they have similar properties.
What's the best way to model this kind of problem ? How to find the context boundary ?
A bounded context is chiefly a linguistic boundary. A quote from the blue book (highlighted key part):
A BOUNDED CONTEXT delimits the applicability of a particular model so
that team members have a clear and shared understanding of what has
to be consistent and how it relates to other CONTEXTS. Within that
CONTEXT, work to keep the model logically unified, but do not worry
about applicability outside those bounds. In other CONTEXTS, other
models apply, with differences in terminology, in concepts and rules,
and in dialects of the UBIQUITOUS LANGUAGE.
A question to ask is whether the different types of orders created are entirely distinct aggregates, or are they all order aggregates with different values. Is there a need to consider order as a whole regardless of how they were created? I've build and worked with ecommerce systems where different types of orders were all modeled as instances of the same aggregate, just with different settings and there were no linguistic issues. On the other hand, the orders in your domain may be different enough to warrant distinct contexts.
I often consider BC boundaries from the perspective of functional cohesion. If you segregate orders into two BCs will there be a high degree of coupling between them? If so, that may be a sign that they should be combined into one BC. On the other hand, if the only place that the BCs interact is for reporting purposes, there is no need to combined them.
It appears as though you may have missed a bounded context. When this happens one tends to try and fit the functionality into an existing BC. The same thing happens to aggregate roots. If something seems clumsy or it doesn't make sense try to see whether you haven't missed something.
In your example I would suggest a Shopping BC (or whatever name makes sense). You are trying to fit your checkout process into your Order BC. Your Shopping BC would be responsible for gathering all the data and then shuttling it along to the relevant parts.
The product type selected will determine whether a physical delivery is required.
Hope that helps.

Resources