Notes 20 January 2004
Domain Driven Design (VIII)
Guest Author: Eric Evans
Russ: Let’s start with Strategic Design (Part IV) — what do we need
it for? How about considering the ways to get in trouble on the extremes.
How do you look at a system and understand whether we’re doing what Eric’s
doing, or one of the bad alternatives he discussed. (p. 328, halfway down).
The more systems I see, the more surprised I am by the range of systems
I see. Some of it’s really good, some of it’s kind of scary. This was
a good way of describing a large class of the problems, so I thought it
was a good way of introducing tonight’s topic.
(Russ referred to text in second half of second paragraph p. 328, “monolithic”
vs. “ad-hoc”, avoiding extremes).
Dave: Systems glued together out of lots of pieces are also often full
of contradictions, an unresolved argument about the system.
John B: Like Unix command-line tools, having varying views of the world?
Russ: Is it ad-hoc components, or ad-hoc interfaces?
Mike: the alternative being an enterprise-wide bus, a common interface
for things to plug into, that tries to be everything to everybody. It’s
hard to get systematic designs through, because you have many sponsors
and many forces.
John B: And you have to actually establish the protocols, how to get
things to communicate.
Mike: My company has tried for the system-wide bus, and it seems to address
the needs of only a small number of the people who want software.
Russ: The author is talking about more than just the technical breakdown
of the system, but about the model, the vision of the system.
Eric: Dave said an interesting thing about small pieces composed together
being sort of a dialogue or debate about world views of the system. That
is very much about what Chapter 14 is about.
Phil: A middle approach to bridging the extremes is to compose the pieces,
then to look at what you have, and refactor the composition into the thing
it needs to become.
John B: I see on p. 389, there’s a discussion about refactoring to Shared
Kernel from Separate Ways,
Eric: Refactoring is the *means* by which you change strategies, rather
than the strategy you use.
Phil: Refactoring as using the code to change your ideas, you don’t see
that as well as refactoring as a mechanism?
John B: Eric has listed all the ways to evolve and change the implementation
of the model that he can think of, rather than the actual change of the
model as ideas.
Eric: All the ones I wanted to recommend.
Tracy: If I understand, Phil, you’re talking about refactoring as a process
Phil: Yes, learning, and eventually you get to a global view, a similar
result. The code is telling you what the model has to be.
Eric: I’d like to shift rails a bit, I start from a more fundamental
premise. I start from an observation that on any large project, with more
than 10 people, you will have more than one conception of the domain that
the system is based on. More than one conception means more than one domain
model, and that will affect choices about design. You can just plunge
ahead not realizing that, and not realize when one person’s concept was
controlling the design and when another person’s different concept was.
So that’s where BOUNDED CONTEXT comes in. You would like to have a sense
of which model applies in what part of a larger process. There is sometimes
a very clear situation, where you have smaller subsystems worked on by
different people, and each can be its own model, its own context. But
with a large subsystem, you’re more likely to end up with multiple inconsistent
views. This chapter is about understanding that there are different points
of view, and different ways to describe things, and that becoming aware
of these different perspectives is important in dealing with larger systems.
The “Blind Men and the Elephant” story would be less interesting
if each blind man knew that he had a separate point of view on the same
thing. And we want things to be less interesting in this case, with software
development. So you want to start out by mapping out the territory as
it exists, before making changes. So tactics like CONTINUOUS INTEGRATION
support the decision to have a unified model within a single BOUNDED CONTEXT.
This sort of CONTINUOUS INTEGRATION is the code, *plus* people consciously
synchronizing their concepts with one another through exercise of the
UBIQUITOUS LANGUAGE. But there are other successful ways of connecting
John B: System model vs. domain model? Most of these patterns, to me,
seem like ways to integrate a system rather than a domain.
Eric: Usually people think of system integration as connecting a set
of distinct programs. But you could create two systems based on the same
domain model. Or you could create a program which was internally split
between two domain models. You’d prefer to split your components along
the boundary of the variant models. But I’ve seen components and subsystems
(even classes!) with multiple models reflected in their implementation.
John B: Is Extreme Programming’s continuous integration a different concept
Eric: I think it is the same thing. The XPers are exactly correct about
continuous integration with a context, within a single model conception.
If you need it to interoperate, you need continuous integration of the
*code*, and also of the *model*.
John B: They’re fumbling that direction with the System Metaphor.
Eric: And co-location.
Phil: And pairing.
Russ: I’ve seen a single developer with 3 different bounded contexts
with name clashes in the same source file.
Eric: Three *unbounded* contexts.
Russ: Intermingled contexts.
Eric: If they had bounded those three, they would have been in good shape
since they would have been separate; or more likely they would have unified
them to remove the contradictions. But knowing what the practices help
you achieve, knowing *why*, allows you to adjust to situations, to know
where you are at. And knowing when to stop. You can’t CI a whole company,
you can’t co-locate everyone. And at a certain scale, the overhead of
continous integration in a large system becomes too much. So by making
a context map, you tell yourself, your teams, where you are making CI
work, where you can run XP full-out within a single bounded context, and
where you want to establish a boundary.
Russ: There are two very different notions going on here. 1: You and
I have different models of a system, with shared understanding of a subsystem,
and no assumptions about the non-overlapping parts — two separate but
possibly overlapping models. Vs. 2, if you and I were working on things,
and there was an overlap of concepts which were not part of the shared
kernel, but were in conflict. It’s an interesting distinction to talk
Eric: Yes, that’s a very instructive example. So in the first case, let’s
say there *is* a shared set of concepts. What I call SHARED KERNEL. That’s
both concepts and code.
Russ: So if you were working on the dessert and I were working on the
floor wax, we wouldn’t have to interact on those distinct parts of the
Chris: Until someone comes up with a product which is both dessert and
Eric: So in this case, you might subclass the thing we’ve already got
in hand, say for me working on the dessert, I’d say a floor wax is a special
kind of dessert, and you with the floor wax, you’d say a dessert is a
special kind of floor wax.
John B: Elephant is a subclass of wall, floor, snake, tree, and rope.
Eric: The blind men were lucky, that they were each looking at a single
part of a larger system. But with desserts and floor waxes, the systems
are more complex. At first we might not have any problem. One way is we
can say we go with your model, one way is to go with my model, or one
way is to come up with a new model that meets everyone’s needs. Let’s
say we introduce a new abstraction.
John: They’re both Sprayables.
Eric: So we’ve discovered both the dessert topping and the floor wax
Dave: It opens up new product opportunities because you could make something
that’s a floor wax, dessert topping, and bug spray.
Eric: I think the marketing department would have trouble with that last
Jeff: Maybe lip gloss as something in the same unified space as floor
wax and dessert toppings.
Russ: How are we making these trade-offs to decide how much of the system
should be unified?
Eric: It’s not always unification. you might have a system that’s grown
to the point where integration has become burdensome, so you decide to
split things off and go separate ways.
Dave: As things scale, I’ve never seen it be easy to abstract a core.
Chris: Could you abstract out a framework?
Eric: I’m not talking about a huge company with a “chief architect”
someplace dictating to everyone in the company “these are the objects
Phil: During the development of J2EE at Sun, different groups had a concept
of “qname” that was slightly diffferent. We got everyone in
the same room and agreed on a common interface that everyone could use,
and we created a JAR with just qname in it that everyone could use.
Eric: That’s a Shared Kernel.
Phil: Right, and it’s a little thing, not a big one.
Dave: What was the overhead involved in getting all the interested party
together in a room to make that decision?
Phil: You have no idea…..
Eric: The first thing is to have contexts that are bounded. And have
a map so you can say, “This thing belongs to this context.”
John C (?): What about the tragedy of the commons problem, since the
Eric: But all we’re agreeing on is the _boundaries_.
John B: “Good fences make good neighbors.”
Jeff: Get that down.
Eric: You want to know, “Am I in my own context, where I can go
my separate way, or am I in a shared context where I need to integrate
with someone else?”
John C: I’m thinking of a company where there are two products, one of
which is a big revenue producer, and another that gets less resources.
The one that makes a lot of revenue basically gets to disregard the needs
of the other one.
Eric: That sounds like a case for Conformist, because of the power differential.
Eric: I’m not saying the company has some global enterprise-wide context
map. I’m just saying for your own project, identify the different contexts
Eric: Even in a one-person project, you’ll have multiple contexts, like
“current understanding”, vs. “last years understanding”.
(The code you wrote last year, but haven’t had a chance to refactor to
your latest insight.)
???: What about upstream/downstream suppliers where one is stuck with
???: “Ball and chain” pattern.
(Mike: discussion of a protocol with a large installed base with messaging
to distributed clients — difficulties with changing the protocol to enrich
Eric: So your clients have a presumption, a model for what the messages
in the protocol mean. And how they handle the messages reflects that model.
If they get back a response message in a different format than the one
they asked for, then they have to handle that. They have to handle the
fact that the variations in the new model are exposed by the new protocol.
So what made this hard is that within your context, you changed your domain
model, but the other systems at the boundary are related to you via an
OPEN HOST SERVICE. The interface expresses a frozen model.
Mike: Because so many groups are connected to it.
Eric: And part of the problem was a change in the model as expressed
in the protocol. If you had just made a slight re-arrangement of the same
information, it would be no means as difficult. There’s a technical dimension
to the problem, but there is importantly, a conceptual one. And the conceptual
difference is what it makes it hard.
John B: Sounds more like ANTICORRUPTION LAYER rather than OPEN HOST SERVICE.
Mike: We have an invariant API.
John B: If you had an ANTICORRUPTION LAYER, you would be able to fold
the new protocol into the old one.
Eric: But let’s say he is getting his message data from somewhere else,
a legacy system. So what he does is set up an ANTICORRUPTION LAYER to
translate the old stuff into the new, enhanced model. But it’s the client-facing
side, he’s got clients who are asking for stuff. There might be a few
with ANTICORRUPTION LAYERs because they need to express the concepts of
the message internal in unusual ways, but most of them use CONFORMIST,
expressing his message stream in the same terms.
Mike: We want to enrich the service without affecting the clients who
are not interested in / capable of dealing with the information in the
Eric: They’ve always had Sweet ‘N Low before, but you want to give them
Russ: You can give them more feeds, by establishing a an upstream message
feed that you can translate into Sweet N’ Low for the old clients, and
to Splenda for the new clients. (Arranges two diverging lines of pens
and flatware with a pink paper packet in one line of the V, and a yellow
one in the other line).
Eric: OK, so I understand you have a TRANSLATION LAYER which takes the
new, enriched internal format and emits a message feed in the old format
for your established customer base.
Eric: There’s a stress point on the OPEN HOST SERVICE pattern. If you
have two sets of clients who want different services, it’s somewhat difficult.
OPEN HOST SERVICE says that everyone gets the same thing, everyone can
accept the same protocol. So if your situation is that each customer wants
little, extra bits on the service, perhaps you want a bunch of one-off
translators, one-off versions for the different groups, to keep the primary
protocol simple and clean. Now we end up with more of a classic CUSTOMER-SUPPLIER
relationship for the custom parts of the protocol. That frees most of
the clients from dealing with the special interfaces, and the individual
special needs can be managed without changing anything about the common
John B: You have an off-the-rack interface, and then a set of tailor-made
Eric: But you want it recognized that that’s what you’re doing, that
there is a decision process being made.
Chris: The more I’m listening to this is more like a pattern I applied
in a system I worked on. In this case, the requester specifies the format.
If they didn’t specify, you got the old format. If you needed something
new, something else offered by the current system, the client would change
their format specifier.
Charlie: Do some of the specializations, some of the customizations really
belong on the client side?
Eric: If you’re using OPEN HOST SERVICE, you need to keep it simple and
consistent for you as the maintainer. For variations, you may choose to
make a special adaptation, negotiating it one at a time based on company
priorities or revenue, etc. If you have a custom protocol that only *one*
customer can use, you can change the interface as often as your two groups
agree to. Once there are multiple clients of the protocol, it’s far, far
harder. It’s the OPEN HOST SERVICE situation, where the interface is frozen
Darlene: At what point might you go toward a general solution, a new
protocol with the space to accommodate a new set of variations? Rather
than maintain half a dozen variations on the common protocol?
Russ: Maybe we should define ANTICORRUPTION LAYER, we’ve used it several
(p. 364, ANTICORRUPTION LAYER: picture of the Great Wall of China)
John B: I’m seeing this adapter-service thing, that’s a lot like…
Eric: I use the terms TRANSLATION LAYER and ANTICORRUPTION LAYER. An
ANTICORRUPTION LAYER is certainly a TRANSLATION LAYER. It’s the difference
in intent, in posture, that makes the difference. An ANTICORRUPTION LAYER
defends your system from having to adapt to a divergent external model.
I don’t think you could mechanically tell the difference. But it’s the
difference between a wall and a bridge, almost. A bridge is like a regular
TRANSLATION LAYER, where one side is reaching out to the other, or both
to each other. An ANTICORRUPTION LAYER is protected, a wall, a moat, and
a gate. You don’t have an ANTICORRUPTION LAYER separating you from a protocol
that you designed.
Russ: Maybe a protocol you designed in the past, that you don’t want
to work with any more.
Eric: With ANTICORRUPTION LAYER I make stronger statements about why
you’re doing it. It’s that you are protecting your model from the concepts
on the other side. The concepts on the other side of the wall will mess
you up if you have to try and deal with them.
John B: Not just corrupting data, corrupting your model.
Eric: Your way of thinking. There isn’t a functional distinction between
Mike: The OO-SQL translation layer as one example of trying to bridge
Eric: An ANTICORRUPTION LAYER is one-sided, built by one side to protect
itself. Vs. the Chunnel, a cooperative effort by the British and French
to bring each other together.
Mike: You could think of an O-R persistence layer as an ANTICORRUPTION
LAYER if you have to adapt to an organizational standard which interferes
with how you can deal with things.
John C: A Cartesian to radial coordinate translation.
Eric: More like where you have Cartesian coordinates on one side and
on the other, a tribal society which describes how to find things by how
many days’ walk between locations, considering weather conditions, and
refers to locations by their historical association. You would want to
protect the clean, simple Cartesian model from the complex expression
of locations on the other side.
John B: So let’s say you have an RDBMS with transaction scripts talking
to a database. That’s where you might put a translation layer to protect
(some additional discussion of ANTICORRUPTION LAYER vs. TRANSLATION LAYER
in different contexts)
Mark: Web pop-up blockers are an ANTICORRUPTION LAYER.
John B: They protect you from the advertisers’ protocol.
Eric: By doing complicated gymnastics inside the browser. If you provide
a compatible interface to protect your clients from changes, that’s being
John B: It’s like being CONFORMIST to a layer that keeps squiggling out
from under you, you conform to what the ANTICORRUPTION LAYER presents
and adapt to the changes inside that layer.
Eric: If the old model is nice and clean, if it isn’t a conceptually
difficult translation… unless there were no longer a straightforward
relationship between the new model and the old model, it’s not something
where the service is protecting yourself. I don’t think that offering
Russ: Insulation but not anti-corruption.
Eric: But if the old model were a BAD one, incompatible, a messy, complex
translation from the current system’s model, then perhaps it is an ANTICORRUPTION
LAYER on an outward feed.
Tracy: Maybe I can make a point that will help. So let’s say the new
internal model is the brown sugar. So if the guys that wrote this offer
a new interface that’s sugar, and doesn’t offer the interface of Sweet
N’ Low, then the client might build an ANTICORRUPTION LAYER to defend
themselves from the incompatible new interface.
Russ: So if the motivation is trying to protect your old clients by offering
a translation layer to a protocol they want, it’s different from…
Eric: Yes, the attitude is different.
John B: It’s where there is a meeting of minds (TRANSLATION LAYER) vs.
no meeting of minds, a disagreement (ANTICORRUPTION LAYER).
Charlie: The word “corruption” is subjective itself, it depends
on point of view.
(some additional discussion of ANTICORRUPTION LAYER to attempt to clarify
p. 371, SEPARATE WAYS
Phil: I love the picture for SEPARATE WAYS. You see all those team rowboat
pictures in those motivational posters. Seeing that picture of that one
guy in the rowing shell really captures the feel.
John B: It’s like a standalone context, like your earlier discussion
of STANDALONE CLASS.
Eric: Yes. But separate contexts may introduce duplication. If you have
separate contexts, you can have duplication. But not sharing.
Russ: It’s positive danger to share things between contexts.
Eric: Unless you have a SHARED KERNEL.
Mike: Does SHARED KERNEL drive you to use CONTINOUS INTEGRATION? Or another
specific process to support the SHARED KERNEL.
Eric: Yes, if you have SHARED KERNEL, you have a process that needs to
support it. CONTINUOUS INTEGRATION is an example of one process that could
support it, but it’s not the only way to do it. Frequent integration,
appropriate to its rate of change; having each side supply some test cases,
and each side runs all the shared, compiled test cases. I wouldn’t recommend
in more detail than that, but you do need a process.
John B: So you might have meetings or pow-wows between the teams sharing
the SHARED KERNEL, to negotiate the interface changes, where an XP team
would just go bam, there the interface changes.
Eric: *Within* a context, you can use full-on continuous integration.
Charlie: Does a SHARED KERNEL tend to be more stable than the rest of
Eric: Sometimes, but not necessarily. Sometimes it has the most change
at certain phases of the project, although it has more inertia from the
multiple forces depending on it. You’ve traded away some agility.
John B: You need these patterns in order for XP to work, for changing
the system to make it better?
Eric: The assumption that change makes things better is implicit to XP.
Chris: Does the way that XP works, that you surge forward, changing the
model, in a couple of different contexts. Does that make integration of
two divergent teams’ work difficult at a later point? The lack of detailed
Phil: Just read the tests?
John B: The tests will get you a long way. All the translations will
have to be green-bar preserving.
Russ: That’s where you encounter the greatest risk of the tests becoming
irrelevant. When the model changes, the tests may be making irrelevant
assertions. Incorrect assertions.
John B: The unit tests, yes. Not the acceptance tests. They reflect knowledge
of the domain.
Eric: But those acceptance tests contain some assumptions about the model,
they exist within a context. If the model changes slightly, what the acceptance
tests express may be subtly different.
Jeff: Perhaps if the acceptance tests were expressed in different units,
they might be able to be consistent within a larger framework. Say more
detailed units of time or money or something. That you could translate
the acceptance tests into a common larger perspective, but the new perspective
might have lots of holes in the acceptance test coverage.
John B: But how do you do this in the context of a non-XP team? You have
a document, maybe, but it doesn’t reflect how things really are.
Phil: How things used to be, how things were supposed to be, how we thought
the system was going to turn out.
Chris: Even if those two documents were inaccurate, they are marker points
to bring up subtle points that people might forget. But they provide a
place to start talking, a guide to find out if the two kinds of apples
we’re trying to merge are really two kinds of apples, rather than apples
and something else.
Chris: To the extent you can automate the documentation (TogetherJ was
John B: Supple design assertions, what’s the invariant for an apple?
Those can really help you reveal what the common points of view are between
Russ: Sometimes it’s how the actual artifacts of the code relate drives
you in a direction. What Phil was saying earlier about refactoring driving
you toward better understanding of how things were being used. When the
problem is too big to hold in your head.
John B: The problem is not the technical issues so much that there is
my model and your model, and clearly my model is better than yours, and
there are two sets of (mine, yours) in the room. The difficulties are
more sociological than technological.
Russ: But maybe we aren’t even at this point. We have to decide whether
the models have any correspondences where we can extract some common point
of view. Using diagrams, pictures, descriptions, etc, to see if common
points of correspondence occur.
Charlie: I was once a “swamp guide” for new hires at my company.
There were lots of questions about certain idiosyncrasies in the code
which related to evolution in the company’s business model without the
objects being changed to reflect the new point of view.
John B: The context of “now and then”.
Eric: Similar to Mike’s issue with the different messaging protocols.
He had to deal with the protocol based on “then”, and the internal
model based on “now”, and facing the challenge of how to get
more “now” into “then”.
p. 388: a diagram grouping the “context” patterns in relationships,
from SEPARATE WAYS at one end (need no control of other systems, no communication)
to Single BOUNDED CONTEXT (need high control, high communication).
Russ: Even on our small team, we have three different contexts in which
there’s a “Book” object
Eric: (discussing the diagram) But CONFORMIST has no control and requires
high communication. ANTICORRUPTION LAYER is somewhat similar. Then there’s
a break to a set of patterns which require greater integration, greater
control over other systems and more communication about internals… CUSTOMER-SUPPLIER
TEAMS, OPEN HOST SERVICE, SHARED KERNELs are partway along toward the
single BOUNDED CONTEXT.
Russ: You’re really nice to XML on p. 376.
Eric: I wrote that back in the glory days of XML. We’re all a little
disillusioned these days. I really wanted to talk about XML as a stimulus
to create common languages for interchange.
Eric: The E-commerce enthusiasts for XML as the magic bullet are not
realizing that the really key thing is the common model. The problem isn’t
getting to a common syntax. With a common model, you can reach a common
syntax fairly easily.
John B: The fact that there’s a common syntax, a common way of parsing
it did help take some of the syntax and formatting issues out of the way.
Russ: XML helps you with the easy problems, but not the hard ones, the
conceptual meaning of the marked up object. Here’s a price with a dollar
value. But does it include tax? Not? How are you allowed to interpret
this value you’ve been given, <price><value unit=”USD”>50</value></price>
(brief discussion of XML web services design, what might make it supple,
will good designs win?)
Eric: p. 378, Notice the UML diagram is more compact than the poem!
Mark: What about the second and fifth guy?
Eric: Oops! Guess that was enough to make the point.