It is often said that DDD (Domain-driven Design) is better suited for complex domains instead of simpler ones.
What characterizes a complex domain? (please be more specific than "it has complex business rules");
Which are examples of complex domains?
How can I classify a domain as complex (i.e. suitable for DDD) or not?
From my experience 3 most important thing that makes your domain complex:
Size
Big domains tends to increase complexity. Handling and coordinate a lot of things is always hard.
Rules and invariants
Domains (even domains with just a couple of bounded context) might have a lot of domain rules and invariants and/or a lot of nuances in its use cases and process. This increase complexity. Rules that spam a lot of changes in a entity or inter-domains events are often the complex business rules.
Context
Context complexity is hard to explain wihtout a example. Let's put in the table a context complexity related to a entity named Product.
Depending of context; a entity could means different things in your domain. A Product entity doesn't means the same for Factory context, Marketing context, Sales context, PostSales support context, etc.
If the data, user cases, process, behaviour, etc related to Product entity, in every context, are very different the complexity increase a lot even when you just have a handful of context and entities. This usually means that you have many Product entities (one in every context) even if all of them are supported by the same persistence store (in case of ER store, the same table/s).
There is no unique definition of complexity, but there is a useful description in Vaughn Vernon book (Implementing Domain Driven Design) : Table 1.1 The DDD Scorecard.
He describes the project with different criteria, for example : a complex project is going to change often (new features and it will be hardly to anticipate), you don't fully understand the domain (or there is a lot of ambiguity that you need to discuss with business expert), the size as #jlvaquero said (number of feature/rules/richness of the language...).
In my opinion, one sign of complex domains is degree of hardness of creating and maintaining Ubiquitous Language.
As the vocabulary, phrase, and terminology become more diverse, creation of UL become more difficult. This confirms the complexity of the domain.
Related
How would you handle a domain that shares much of the same business logic, but has slight variances in both the domain language and attributes of entities. These variances change by "region".
A fictitious example is a Real Estate System for managing residential Real Estate. The language used can vary slightly between State/Province, and attributes about the Real Estate can be more detailed in some States. There would be an Office in each State/Province managing the Real Estate for that "region".
Would you create a separate Bounded Context for each State/Province? So there would potentially be 50+ Bounded Contexts?
Would you create a single Bounded Context, and just handle the variances of language, and data through object inheritance or composition?
Let me start off by saying that I don't think there's a silver bullet here. As always it all depends on different factors. That's way my reaction is not a concrete idea but rather a set of consideration you and your team could take into account on the path to a decision.
If I would be asked to define a bounded context I would say that it is the setting where a word has a certain meaning or connotation. If we can agree one the above statement then one would immediately be tempted to create a bounded context per region or setting.
That is, if the benefit you gain from having all those context contributes to the comprehensibility of the codebase. But if the context you are creating are really thin or you pay a heavy technical maintenance costs of having all those contexts I would strongly advise against going for multiple contexts.
I'm not certain but I feel that in your case one word will have the same meaning in each context only the word used will be different in each context. Whereas normally the same word used in different contexts has a different meaning.
I hope that this all makes sense and it helps you figure out your issue.
I reached out to Vaughn Vernon, one of the leaders in the area of DDD and I thought I would share his response (summarized by me).
Based on the limited information and examples I provided he brought up these points:
Metadata driven design would be more effective and efficient. Meaning, each "region" would have metadata to drive its flows, and data
Look at the State Pattern to drive regional situations
Look at the concept of DCI for ideas, but limit your attempts at actual DCI implementations as it can increase complexity of the code
Im new to learn DDD concept and i cant understand something.
1-What difference between Context Map and Bounded Context and SubDomain?
2-How to recognize relation between Bounded Context ?
As said in the comment, this is a wide subject, and very important in DDD. It is the strategic part of DDD. Anyway I will try to answer your questions with an overall explanation:
DDD is about understanding and distilling the domain of the problem we want to solve. It is a continuous process of learning about the domain, talking to the domain experts. All people (developers, business people, etc) speak the same language. This language is used everywhere (conversations, documentation, source code, ...). It is called the Ubiquitous Language (UL).
The problem domain may have different areas of functionality, which would be domains too. They are the subdomains. So a subdomain is a subset of the problem domain. It is like splitting the problem into smaller subproblems, and a subdomain would be the domain of a subproblem. There are 3 kinds of subdomains:
Core: The point of distillation is to discover the subdomain that has value for the business, i.e., the one that will make your product better than others of the same kind. Such subdomain is the "core subdomain". For example, in "project management", the "task assignement" would be core.
Supporting: It is specialized in some business aspect that helps the core functionality. For example, in "project management", a "calendar" (for marking tasks delivery dates).
Generic: Functionality that maybe needed by any kind of application. For example, authentication and authorization of users.
Subdomains belong to the problem space.
To solve the problem, you model the subdomains, and you create bounded contexts (BCs). In practice, a BC is an autonomous application that contains the software model of a subdomain. A BC has its own UL. It is the context on which a term of the UL has a meaning. UL and BCs are the most important things in DDD. UL drives the BCs identification.
Ideally, you should align 1:1 the subdomains of the problem space with the BCs of the solution space, i.e., you should have a BC for each subdomain.
A team can develop one or more BCs, but a BC should be developed by just one team.
BCs belong to the solution space.
Context Map: It is a drawing that shows the BCs, and the relationships among them. Every relationship is classified in one of the following patterns:
Partnership
Shared Kernel
Customer-Supplier
Conformist
Anticorruption Layer
Open Host Service
Published Language
Separate Ways
Big Ball of Mud
Recognizing which pattern to apply in a relationship it will depend on the particular case you have. Some things that you have to consider are:
The 2 teams collaborate together.
One of the teams doesn't care about the other one.
The teams can negotiate.
The teams are independent.
Changes on a model (upstream) affects to the other model (downstream).
As #Augusto mentioned, this is a couple of chapters in the blue book, but here goes.
The domain model is found in the business rules and how people talk but a simplification of it is captured in code. Certain naming is consistent and the necessary invariants are enforced in the model.
A bounded context is mostly conceptual (might be a namespace, module, project in code as well...). It is the intention to keep a domain model consistent within it. So within the context, a certain ubiquitous language is used. And a model need only serve the needs of THAT context. It is the boundary in which the model can be used. In terms of recognizing these relationships? Some might be subtle but most are not. At least some people in the team will want to "avoid duplication" by unifying the model... so that is a clear indication that there is a relationship. Names are often the same or similar... or could be the same but one is better suited to one domain and another to another domain.
A context map is a bit more of a project management tool. It is a map of how different contexts (and the models within) relate to each other. In an Ordering Domain in an e-commerce system you may have a product. It would lead to A LOT of complication trying to have a unified Product in a model that spanned Ordering, Payments, Content for the website and Inventory domains (for example). So each of those domains should have a separate model. The context map is a diagram and related documentation that relates these bounded contexts together since there would be relationships and translation of data across from one model to the next, as an order flows through the system.
The last element you asked about is a subdomain. Here you probably are referring to a generic subdomain. Personally, I think the name is a little confusing. It makes it seem like a subset of the model. Maybe this is on purpose but I generally think of them as their own domain, just one that is not central to the business's proposition. For instance, if the aforementioned e-commerce company was known for its same day or next day delivery, then they probably shouldn't buy an off-the-shelf solution to inventory and shipping management. On the other hand, if they were focusing on a market that just wanted the cheapest deal but didn't mind waiting a few days, then that would be a perfect candidate for a generic subdomain.
My DDD glossary which has plenty of links at the bottom to more detailed articles.
If you are serious about learning this subject and can get your hands on some books:
Domain-driven Design by Eric Evans
Implementing Domain-driven Design by Vaughn Vernon
Domain-driven Design made functional by Scott Wlaschin (my favourite)
I've read Eric Evan's book and am reading Vaughn Vernon's book now. I'm in the second chapter where he talks about subdomains and bounded context and am thoroughly confused now.
From what I was able to distill, there should be a 1:1 relationship between a BC and an SD. However, I read in other places that this isn't necessarily the case.
Can someone explain to me the relationship between a BC and SD?
A subdomain is a part of your business. There are core domains, supporting domains and generic domains. Core domains are where the money is, supporting domains support your core business, and generic domains are the ones you need, but don't care a lot about, so you would probably buy them of the shelf. For an insurance company, the core domain is insurance, a supporting domain could be client portfolio, and a generic domain could be something like timesheets.
In general a bounded context is a boundary within which the ubiquitous language is consistent. In DDD walhalla each subdomain would live in its own bounded context. In reality however, there is legacy, there are packages that try to do everything at once... which will force all kinds of awkard relationships.
I try to explain these concepts with my understanding.
In DDD, everything should be communicated under ubiquitous language so the technical team and business team can use the same terms and have same views on the problems
Domain in DDD represent real problem in business. Such as: E commerce is a domain, Payroll system is a domain
Domain is divided into many sub domains, so each sub domains focus smaller problems. Such as: E commerce has many sub domains such as: Shopping Cart, Billing, Product Catalog, Customer Information...
Each sub domain should have explicit responsibilities so it has a boundary to limit their functionalities, the boundary will help sub domain focus to do only 1 thing and do well. This boundary is considered as bounded context of the sub domain. The bounded context will define:
How many domain models needed for the sub domain?
Which properties needed in the each model?
Which functionalities needed in sub domain?
Ex: Shopping Cart sub domain needs models: Cart, Product, Customer Info... and contains functions to perform CRUD on the cart. Notes: The Product and Customer model in the Shopping Cart sub domain maybe not the same with the models in Product Catalogs and Customer Profiles sub domain, they just contain necessary properties to display on Shopping Cart.
Vaughn Vernon in his “Implementing Domain-Driven Design” book states that “the subdomains live in the problem space and the bounded contexts in the solution space”
Imagine a software that is being developed to support a dentist. A dentist has two problems: fixing patients’ teeth and making appointments for the patients. Fixing teeth is the core domain and making appointments is a supporting subdomain. In the core domain the medical staff cares about a patient’s dental history, can they handle general anesthesia or not, what their current problem is, etc. In the subdomain the staff (not necessarily medical staff) cares about a patient’s contact information, a date and a time that best suits both the doctor and the patient, the type of dental work needed, etc. Both domains need a model of a patient, but that model will depend on the bounded context we put in place to ensure the correct information and features are available when solving the problems of each domain.
read https://robertbasic.com/blog/bounded-contexts-and-subdomains/
Rereading the Booking Context from the blue book 18 times helped me finally get a handle. http://codeidol.com/csharp/domain-driven-design/Maintaining-Model-Integrity/Bounded-Context/
This article helped as well: http://gorodinski.com/blog/2013/04/29/sub-domains-and-bounded-contexts-in-domain-driven-design-ddd/
Here is my understanding, I would use the Hospital example to elaborate the concepts and deep dive into how is BC is different than Subdomain and why they can be a case where there is no 1:1 relationship between them
Example
Imagine we are making software for a Hospital, in which we have identified 3 subdomain
Health Care (Core domain, where they actually want to cure the patient)
Invoice (Supporting domain focused on invoicing)
Knowledge (Generic domain, where doctors maintain procedures on how to operate on a patient for a particular disease)
Now we know that Bounded Contexts are boundaries under which terms
have a very well-defined meaning. So let us apply those in Subdomains
Let's consider the term. Patient. What are the things that you think about when hearing the term patient?
Their current symptoms
Past medical records
Allergies
How about their bill-paying credibility? Current outstanding balance? Didn't think of it? The reason is you were thinking in the core subdomain space of Health Care. The bill-paying credibility makes sense only when you shift to the Invoice subdomain.
What we understand from this is the Patient term is inside a Bounded Context, its a boundary inside a subdomain where it has a very specific meaning
The reason it said
BC is in solution/implementation/programming space and not in business
space
is because here we decide what fields and behaviors should be part of the Patient model
In the core domain space, you might represent Patient it like this
class Patient {
List<Allergy> alergies;
List<MedicalRecord> records;
Age age;
boolean isAllergicTo(Allergy allergy)
boolean canTakeLocalAnesthesia()
}
Whereas in the Invoicing subdomain you might want to represent it like this
class Patient {
CreditCard creditCard;
CreditScore creditScore;
Bill currentBill;
void charge(Amount amount)
}
Similarly, the term Cure in the Health Core subdomain, would have the operations that were/are_to_be performed on a patient to cure the disease whereas in the Knowledge subdomain it would contain information about Symptoms, Diagnosis tests, Prescription suggestions, that go along with a disease.
You can now see the Health Care subdomain has multiple BCs and under a BC each term has a very specific meaning thus supporting the Ubiquitous Language
Please check this link it will help you,
Bounded Context or Context?
The term Context is a general description of a grouping of concepts, the term Bounded Context is more specific – a Bounded Context is an area of your application which has explicitly defined borders, has its own Model, and maintains its own code. Within the Bounded Context everything should be strictly consistent.
Usually, we can use the terms Context and Bounded Context interchangeably, though I tend to talk in terms of Context about the business side of things, and the term Bounded Context about the technical implementation.
In a very short and simple sentence, we can say: subdomains are part of the problem space and are chosen by The Business whereas bounded contexts are software boundaries defined by engineers.
First. The official definitions from the Blue Book is:
Domain: A sphere of knowledge, influence, or activity.
Bounded context: The delimited applicability of a particular model. Bounded contexts gives team members a clear and shared
understanding of what has to be consistent and what can develop
independently.
Note that those concepts exists by themselves before any architecture design or line of code is written down.
DDD is about having a domain model shared by business people and programmers that is reflected in source code. But with medium or bigger organisations it is not practical to have a single model. It is better to divide and conquer because:
Different areas have different needs, cultures, jargon, etc. Sometimes the same concept has different terms or viceversa.
Creating a big meeting to make people agree is costly and it is really hard to agree in something at this scale for so many people.
The cognitive load of developing an enterprise-wide mega application. Better to implement a components that can assigned to smaller teams.
So you reduce the domain modelling to an specific an concrete bounded contexts. This has the advantage of also reducing the complexity. But what if the same concept is used in several contexts? This leads me to the second question:
There should be a 1:1 relationship between a BC and an SD. However, I
read in other places that this isn't necessarily the case.
No. There is no need. Here is an example from Martin Fowler: the products and customers subdomains are shared by the sales and support bounded contexts.
Of course you try to select bounded contexts as loosely coupled as possible. But just as when you separate modules in an app there is a minimum level of coupling to make the connection. So, the same concept is modelled differently in each context (Multiple Canonical Models). This can be implemented in code by adding an Anti-Corruption-Layer that translates between models.
Moving to a single bounded context is not just a matter of software design. It would require modifying the mental model of business and this is hard. Also, people sometimes have simpler views of a domain because it reduces the complexity and their cognitive load.
Concrete example:
In this talks from DDD Europe they have an example from Amazon:
The sub-domain term Book has a very different model in different bounded contexts:
In the Catalog bounded context: Picture, title, authors, rating...
In the Shipping bounded context: Dimensions, weight, international restrictions
In the Search inside bounded context: full-text content, copyright dealing policy
So Amazon may have very complex sub-domains with lots of attributes:
Books: isbn, title, number of pages)
Clothing: size, colour, material
Computers: cpu, graphic card, hard-drive, ram
But only some of them would be relevant in different subdomains.
Let me add a diagram with a more global example
Extra resources:
"Bounded Contexts" Talk by Eric Evans in DDD Europe 2020
DDD Crew: repo resources
Virtual DDD community
Vaughn Vernon states in his book “Implementing Domain-Driven Design” the following:
"It is a desirable goal to align Subdomains one-to-one with Bounded Contexts." Page 57
A model's boundary, the bounded context, can contain ideas from various subdomains. Or a single subdomain might be represented by a number of bounded contexts. The ideal scenario would be one bounded context for one subdomain. If you are able to define multiple bounded context for a subdomain, that sometimes leans you into realizing that the subdomain is not fine-grained, and maybe the subdomain could be distilled into separated subdomains.
The other way around could also be justified, when you had multiple subdomain aspect covered in one BD, because e.g. that was pragmatic to do so.
More specifically, when the subdomain is generic, and the generic solution is easy to integrate, it may be more cost-effective to integrate it in each of the bounded contexts locally.
An example is a logging framework; it would make little sense for one of the bounded contexts to expose it as a service, as the added complexity of integrating such a solution would outweigh the benefit of not duplicating the functionality in multiple contexts.
When two different languages talking the same or similar thing, the thing is referred in 2 different contexts. You can translate the thing in 2 context in certain extents.
Similarly a term could have different meaning in different departments. in that case different context explain the term differently. Translation between two to some extent maybe possible.
Instead of saying “Bounded context” maybe try saying “bounded world”
My understanding about sub-domain and bounded context is-
Each subdomain represents a specific area of knowledge or responsibility within the overall domain, and each subdomain may have one or more responsibilities associated with it. In some cases responsibilities can split across multiple subdomains. Considering all theses issues, it can be useful to draw logical boundaries to separate those responsibilities and maintain consistency and transactional integrity.
Bounded contexts in Domain-Driven Design (DDD) are used to define these logical boundaries and provide a way to manage the complexity of large and complex systems by dividing them into smaller, more manageable parts. By using ubiquitous language we can ensure that the concepts and rules of that context are clearly understood and communicated within the development team. So we draw that boundary based on the uses language in that particular context.
So, in summary, a subdomain represents a specific area of knowledge or responsibility within the overall domain, and bounded contexts are used to manage the complexity of large systems by creating logical boundaries around specific areas of responsibility, and using a specific language, or ubiquitous language, to ensure clear communication and understanding of the concepts and rules within that context.
Bounded context ensure us that one responsibility doesn't blend with another one and finally prevent us from introducing complexity and confusion. In that sense it is very similar with SRP of SOLID
When you are developing an architecture in OO/DDD style and modeling some domain entity e.g. Order entity you are putting whole logic related to order into Order entity.
But when the application becomes more complicated, Order entity collects more and more logic and this class becomes really huge.
Comparing with anemic model, yes its obviously an anti-pattern, but all that huge logic is separated in different services.
Is it ok to deal with huge domain entities or i understand something wrong?
When you are trying to create rich domain models, focus entities on identity and lifecyle, and thus try to avoid them becoming bloated with either properties or behavior.
Domain services potentially are a place to put behavior, but I tend to see a lot of domain service methods with behavior that would be better assigned to value objects, so I wouldn't start refactoring by moving the behavior to domain services. Domain services tend to work best as straightforward facades/adaptors in front of connections to things outside of the current domain model (i.e. masking infrastructure concerns).
You can also put behavior in Application services, but ask yourself whether that behavior belongs outside of the domain model or not. As a general rule, try to focus application services more on orchestration-style tasks that cross entities, domain services, repositories.
When you encounter a bloated entity then the first thing to do is look for sets of cohesive set of entity properties and related behavior, and make these implicit concepts explicit by extracting them into value objects. The entity can then delegate its behavior to these value objects.
Since we all tend to be more comfortable with entities, try to be more biased towards value objects so that you get the benefits of immutability, encapsulation and composability that value objects provide - moving you towards a more supple design.
Value objects enable you to incorporate a more functional style (eg. side-effect-free functions) into your domain model and thus free up your entities from having to deal with the complexity of adding complicated behavior to the burden of managing identity and lifecycle. See the pattern summaries for entities and value objects in Eric Evan's http://domainlanguage.com/ddd/patterns/ and the Blue Book for more details.
When you are developing an architecture in OO/DDD style and modeling
some domain entity e.g. Order entity you are putting whole logic
related to order into Order entity. But when the application becomes
more complicated, Order entity collects more and more logic and this
class becomes really huge.
Classes that have a tendency to become huge, are often the classes with overlapping responsibilities. Order is a typical example of a class that could have multiple responsibilities and that could play different roles in your application.
Given the context the Order appears in, it might be an Entity with mutable state (i.e. if you're managing Order's commercial condition, during a negotiation phase) but if you're application is managing logistics, an Order might play a different role: and an immutable Value Object might be the best implementation in the logistic context.
Comparing with anemic model, yes its
obviously an anti-pattern, but all that huge logic is separated in
different services.
...and separation is a good thing. :-)
I have got a feeling that the original model is probably data-centric and data serving different purposes (order creation, payment, order fulfillment, order delivery) is piled up in the same container (the Order class). Can't really say it from here, but it's a very frequent pattern. Not all of this data is useful for the same purpose at the same time.
Often, a bloated class like the one you're describing is a smell of a missing separation between Bounded Contexts, and/or an incomplete Aggregate separation within the same bounded context. I'd have a look to:
things that change together;
things that change for the same reason;
information needed to fulfill behavior;
and try to re-define aggregate boundaries accordingly. And also to:
different purposes for the application;
different stakeholders;
different implicit models/languages;
when it comes to discover the involved contexts.
In a large application you might have more than one model, thus leading to more than a single representation of a single domain concept, at least for concepts that are playing many roles.
This is complementary to Paul's approach.
It's fine to use services in DDD. You will commonly see services at the Domain, Application or Infrastructure layers.
Eric uses these guidelines in his book for spotting when to use services:
The operation relates to a domain concept that is not a natural part of an ENTITY or VALUE OBJECT.
The interface is defined in terms of other elements in the domain model
The operation is stateless
I am quite new with DDD and would like to know about any pitfalls you might want to share. I will summarize it later for more newbies to read :)
Thanks
Summary so far:
Anemic domain model where your entities are primarily only data bearing and contain no business logic
Not using bounded contexts enough
Focusing too much on patterns
There is a good presentation on this topic as well here (video).
Probably the most important one: not grokking the central, fundamental principle of the Domain Model and its representation in Ubiquitous Language. With the plethora of technology options around, it's very easy for your head to fill up with ORMs, MVC frameworks, ajax, sql vs nosql, ... So much so there's little space left for the actual problem you're trying to solve.
And that's DDD's key message: don't. Instead, explicitly focus on the problem space first and foremost. Build a domain model shorn of architectural clutter that captures, exposes and communicates the domain.
Oh, and another one: thinking you need Domain Services for everything you can do in the domain model. No. You should always first try to put domain logic with the Entity/Value type it belongs to. You should only create domain services when you find functions that don't naturally belong with an E/V. Otherwise you end up with the anaemic domain model highlighted elsewhere.
hth.
One of the biggest pitfalls is that you end up with a so-called anemic model where your entities are primarily only data bearing and contain no business logic. This situation often arises when you build your domain model on top of an existing relational data model and just make each table in the database an entity in your domain model.
You might enjoy presentation of Greg Young about why DDD fails.
In short:
Lack of intent
Anemic Domain Model
DDD-Lite
Lack of isolation
Ubiquitous what?
Lack of refinement
Proxy Domain Expert (Business analyst)
Not using bounded contexts enough. It's toward the back of the the big blue book but Eric Evans has gone on record as saying that he believes that bounded contexts and ubiquitous language are THE most important concepts.
Similarly, people tend to focus too much on the patterns. Those aren't the meat of DDD.
Also, if you do not have a lot of access to domain experts you are probably not doing DDD, at best you are DDDish.
More concretely, if you end up with many-to-many relationships, you've probably designed something wrong and need to re-evaluate your aggregate roots/contexts
Only adding to what others have already said;
My personal experience is that people often end up with an anemic model and a single model instead of multiple context specific models.
Another problem is that many focus more on the infrastructure and patterns used in DDD.
Just because you have entities and repositoriesand are using (n)Hibernate it doesn't mean you are doing DDD.
It's not from my personal experience with subject, but it was mentioned for a couple of times in DDD books and it's what I've been thinking about recently: use Entities when you really need identity, in other cases use Value Object. I.e., Entity pattern often happens to be the default choice for any model noun, and it's not the way it should be.
Beware of the Big Ball of Mud.
One of the pitfalls of domain driven design is to introduce ambiguity into a model. As explained in the article Strategic Domain Driven Design with Context Mapping:
Ambiguity is the super-villain of our
Ubiquitous Language
This may happen when two distinct concepts share the same name, or when the same concept can have different uses. It may be necessary to
expose the domain structure in
terms of bounded contexts in a context
map
If a model is used in too many different ways, or has too many responsibilities, it may be a sign that it should be divided.