Domain Driven Design - When to seperate one bounded context into two - domain-driven-design

While learning domain driven design, I learnt that we should keep two bounded contexts independent from each other. However I am having trouble decoupling two bounded contexts that really dependent on each other.
To be more specific, I am designing a Point Of Sales system. It has a Inventory management subsystem which manages the products in the inventory. It also has a Sales subsystem which is responsible for managing customer orders, transactions. They seem to be separated bounded context, however I can not decouple them:
An order [in Sales context] has reference to a product [in inventory context].
When user paying an order [which is done in Sales context], the product quantity should be decreased [which is done in inventory context].
I know I can use domain event and Saga to replace the cross boundary service calls, however just want to know am I designing this correct? Are Sales and Inventory really belong to two separated bounded contexts?

If you instead separate these in three bounded contexts, you can make these dependencies cycle-free:
Product BC, where your products are managed (including price, weight, ...); no dependencies
Sales BC, where sales are handled; dependency on Product BC
Inventory BC, dependencies on Product and Sales BCs.
Usually sales are completely separated from inventory (i.e., you can make sales w/o having the product available yet). If you have a requirement that only products in stock can be sold, let your UI be responsible for offering only products for sale that are also in stock in your inventory.

Related

Relationship between concepts in DDD

I'm developing a budgeting app using Domain Driven Design. I'm new to DDD and therefore need a validation of my design.
Here are the concepts I came up with:
Transaction - which is either income or expense, on annual or monthly or one-off etc. basis.
Budget - which is the calculated income, expenses and balance projection, divided into occurrences (say e.g. 12 months over the next year, based on the Transactions).
I made the Transaction the Entity and Aggregate Root. In my mind it has identity, it's a concrete planned expense or income that I know I'll receive, for a concrete thing, and I also need to persist it, so I can calculate the budget based on all my transactions.
Now, I have an issue with the Budget. It depends on my concrete list of Transactions. If one of the Transactions gets deleted, the budget will need to be re-calculated (seems like a good candidate for a domain event?). It's a function of my identifiable transactions at any given time.
Nothing outside the Aggregate boundary can hold a reference to anything inside, except to the root Entity. Which makes me think the budget is the Aggregate Root as it cannot be a ValueObject or Entity within the Transaction.
What's confusing is that I don't necessarily need to persist the budget (unless I want to cache it). I could calculate it from scratch on request, and send it over to the client app. 2 different budgets could have the same number of occurrences, incomes, expenses and balances (but not Transactions). Perhaps an argument for making it a ValueObject?
So, my questions is - what is the Budget?
Domain context vs Aggregate
First element you get wrong is a point of details about DDD semantics. If there is only one object in your "aggregate", then it is not an aggregate. An aggregate is a structure made of multiple (2+) objects, with at least one being an entity and called the aggregate root. If a TransactionRpository returns a Transaction object that has no value object or entity, then Transaction is an entity but not an aggregate nor an aggregate root. If a BudgetRepository returns a Budget entity that includes a Transaction object, then Budget and Transaction form an aggregate, Budget being the aggregate root. If Budget and Transaction are returned from different repositories, then they form different contexts.
Context being the generic concept that can either be an aggregate or an entity.
Contexts are linked to use cases
Second element you get wrong is that you are trying to design your domain model outside of your use cases context. Your application clearly manipulates both concepts of Budget and Transactions, but does your application handles uses cases for both (budget management and transaction management) ? If yes, are these uses case different in a way that implies different domain constraints ?
If your application only handles Budget management, or both but they share their business constraints, then you only need a single context, that manipulates both concepts in a single aggregate. In that situation, Budget is probably your root aggregate, and it's up to your mode and use cases to tell whether the Transaction is a value object or you need to access them by Id.
If your application handles uses cases for both, with different business constraints, then you should split your domain in two contexts, with two different models, one for the Budget management use cases, the other for the Transaction management use cases.
Polysemic domain model
The third element you get wrong, is that you are trying to build a single, unified, normalized domain model. This is wrong because it introduces very complex structures, and a lot of business rules that are irrelevant to your business cases. Why would you need to manipulate the Budget domain model when the use case does not need knowledge of the Budget concept or linked business rules ?
If your application has use cases for both concepts, you need two models. The Budget management model should not use the Transaction management model. However, that does not implies that the Budget model is not allowed to manipulate the Transaction concept and vice versa. It only means you must write another model for that. You could have a Budget context that manipulates Budget and BudgetTransaction models, and Transaction context that manipulates Transaction and TransactionBudget models. These models can map to the same RDBMS tables with different columns, relevant to their use cases, implementing relevant business rules.
This is called writing a polysemic domain model.
Conclusion
So, my questions is - what is the Budget?
It is not possible to answer definitely your last question, as the answer depends on the use cases your application handles. However, you mention the following constraint:
If one of the Transactions gets deleted, the budget will need to be re-calculated
This seems a very good argument in favor of making your application as a single context application, based on an aggregate with Budget being the aggregate root and Transaction being an entity in the aggregate.
If you don't need to, try to refrain from splitting these two concepts in different contexts, unless you have very good reasons to do so: they manipulate excluding columns, they manipulate excluding business rules, you are interested in deploying these two in different bounded contexts, different services, as they would scale differently, etc ...
Having business constraints that span accross multiple contexts implies a complex implementation based on domain events, 2-phase commits, saga pattern, etc ... It's a lot of work, you should balance that work with the benefits you expect in return.

DDD Customer, Contacts, and Addresses (aggregate root)

I'm building an application that manages most of the LOB stuff at my company. I'm trying to wrap my head around DDD... starting with customer management. Many examples are very, very simple in regards to the domain model which doesn't help me much.
My aggregate root is a Customer class, which contains a collection of Addresses (address book), a collection of Contacts, and a collection of communication history.
Seems like this aggregate root is going to be huge, with functions to modify addresses, contacts (which can have x number of phone numbers), and communication.
E.G.
UpdateCustomerName(...)
SetCustomerType(...) // Business or individual
SetProspect(...) // if the customer is a prospect
SetDefaultPaymentTerms(...) // line of credit, etc. for future orders
SetPreferredShippingMethod(...) // for future orders
SetTaxInfo(...) // tax exempt, etc.
SetCreditLimit(...)
AddAddress(...)
RemoveAddress(...)
UpdateAddress(...)
VerifyAddress(...)
SetDefaultBillingAddress(...)
SetDefaultShippingAddress(...)
AddContact(...)
UpdateContact(...)
RemoveContact(...)
SetPrimaryContact(...)
AddContactPhoneNumber(...)
RemoveContactPhoneNumber(...)
UpdateContactPhoneNumber(...)
AddCommunication(...)
RemoveCommunication(...)
UpdateCommunication(...)
etc.
I've read that value objects don't have identity. In this system, each address (in the database) has an ID, and has a customerId as the foreign key. If Address is it's own aggregate root, then I wouldn't be able to have my business logic for setting default billing / shipping. Many examples have value objects without an ID... I Have no idea how to persist the changes to my Customer table without it.
Anywho, feels like I'm going down the wrong path with my structure if its going to get this ginormous. Anyone do something similar? Not sure how I can break down the structure and maintain basic business rules (like making sure the address is assigned to the customer prior to setting it as the default billing or shipping).
The reason that you're butting up against the issue of where business logic should lie is because you're mixing bounded contexts. LoB applications are one of the typical examples in DDD, most of which show the application broken up into multiple bounded contexts:
Customer Service
Billing
Shipping
Etc.
Each bounded context may require some information from your Customer class, but most likely not all of it. DDD goes against the standard DRY concept when approaching the definition of entities. It is OK to have multiple Customer classes defined, one for each bounded context that requires it. In each bounded context, you would define the classes with properties and business logic to fulfill the requirements within that bounded context:
Customer Service: Contact information, contact history
Billing: Billing address, payment information, orders
Shipping: Line items, shipping address
These bounded contexts can all point to the same database, or multiple databases, depending on the complexity of your system. If it is the same database, you would set up your data access layer to populate the properties required for your bounded context.
Steve Smith and Julie Lerman have a fantastic course on Pluralsight called Domain-Driven Design Fundamentals that covers these concepts in depth.

DDD Composing Multiple Bounded Contexts

I would like your advices about bounded contexts integration.
I have a usecase which put me in a corner :
I have a bounded context for Contract management. I can add parties (various external organizations for example) to a contract. Select for each party their investment / contribution (ex: 10% of the total). SO contract management is two-fold : one is administrative (add party, manage multiples dates, ...) the other one is financial (plan their contributions that span multiple years, check contributions consumption, ...).
I have another bounded context for Budget. This context is responsible for expenses management at the organisation level. Example: a service A will have 1000 € of expense capacity. We can plan a budget and after that each organisation party can consume, buying stuff, their part. In order to build a budget, the user in charge of the enterprise budget can allocate money directly or integrate a yearly contract financial component. When we integrate a contract part inside the budget we froze the data inside the budget, i.e we copy the monetary data from one database table inside another one (adding some audit informations). We have a single database.
It is this last part I struggle with. Each bounded context is a dedicated application. In the budget application, after a contract part has been integrated inside the current budget, I need to display the budget details lines. Unfortunately in the budget tables I have only the money data and not some basic info about the contract (object, reference, ...).
What am I thinking :
sometimes is not bad to duplicate data between bounded contexts. I froze the money part of a contract. I can also freeze / duplicate the object and reference of the contract. Then the querying will only take place inside the budget context. But what is problematic here is the data duplication. Today I need object /refrerence and if tomorrow I need more fields ... I will need domain events management to keep the data between contract / budget in sync.
querying budget and for each line query a contract service that will return the data needed. That keep each context autonomous but I need to make lots of database requests to enrich the budget details line objects.
with only one join at the database level we can make this work. What about coupling here ? It is the simple solution and what we are doing today (is it a shared kernel ?). It seems we can't afford to change contract structure without rebuilding the budget application. I don't have a programmatic contract between the contexts.
My question is :
How can I build this UI screen that need data from the budget context and each details line need data from the contract context ?
Side Notes :
Perhaps the contexts identification and perimetre are wrong from the start (it is a legacy design).
What I would like is to keep the context separate (loose coupling). If we can specify design contracts between the contexts, the maintenance is easier (or not ?).
I failed to see how to integrate these contexts (I need to re-read shared kernel, ustream / downstream etc).
This is an additional, distinct bounded context. It has some overlap with the existing bounded contexts, which can easily lead you down the wrong path (merging contexts or putting additional behaviour in a context where it doesn't belong).
Sometimes it's OK to have entities in different bounded contexts which are referring to the same logical entity, but which are just providing a different view of that entity for the purposes of a specific scenario (eg in a specific context).
A good example of this is in an e-commerce scenario. In most e-commerce applications you will have the concept of an Order, but there is no global, definitive notion of what an "order" is. In a finance context - the order is simply an invoice. In a fulfilment context - the order is simply a packing list and an address to send the goods to. In a marketing context - the order represents a little piece of intelligence about what the customer is interested in, which can be used for future targeted marketing.
There is a thread of commonality which runs through all of those entities, but you would likely see at least 3 separate Order classes, each one capturing the concept of an order within a context.
And so in your case, you have a bounded context for Contract and a bounded context for Budget. It seems to me that you now have another way of looking at these entities, and specifically the way in which they interact with each other. This is a new view of the entities, a view which can be captured in its own context. This new context will likely have its own Contract and Budget entities, and there will be overlap with the Context and Budget contexts, but there will also be additional relationships and behaviour in there, which wouldn't make sense in those other contexts.
This is a really difficult idea to explain :) I wrote an answer to a similar question some time ago here: DDD - How to design associations between different bounded contexts

trying to identify the aggregated roots of a car rental domain

I am trying to study some aspects of ddd with the domain of a car rental website.
The user/customer selects a car from a start and destination station and the time period.
The price calculation depends on various things like payment method, time, car classification and so on. The data is retrieved from a subsystem which differs in data access strategy from the rest of the application.
There are several actors in the domain like station service, call center...
Idea for the bounded context are
Company (employee, car, station)
Booking (reservations, model for booking request process)
Pricing (the price model)
Billing (rental billing, positions, customer)
After defining the bounded context I am unsure if the aggregated roots of each are correct. My thoughts are
Company: all three of them
Booking: reservation (access to billings, the car and customer)
Pricing: tariff matrix
Billing: customer (access to reservations, billings)
If needed I can add some class diagrams to show the different bounded context.
If more information is needed, a class diagram or this should be migrated to an other section feel free to ask/do it.
With what little experience I have with the car rental domain, I'd say you are on the right track. A couple of things you should be aware of: Bounded Context are a logical separation, not a physical one. As such, using something like a compositional UI, would allow you to display pricing information as part of the booking process. You'd be hosting UI components from different BCs side by side, and using them to guide the end user through the process he's trying to complete. The other thing is, you're looking for aggregate roots in all of the BCs, but I do hope you realize that you don't need a domain model in each and every one of them. Maybe a simple datamodel will do if things are not "core" to your business or crud-based by nature. That's the beauty of BCs, the ability to make deliberate technology choices.

DDD: bounded contexts - domain entities that reference concerns in another bounded context

I'm getting confused on how to define bounded contexts where there are shared concerns between them, and how to represent this with Domain Entities.
For example:
A customer has many products in a Customer context
A company has and a list of products in the Company context
So the customer is managed via the customer context, and the company via the company context
Given the contexts are in differnt modules.
If I want to provide the Company's address details with a product, how should this be handled?
Do I reference the module containing the Company context in the module containing the customer, or do I create a Company entity in the customer context specifically for use when interacting with customers?
Thank you
You can have different representations of the same entity in different bounded contexts. Company in Company BC can be very different from company in User BC. All they have to share is some kind of correlation Id.
This is how we approached it in our project as well.
For one bounded context we used a contract as an Aggregate Root, while in another bounded context we used the contract as a value object/entity
In the first module/BC we had a big contract class with a lot of behavior in it, while in the second module/BC we had another contract class, which only contained a few properties with private setters.
This way it would be possible to separate the 2 BC's into separate assemblies of services in a SOA design even.

Resources