Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
Contents
About The Author
Introduction
ii
ii
ii
iii
A Problem Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iii
A Solution Space . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
iii
iv
1.1
1.2
Developing In Mud . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
2.1
Team Modelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
10
13
13
Sketching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
13
14
CONTENTS
2.2
2.3
2.4
2.5
2.6
3
Powerful Questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
14
Rapid Prototyping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
15
15
16
16
17
Subdomains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
18
18
Core Domains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
21
22
Generic Domains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
Supporting Domains . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
23
23
24
Model In Context . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
24
25
Context Game . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
26
27
28
28
29
30
3.1
30
3.2
30
31
32
3.3
Teach Your Domain Experts To Focus On The Problem And Not Jump To A Solution 33
Using Features And Scenarios To Demonstrate Domain Scenarios . . . . . . . . . .
33
3.4
34
3.5
35
CONTENTS
36
4.1
36
37
38
40
41
42
43
44
4.3
45
4.4
46
47
47
49
49
50
51
Shared Kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
52
53
Publish-Subscribe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
54
55
Customer-Supplier (Upstream/Downstream) . . . . . . . . . . . . . . . . . . . . . .
56
Conformist . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
56
Partnership . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
57
57
4.2
4.5
4.6
4.7
5
58
5.1
58
59
A Clean Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
59
Persistence Ignorance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
60
CONTENTS
61
62
62
63
Hands On Modellers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
63
63
64
Value Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
64
Entities . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
67
71
Domain Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
75
Domain Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78
78
Factories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
78
Repositories . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
80
Application Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
81
Infrastructure Services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
83
5.3
83
5.4
86
5.2
88
6.1
88
6.2
88
91
6.3
91
6.4
91
6.5
92
7.1
93
Patterns For Understanding The Problem Space Are Useful On All Projects, ModelDriven Design May Not Be . . . . . . . . . . . . . . . . . . . . . . . . . . .
93
93
CONTENTS
7.2
94
7.3
95
95
95
95
7.4
97
98
99
100
III Case Study: Putting Theory And Coding Patterns Into Practice
101
11 A Modelling Example
102
Appendix
103
Version History
104
Introduction
Why You Should Read This Book
Writing software is easy, sorry writing greenfield software is easy. When it comes to modifiying
code written by other developers or code you wrote six months ago, it can be a bit of a bore at
best and a nightmare at worst. The software works but you arent sure exactly how. It contains all
the right frameworks, patterns and has been created using an agile approach, yet introducing new
features into the code base is harder than it should be. Even business experts are of no use as the
code bears no resemblance to the language they use. Working on such systems becomes a chore
leaving developers frustrated and devoid of any coding pleasure.
Domain-Driven Design (DDD) is a process that aligns your code with the reality of your problem
domain. As your product evolves, adding new features is as easy as it was in the good old days
of greenfield development. Where DDD understands the need for software patterns, principles,
methodologies and frameworks, it values developers and domain experts working together to
understand domain concepts, policies and logic equally. With a greater knowledge of the problem
domain, and a synergy with the business, developers are more likely to build software that is more
readable and easier to adapt for future enhancement.
Following the DDD philosophy will give developers the knowledge and skills they need to tackle
large or complex business systems in an effective manner. Future enchancement requests wont be
met with an air of dread and developers will no longer have stigma attached to the legacy application.
In fact the term legacy will be recategorised in a developers mind as meaning; A system that
continues to give value for the business.
iii
Introduction
A Solution Space
With a sound understanding of the problem domain strategic patterns of DDD can help you to
implement a technical solution in synergy with the problem space. Patterns enable core parts of your
system that are crucial to the success of the product to be protected from the generic areas. Isolating
integral components allows them to be modified without having a rippling effect throughout the
system.
iv
Introduction
Core parts of your product that are sufficiently complex or will frequently change should be based
on a model. The tactical patterns of DDD along with Model-Driven Design will help you to create
a model. A model that is in synergy with the problem domain will enable your software to be
adaptable and understood by other developers and business experts.
The figure below shows a high-level overview of the solution space of Domain-Driven Design that
will be introduced in the first part of this book.
Introduction
Introduction
vi
that will give you the most value) on an abstract model that reflects the real business subdomain.
This model will enable the core parts of the system to be flexible enough to change when critical
parts of the business change.
What is a Problem Domain?
A problem domain refers to the subject area that you are building software for. DDD stresses
the need to focus on the domain above anything else when working on creating software
for large-scale and complex business systems. Experts in the problem domain work with
the development team to focus on the areas of the domain that are useful to be able to
produce valuable software. For example when writing software for the health industry to
record patient treatment it is not important to learn to become a doctor. What is important
to understand is the terminology of the health industry, how different departments view
patients and care, what information doctors gather and what they do with it.
.
your business domain the better equipped you will be when you are trying to solve problems
within it.
.
Developing In Mud
Continuing to persist with an architectural spaghetti-like pattern can lead to a sluggish pace of
feature enhancement. When newer versions of the product are released often they can be buggy
due to the unintelligible mess of the code base that developers have to deal with. Over time the
development team increasingly complains about the difficulty of working in such a mess. Even if
resource is added to the project, velocity cannot be increased to a level that satisfies the business.
In the end, exacerbated by the situation, the request for the dreaded application rewrite is granted.
Without due care and consideration however even the greenfield project can often fall fowl of the
same issues that created the original BBofM. This entire experience can be frustrating for the business
that saw a great return on investment in terms of features and speed of delivery at the beginning
but over time, even with additional investment in resource, did not see the sustained evolution of
the product to meet the needs of the business.
design. Technical debt is similar to financial debt in that if you do not pay it back quickly
you will incur greater costs later when you try and deal with it. The problem with technical
debt is that it makes future changes to the software very difficult as the code is constructed
in an unorganised manner. Sometimes it is a pragmatic choice to incur some technical debt
in order to hit a deadline. However it is important that after the deadline is met, and if the
software will be continued to be invested in, that the technical debt be paid back in the form
of refactoring.
.
What is Refactoring?
Refactoring is the redesign of a softwares structure without altering its functionality. The
purpose of refactoring is to make the software design easier to read and easier to change,
as developers spend more time reading code than writing it. As teams iterate through the
creation of a product they learn more about the domain, and this knowledge needs to be
transferred into code. Lots of small refactorings enable deeper insight into the problem
domain and will enable other developers to understand and modify the software with greater
ease in the future. Unit and integration tests support refactoring by enabling developers to
alter the design of software with the confidence that they wont break existing functionality.
.
The model contains only what is relevant to solve problems in the context of the application being
created. It needs to constantly evolve with the business in order to keep itself useful and valid.
A domain model can be represented in UML or code as shown in the figure below.
So where do we start when trying to create a domain model? How do we as developers get a greater
understanding of the problem domain we are creating software for?
Historically the capturing of requirements for software systems was seen as an activity that could
occur long before coding was due to start. Business experts would talk to business analysts, who in
turn would talk to architects who would produce an analysis model based on all of the information
from the problem domain. This analysis model would then be handed over to the developers, along
with wireframes and workflow diagrams in order for them to build the system.
What Is An Analysis Model?
An analysis model is a collection of artefacts that describe the model of a system. These
artefacts can be in the form of UML such as class diagrams and interaction sequence
diagrams. The analysis model exists to understand the problem domain; it is not a blueprint
for the technical implementation.
.
As developers start to implement the analysis model in code they would often find a mismatch
between the high-level artefacts produced by architects and the reality of building the system.
However at this stage there is often no feedback loop for developers to talk to the business and
architects in order for the analysis model to be updated and their discoveries to be reflected.
Instead the developers diverge from the analysis model and their implementation often overlooks
important and descriptive domain terms and concepts that would have provided deeper insight and
understanding of the domain.
As the development team further evolves away from the analysis model it becomes less and less
useful. Crucial insight into the model is lost as the development team focus on abstracting technical
concerns instead of business concepts. In the end the job gets done but the code bares no reflection
to the original analysis model. The business still believe their analysis models are correct. They
are unaware of the alterations within the code model required to fulfil the wishes of the business
application.
The figure below shows how the analysis and code models can diverge from each other if the
development team are not involved in domain knowledge crunching.
10
The reason why this is a problem is revealed when later enhancements to the codebase are difficult to
implement. The difficulties are due to the business experts and developers having different models
of the business. The code doesnt have a synergy with the business processes and is not rich in
domain knowledge.
Team Modelling
DDD suggests a more collaborative method of capturing system requirements and understanding
existing workflow. Emphasis is placed on the entire team together with business experts and
architects (as long as they code) having discussions around the problem space. Discussions can
include any documentation or legacy code that is related to the system in question. The idea behind
the collaborative knowledge crunching sessions is for the developers, testers, business analyst,
architects and business experts to work as a single unified team. This enables the developers
and testers to learn about the meaning behind domain terms and understand complex logic in
the problem area. It will also enable business experts to experience the modelling techniques
employed. With an understanding of modelling, business experts, will themselves, be able to
model and validate designs with the development team.
11
The sharing of information enables business experts to contribute to the software design as well
as providing a deeper insight and understanding of the domain to the development team. After a
period of time developers, and business experts will discover the relevant information to build an
initial model of problem domain. This initial model is put to test by using domain scenarios; real
problems of the domain to validate its usefulness. Modelling out loud, using the terms and language
of the model can also help to validate early designs.
The important aspect of modelling together is the constant feedback the development team get from
the business experts. This leads to the discovery of important concepts and also allows the team to
understand what is not important and can be excluded from the model. Breakthroughs in sessions
are manifested as simple abstractions that clarify complex domain concepts which lead to a
more expressive model.
The model is then expressed in code and the team, along with business experts can gain fast feedback
with early versions of software. Feedback in turn fuels deeper insight which can be reflected in the
code and analysis models, as highlighted in the figure below.
The code model and the analysis model are kept in synergy.
During each iteration the development team may come across parts of the model that they thought
were useful and could solve a problem, but during implementation they had to change. This
knowledge is fed back to the business experts for clarification and to refine their own understanding
12
of the problem domain. In this process the code model and analysis model are one and a change in
one will result in a change to the other
The figure below shows how the analysis and code model are in synergy and evolve as one during
the creation of a product.
Team modelling.
13
Modellers Block?
Wake yourself up. Brainstorm in code by capturing business requirements as classes and
methods. Model on the whiteboard, on paper, with your colleagues or even your wife. Warm
your brain up by doing something, anything, and the design will eventually bubble up in
your consciousness. If that doesnt work perhaps ideas appear to you during times of quiet
contemplation, and there is no better time for that then when getting the teas in for the team.
Either way, invest in your problem by giving yourself time to think.
.
Sketching
UML is a wonderfully useful language that can be used to communicate complex systems in an
understandable manner with little or no technical expertise. Therefore its a good choice to capture
the initial analysis model. However during knowledge crunching sessions a model is a fluid entity
and will be changing at a rapid rate. Therefore dont try and use elaborate packages such as Visio
or Rational Rose to capture a moving model. Instead sketch out the model on the white board. You
will be less precious about a sketch that took you minutes to draw than a diagram in Visio that took
you most of the morning. If you must write up your knowledge crunching sessions do it at the end
when you know the most about the problem domain.
14
Powerful Questions
Powerful questions are key to good analysis sessions. Greg Young
What does good look like? What is the success criteria of this product? What will make it a
worthwhile endeavour? What is the business trying to achieve? The questions you ask during
knowledge crunching sessions will go a long way to revealing a greater understanding of the
importance of a the product you are building and the intent behind it.
Here are some examples to get your domain expert talking and revealing some deeper insight into
the domain:
http://codebetter.com/gregyoung/2012/02/28/the-gibberish-game-4/
15
Rapid Prototyping
Favour rapid prototyping during knowledge crunching sessions. Business users like nothing more
than screen mock-ups, as it reveals so much more about the intent they have behind a product. Users
understand UI, they can interact with it and act out workflows clearly.
Another form of rapid prototyping is to capture requirements in code. Greg Young calls this code
as analysis. Again business users will love the fact that you are writing and creating before their
eyes. Starting to code will help focus analysis sessions. Starting to implement abstract ideas from
knowledge crunching will enable you to validate your design. It also helps to avoid you only thinking
abstractly which can lead to analysis paralysis.
Coding quickly helps create your powerful questions. Helps find missing use cases. Use the code to
identify and solve the problems. After an hour or so of talking see if you can create a code model of
your brainstorming. I often find creating code quickly helps to cement domain concepts and speeds
up knowledge crunching as the team is deeply engrossed in learning about the domain.
Remember only create a code model of what is relevant and within the specific context to solve a
given problem; you cant effectively model the entire domain. Think small and model around rules
then build up. Most importantly remember that you are writing throw away code, dont stop at the
first useful model, and dont get too attached to your first good idea.
16
17
without it a lot of the design breakthroughs would not happen. It is this deeper design insight
that makes the software useful and able to adapt as and when the business processes change.
If its not possible to sit with your domain expert then join her for lunch. Spend as much time as you
can with her, learn as much as possible. You will never gain an insight into a domain from weekly
project meetings. You must eat, sleep and breathe it. Read around the subject; immerse yourself in
it. You will produce better software.
Be Careful What Youre Asked For
Be wary of customers asking for enhancements to existing software as they will often give
you requirements that are based on the constraints of the current systems rather than what
they really desire. Ask yourself how often you have engaged with a user to really find
the motivation behind a requirement. Have you understood the why behind the what?
Once you share and understand the real needs of a customer you can often present a better
solution. Customers are usually met by surprise when you engage them like this, quickly
followed by the classic line: Oh really I didnt know you could do that? Remember, you
are the enabler, dont blindly follow the users requirements, business users may not be able
to write effective features and express goals. You must share and understand the underlying
vision and be aware of what the business is trying to achieve in order to offer real business
value.
.
18
Subdomains
Large models can be broken down into subdomains in order to focus on specific areas of the domain
to create more focused smaller models. Many of these subdomains will be generic to any enterprise
business software such as reporting and notification needs. These subdomains, which do not define
the application are referred to as generic domains. The areas that distinguish your companys unique
product offering from a rivals and defines what gives it a competitive edge in the market are known
as your core domains. The core domains are the reason why you are writing this software yourself.
The remainder of the subdomains that make up a large-scale applications are known as supporting
domains.
One Model To Rule Them All?
It may seem sensible to model the entire problem domain using an enterprise model.
However this can be problematic due to the fact that it will need to cater for all the needs
of your domain. This will render the model too complex or overly generic and devoid of
any meaningful behaviour. If you have large systems it is far better and more manageable
to break down the problem space into smaller more focused models that can be tied to a
specific context.
.
19
The figure below shows how the domain model of an e-commerce application can be distilled into
subdomains.
20
The distillation of knowledge after sessions with domain experts should reveal whats unique and
important about the application you are about to create. The subdomains can be separated into core,
generic and supporting domains as shown in the figure below.
21
The distilled domain of e-commerce sorted into core, generic and supporting domains.
In order to know where to invest the most effort and quality its crucial to understand where the core
domains are as these are key to making the software successful. This knowledge is distilled from
knowledge crunching sessions working in collaboration with domain experts to understand
whats the most important aspect of the product under development.
Core Domains
To understand whats core to the product that your business is asking you to develop you need to
ask yourself: What are the parts of the product that will make it a success? Why are these parts of
the system important? And why cant they be bought off the shelf? In other words, what makes
your system worth building?
The core parts of the system represent the fundamental competitive advantage that your
company can gain through the delivery of this software. Whats core is not always obvious.
If the generic domains should be bought in and have little development, then the core domain is the
polar opposite. The core domains will require your best developers, your commandos if you will.
22
The core domains may not make up the lions share of your companys technology but they will
require the most investment.
What is core will certainly change over time. If you are successful competitors will mimic, so the
core domain must evolve in order to set your business apart from the rest and keep it ahead of the
game. Its vital that the development team take this on board and ensure they are in synergy with
the values of the software and the business.
The Core Domain of Pottermore.com
Pottermore.com is the only place on the web were you can buy digital copies of the Harry
Potter books. Like any e-commerce site it has the ability to browse products, store products in
a basket and checkout. The core domain of the Pottermore site is not what the customer sees,
but rather what they do not. Pottermore books arent DRM-locked , they are watermarked.
This invisible watermark allows the books that are purchased to be tracked if they should
be hosted illegally on the web. The core domain of the Pottermore system is the subdomain
that enables this watermarking technology to deter illegal distribution of a book without
infringing on the customer e.g. she can copy the book to any other her devices. This is
whats most important to the business, what sets it apart from other ebook sellers and what
ensures the system was built rather than being sold on iTunes or other ebook sellers.
http://www.futurebook.net/content/pottermore-finally-delivers-harry-potter-e-books-arrive.
23
manager will refactor the press release until the feature offers real value for the customer.
At all times Amazon are focused on the customer and ensure that they are clear about the
advantage a new feature can bring before they set out with development.
http://www.quora.com/What-is-Amazons-approach-to-product-development-and-product-management
Generic Domains
A Generic Domain is a subdomain that can be found in many large business systems. An example
of a generic domain is an email sending service, an accounts package, or report-suite. These
subdomains arent core to the business, but the business cant operate without them. As these
subdomains arent core and wont give you a competitive edge it doesnt make sense to spend a
lot of effort or investment in building them. Instead look to buy in software for generic domain.
Alternatively use junior developers to build these systems, freeing up more experienced resource to
work on whats core to your business.
Note, however, that a business defined by communication and targeted emails on limited time offers,
like a Groupon or Wowcher, could have its core domain as a sophisticated email/CRM system. What
is core to one business may well be generic to another.
Supporting Domains
The remaining subdomains in the system are defined as the supporting domains. These are
subdomains that, while not defining what your system does, help to support your core
domains. For example, Amazons supporting domains would be the functionality that enables a
customer to browse a catalogue for products. Amazons product browsing functionality doesnt
define it as a company and neither is it that different from any other e-commerce site, but it does
support the tracking of user journeys in order to feed a recommendations engine.
As with the generic domains, if possible, you should look to buy off-the-shelf solutions. Failing
that, do not invest heavily in these systems; they need to work but do not require your prolonged
attention. Its important to note that you may not always need to implement a techniqual solution
to a supporting domain. Perhaps a manual process could meet the needs of the business while
developers focus on the core domain.
24
In this instance the business want to learn quick and fail fast without putting in a lot of upfront
effort.
The first version of a product that is not well understood by the business may not be well crafted.
This is fine as the business is unsure if it will be invested in over time, and the development team
should understand why the business want speed of delivery over supple design. However, if the
product is a success and there is value in a prolonged investment in the software, you will need
to refactor in order to support the evolution, otherwise the technical debt racked up in the rush to
deliver will start to become an issue.
25
Multiple Models.
26
Context Game
In order to demonstrate the importance of modelling in context and to reveal multiple models within
the domain you can employe another facilitating game. The Context Game, a game that I learnt from
a Greg Young , helps to make it clear where an additional model is require to map the problem space
effectively.
You can introduce the game into knowledge crunching sessions when you think you have an
overloaded or ambiguous term. Split the group into smaller groups of developers and business
experts. You should split the business experts by department or business responsibility. Give them
20 mins to come up with a definition on what the term or concept means to them in their part of
the business, using the developers to capture the knowledge. Then bring the whole team together
to present their views on the concept.
You will find that different parts of the business have different views on the shared terminology.
http://codebetter.com/gregyoung/2012/02/29/the-context-game-2/
27
Where the business functions have a difference of opinion this is where you need to draw your
context lines and create a new model. This is shown in the following figure with the product concept
exisitng in many different contexts.
28
29
do this you must understand and share the vision and ultimate goal that the software is expected
to meet. This Understanding will enable you to include only the most important features of the
product and ensure it delivers the value expected by the business.
31
dont exist in the problem domain but have been discovered and labelled during modelling in the
software.
The team must communicate with each other using the ubiquitous language. The development
team must use it in code, and the domain experts must use it when talking to the team. The
benefit of a shared language removes the need to translate from business speak into tech and
vice versa. It also removes the possibility of ambiguity and misinterpretation as everyone
understands the meaning behind the concepts.
The ubiquitous language should be clean and concise. Technical terms should be removed in order
not to distract from business concepts. Likewise domain terms not relevant for the software under
creation must also not be allowed to cloud the shared language.
Validating The Model Out Loud
Linguistic consistency can be used to validate the usefulness of a model. For example listen
to conversations about the model and focus on concepts in the design that dont fit or when
the model cant easily satisfy business scenarios.
.
32
33
34
In order to better understand a feature and its behaviour, scenarios are written to describe the feature
under different use cases. Scenarios start with an initial condition, the Givens. It then contains one
or more events, the Whens, and finally the scenario describes the expected outcomes, the Thens.
The scenario below shows the behaviour of the feature for a customer who has never claimed for
an undelivered order.
Scenario: Customer making his first claim
Given I have not received my items
And I am a customer that has never notified customer services of an undelivered order
When I notify customer services
Then I should receive a replacement order
In addition to being a light way of capturing requirements the scenarios provide acceptance criteria,
which can be used by developers and testers to determine when a feature is complete and by business
users to confirm to them that the team understand the feature.
The next scenario describes the behaviour for a customer that has already made a claim.
Scenario: Customer making his second claim
Given I have not received my items
And I am a customer that has made a successful claim for a replacement order
When I notify customer services
Then I should be contacted by customer services
Using this method of capturing requirements removes the ambiguity that traditional requirements
documentation can result in whilst also heavily emphasising a focus on the domain language. The
features and scenarios themselves are a product of a collaboration between the development team
and business experts and can help to shape the ubiquitous language.
35
Domain experts should object to inadequate terms or structure in the language or model
Developers should watch for ambiguity or inconsistency
Validate assumptions about the ubiquitous language by talking to domain experts
Validate out loud and confirm you ubiquitous language with linguistic consistency
If a domain expert doesnt say it it shouldnt be in the language
37
It is important when developing the application that you isolate models within subdomains to
avoid the blurring of responsibilities which can lead to code that resembles a Big Ball of Mud.
A single view of an entity in the domain for all subdomains can quickly become a problem.
38
You can see from the diagram above that the product class looks like it should belong to an enterprise
model. An enterprise model is typically used to a create a model of the entire problem domain.
Enterprise models can quickly become large and unwieldy due to all of the contexts they need to
serve, as is shown in the following diagram.
This is the manifestation of the Big Ball of Mud pattern as discussed earlier. A change to logic in
one of the subdomains will have an undesired knock-on effect to unrelated subdomains due
to the interwoven code and the lack of clearly defined boundaries of responsibility.
39
communication boundary so that all models can collaborate to produce the functionality of the
application.
Domain-Driven Design introduces the concept of a bounded context. A bounded context wraps
each model and ensures that the code it contains is solely focused on that specific context.
Any issues that are outside of the bounded contexts boundaries should not distract from its
responsibilities.
40
A layered architecture pattern per bounded context and not per application.
The following figure shows the that the Product class exists in two different contexts defined using
namespaces.
41
42
43
44
45
46
Note however that bounded contexts dont always have to have separate data storage and can exist
in the same solution and class library project separated only by namespaces and different database
table names.
What Is A Composite UI?
A composite UI is a user interface made up of loosely coupled components; bounded
contexts.
.
47
business request. It is fundamental to understand how the bounded contexts in your domain interact
and collaborate to solve business problems. This collaboration map, know as a context map can help
to validate your bounded contexts and your understanding of the problem domain.
In many ways the communication between bounded contexts is often more important in terms of
domain knowledge validation than the bounded contexts themselves. A context map exposes the
systemwide relationships between bounded contexts and shows how subdomains interact. It
can also help to reveal issues with communication and workflows within the business.
48
Firstly the shopping context uses the allocation context to determine if all of the items in the
customers basket are available to purchase. Once this is determined it passes the list of products
to the shipping context which calculates the shipping costs for the available products. Finally the
shopping context passes the list of products and a customer id to the pricing context. The pricing
context then calculates the prices of the products as well as determining if there is any discount for
the customer from the loyalty context.
A simplified view of the context map, as shown in the figure below, can be easily drawn by any
member of the team to aid discussion of business processes and workflows.
49
You can see that each of the Bounded Contexts are responsible for a specific subdomain within
the e-commerce application. The Context Map gives a high level view on how each of the contexts
interact. The Context Map is not only useful to the development teams, it can also demonstrate
issues with process and workflow across the business that they may not have been aware of.
50
Use an Anti Corruption Layer to integrate with code you dont own or cant change.
The translation map, shown in the following figure, works in a similar manner to the adapter pattern
in that it transforms the API of another context into an API that you can work against. The diagram
below shows how the transformation occurs between the bounded contexts.
51
52
Shared Kernel
If two teams are working closely in the same application, on two separate bounded contexts that
have a lot of crossover in terms of domain logic, the overhead of keeping the teams isolated and
using translation maps to translation from one context to another can be too much. In this instance
it may be better to collaborate and to share a part of the model to ease integration. This pattern is
of particular use if you have two bounded contexts in the same subdomain that share a subset of
domain logic. The diagram below shows two bounded contexts sharing a sub model.
53
It is important to ensure both teams share the code and dont implement updates without first
agreeing the changes and the impact of those changes. I also find that a shared kernel is often
best used in the same subdomain as shown in the diagram above.
54
Publish-Subscribe
The publishsubscribe messaging pattern which follows an event-driven method of programming,
where publishers send events (as messages), of something that has occurred, to subscribers that are
unknown to them. It is then up to the subscriber to register interest in the message being sent.
In the diagram below we can see how the sales bounded context communicates with other bounded
contexts by publishing events. Many different integration methods can be used to transport the
messages such as message queues and web services.
55
56
Customer-Supplier (Upstream/Downstream)
The following example, shown in the figure below, shows the relationship between a pricing context
and an allocation context. The pricing context is reliant on the allocation context to tell it the
availablity of items, in order for the pricing context to total the sale. If the business wanted to
enhance this feature and give lead times to the out of stock items, the team responsible for pricing
would need to ask the allocation team to update their solution to not only return if the item was in
stock but also include a lead time for when stock would arrive.
The two teams would be in a Customer-Supplier relationship, with the team responsible for the
sales context taking the role of customer and the team responsible for the availability context taking
the role of supplier. It is important that both teams understand the business intent and purpose of
a change to ensure that they are working towards the common goal. It is also important that the
teams collaborate on the changes to the boundary and the API of the availability context.
Conformist
In the example I gave for the Customer-Supplier team pattern it was assumed that both teams were
working in the same organisation and so were part of a larger team that would naturally help each
other out. However if you find that you are downstream of a team outside of your organisation, or
working with a team that is not as flexible when asked to alter boundaries then you will fall into the
Conformist team pattern. Under this relationship you have to live with the boundary defined by the
upstream team. In order to work effectively with the other team it is sometimes better to confirm
to their published language and model rather than spend lots of effort on translations through the
use of an Anti Corruption layer.
57
Partnership
If a business wish requires changes to multiple bounded contexts in order to be delivered then
teams must work in a partnership. The different teams responsible for the various bounded contexts
must work together on the common goal and have a shared understanding of the context map and
integration points around each of their bounded context.
Context Maps
A context map reflects the way things are right now. It shows the integration methods
and points between bounded contexts as well as the patterns of team work.
Context maps are a key concept, they define how bounded contexts interact and provide
the glue to integration across the domain.
Integrating Bounded Contexts
Anti Corruption Layer
* Use to isolate and integrate with legacy systems
Open Host Service
Publish-Subscribe
Shared Kernel
Patterns for team work
Customer-Supplier (Upstream/Downstream)
Conformist
Partnership
59
A Clean Model
The rules, polices, concepts and workflows of the domain should be represented in the domain
model, separate from the presentation and persistent concerns. The domain model is where you
will invest most of your time. You will work closely with domain experts to produce a useful model
to solve problems within the domain space. Even though it will only make up a small portion of the
code base it is the most important artefact. This is because the UI and persistent concerns will, to a
large degree, remain static, its the rules and policies of your business that will need to evolve over
time. The area of the code base that represents these rules and policies must be supple enough to
change with it.
In reality only a small part of your application will represent a model of the domain, the rest will be
taken up by infrastructural and presentational responsibilities as can be seen in the diagram below.
60
The code that represents the domain model only makes up a small portion of the overall code base.
Persistence Ignorance
The figure below shows a very simple domain model for financial loans. The objects in the
diagram represent concepts in the domain and are simple .net classes also know as POCO (Plain
Old C# Objects). These classes are free from infrastructure concerns and are completely persistence
ignorant.
61
The domain model is ignorant of any persistence concerns. When designing the model we dont
start first with a data model, instead we start with the code model. We strive to keep the model pure
and only compromise if our persistence mechanism deems that we must.
62
Try not to model real relationships instead define associations (meaningful connections) in terms of
invariants and rules in the system. In real life a customer has both a credit history and a contact email
address but how often would you come across a rule that in order to purchase an item a customers
credit history must be a good and they must have an email address starting with A. Instead group
behaviour and data together in order to satisfy the needs of the problem domain rather than
what you think might belong together.
As we are not concerned with modelling real life the domain model cannot be deemed as being
wrong or right rather it should be viewed as useful or not for the given problem it is being used to
solve.
63
Hands On Modellers
Any member of the technical team that has a say in how the model evolves must be hands on. They
must have face to face time with the domain experts and the ability to modify and create code.
There is no place for ivory tower architects that do not have an investment in the domain and the
code base. Its crucial to be able to represent a model in code that has synergy with the problem
domain. It is this hands on approach that will enable deeper insight and breakthroughs which lead
to greater understanding of the domain.
64
A Value Object.
5
6
7
8
9
public Money()
: this(0m, new SterlingCurrency())
{
}
10
11
12
13
14
15
16
17
18
19
20
21
65
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Equallity overrides
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
66
67
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
Entities
An entity represents a concept in your system that is defined by its identify rather than is attributes.
An example of an entity is an order of an e-commerce site. When an order is created it is given an
identity which will never change. However the details of the order may change, for example the
customer may want to change the shipping address or add additional items to the order. Entities are
mutable, their attributes can be altered but its identify will remain consistent. Therefore to compare
two entities we would compare only on identity, regardless of any similarities with attributes. Entites
are dedicated to identity keep attributes within them to a minimum. Instead push logic out into small
and focused value objects.
An Entity.
6
7
8
9
10
11
12
13
14
_retail_price = retailPrice;
_options = new List<Option>();
15
16
17
18
19
68
20
if (!selling_price_matches(new_price))
throw new PricesNotInTheSameCurrencyException(
"You cannot change the price of this product to a different\
currency");
_selling_price = new_price;
}
21
22
23
24
25
26
27
28
29
30
31
if (savings.is_greater_than_zero())
return savings;
else
return new Price(0m, _selling_price.currency);
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
69
70
4
5
6
7
8
9
10
11
12
this.id = id;
13
14
15
16
17
18
19
public TId Id
{
get { return this.id; }
}
20
21
22
23
24
25
26
27
28
29
30
31
32
33
71
34
35
36
37
38
39
40
41
42
43
44
72
However we can ensure consistency is ensured by splitting large object grpahs and treating the
sub groups of entities and value object as an aggregate - an atomic unit. The aggregate forms a
boundary around the objects and controls access, ensuring changes dont leave the collection in an
invalid state.
73
74
An aggregate root acts as the entry point into the aggregate. No other entity or value object outside of
the aggregate can hold a reference to any object within the aggregate. Objects outside the aggregate
can only reference the aggregate root of another aggregate. Any changes to objects in the aggregate
need to come through the root, the root act encapsulate the data of the aggregate and only exposes
behaviours to change it.
75
Domain Events
Domain events signify things that have changed within the model. Events can be used to record
changes to a model in an audit fashion or they can be used as a form of communication across
aggregates. A lot of the time an operation on a single aggregate root can result in side effects that
are outside the aggregate root boundary. Other aggregates within the model can listen for events
and act accordingly.
For example consider the basket within an e-commerce site, every time a customer places an an item
in his basket we want to update the recommended products that are displayed on the site. In this
scenario after a domain event is raised with details of the basket each time it is modified. The event is
subscribed by the recommendatios bounded context. Without using a domain event we would need
to explicitly couple the basket bounded context to the recommendation context. Domain events give
a more natural flow of communication and focus on the when i.e. When a customer orders they
will receive loyalty points.
Domain Events.
In the following code snippet we see a domain event being published from a basket.
A basket publishing the event of a product being added.
1
2
3
4
5
6
namespace Domain.Shopping
{
public class Basket
{
private BasketItems _items;
private Guid _id;
7
8
// ....
9
10
11
12
13
76
77
DomainEvents.raise(new ProductAddedToBasket(this._id,
_items.ids_of_items_in_basket()));
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// .....
32
33
In the following code snippet we see a recommendation service handling the event raised by the
basket.
78
namespace Domain.Recommendations
{
public class RecommendationsEventHandlers
{
// ......
7
8
9
10
11
12
13
Domain Services
Domain services encapsulate domain concepts that just are not naturally modelled as value objects
or entities. They can represent behaviours that have no identity or state. They can also orchestrate
workflow that uses entities of value objects. A good example of a domain service is a shipping
calculator. This service is a business function that, given a set of product IDs and a collection of
courier entities, can calculate the cheapest shipping cost.
A Factory.
79
In the following code snippet we see that a customer entity has a factory method to enable an address
to be created with a valid customer id.
80
// ...
8
9
10
11
12
13
14
Repositories
A Domain Model needs a method for persisting and hydrating an Aggregate. As an Aggregate
is treated as an atomic unit, you should not be able to persist changes to an Aggregate without
persisting the entire Aggregate. A Repository is an infrastructure concern and so it is not always
necessary to abstract away the underlying framework doing all the hard work. It can be more worth
while to lean on ORM frameworks to act as a Repository; examples include Nhibernate, RavenDB
and Entity Framework. A lot of developers get hung up on this pattern. Think of it simply as
a method of persistence and rehydratation. Treat it like infrastructure and dont get hung up on
abstracting it away.
81
A Repository.
Application Services
An Application Service at first sight may be similar to a domain service in terms of responsibility,
however it focuses not on the domain concerns but rather on the concerns of the application. The
Application Service calls into the domain service and domain entities in order to orchestrate business
requests. It does not contain any business logic only orchestration, security, logging and other
infrastructure concerns.
An application service.
82
83
Infrastructure Services
Infrastructure services are a third type of the overloaded term service. They are primamrly used
with the infrastructure layer to abstract purely technical concerns. For example an infrastructure
service can be used to simpliy they interface of sending an email or sending a message on a message
queue.
84
In the following diagram we can see that a view requires information from multiple aggregates.
Using the domain model in its present state would require a lot of unnecessary objects being pulled
from the database in order to provide a tiny subset of data for a screen view or report. This clearly is
not what the domain model was design to do and is outside the context of where the model should
be applicable - put another way the domain model isnt a great pattern for display purposes.
A better way to serve the needs of displaying the state of the domain is to use separate domain view
objects that are tied to a screen or report view. The domain views can be generated direct from the
database as in the figure below.
85
Domain views can also utilise events to create materialised views or a separate presentation model
based on views.
86
87
Life without a domain model for complex products produces code that does something
useful but without explaining how
The only truth
The domain model represents the single model for analysis (to understand the domain)
and design (software implementation). Care for your domain model like you would a
small plant, make sure you keep it updated.
There is a synergy between the code and the model
Dont model real life
Dont blindly model reality e.g. customers > Orders
A model is an interpretation of reality that abstracts only what is relevant to solving the
problem
Dont let the truth get in the way of a good model
* There is no spoon, there is no customer
Model useful abstractions of reality, there is no real life in the world of code
Forget all your OO training about nouns and verbs
Exclude irrelevant features, model only what is useful
A model is only useful for a time
New problems may require update to model
Care for the code quality of your domain model. There are two reasons why you want
to make sure that the code quality of the domain model is top-notch:
* The domain model is the foundation of your application, if it is bad, the whole thing
can fall apart
* It changes a lot. There are very few areas in your code that are going to change so
many times as the domain model
POCO free of infrastructure concerns; keep simple, readability over smart code.
A Model is defined within a context
Putting effort into defining contexts and boundaries is essential to get to good models
A model is a method for handling complexity
88
89
// ....
5
6
7
8
9
10
11
12
13
if (item_quantity.contains_more_than(new Quantity(50)))
throw new ApplicationException(
"You can only purchase 50 of a single product.");
else
get_item_for(product).increase_item_quantity_by(
new Quantity(1));
14
15
16
17
18
19
}
else
_items.Add(BasketItemFactory.create_item_for(product, this));
20
21
22
23
24
However in future months other developers may not understand why such a rule exists. Instead we
should understand the intent and why the rule exists and name the portion of code accordingly. As
it transpires such a rule is enforced by suppliers in order to prevent sites acting as wholesellers. With
this knowlegde we can make the code explicitly reveal this rule by wrapping it in a class which will
reveal a deeper insight and understanding of the domain. This refactoring is seen in the following
code snippet.
// ....
5
6
7
8
9
10
11
12
13
if (_over_seas_selling_policy.is_satisfied_by(item_quantity))
get_item_for(product).increase_item_quantity_by(
new Quantity(1));
else
throw new OverSeasSellingPolicyException(
string.format(
"You can only purchase {0} of a single product.",
OverSeasSellingPolicy.quantity_threshold));
14
15
16
17
18
19
20
21
}
else
_items.Add(BasketItemFactory.create_item_for(product, this));
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
90
91
Learn To Unlearn
Dont get attached to ideas, trial and error is required to reveal concepts in the domain that
will help you to solve business problems. Code within the testing namespace alongside the
92
tests until you are happy with the design, you will be a lot happier to spike solutions and
throw away a useless model that you havent committed to the application namespace.
.
Constant refactoring toward deeper insight will help to create flexibility and this produces
a supple design. Places where code changes a lot will become more flexible and will help
facilitate change.
Martin Fowler model principle Design a model so that the most frequent modification of the
model causes changes to the least number of types.
93
94
DDD does prescribe a set of design best practices, patterns and building blocks which are
often mistakenly thought as core to applying DDD to a product. Instead think of these design
artefacts as merely a means to an end used to represent the conceptual model. The heart
of DDD lies deep in the collaboration between the development team and domain experts to
produce a useful model.
95
96
Use CRUD for bounded contexts with low complexity. You are not a bad programmer if you
dont have a domain model.
97
98
99
100
101
11 A Modelling Example
11.1 Case Study
102
Appendix
103
Version History
This book is a work in progress. Here is a list of updates by date:
4th Feb 2013:
Refactor for Deeper Design Insights: Making The Implicit Explicit
104