Domain-Driven Design
Eric Evans
Addison Wesley, 2004
In many ways, this is two books in one—and not just because it’s 500 pages long. Read broadly, it’s an excellent guide to the evolutionary nature of software design. Read narrowly, it’s about object-oriented design. It’s worth reading for its broad guidance alone, even if that means skipping over some of the application of those ideas.
I particularly like Evans description of supple design, which occupies Chapter 10. He defines a supple design as one that invites change. Outside the occasional one-off, throw-away program, all programs undergo change. A supple design is one that aids, rather than resists, such evolution.
Evans claims "[t]here is no formula" for supple design, but I am less sure. I will claim that his description of the attributes of a supple design correspond to core design principles of high cohesion and loose coupling. If you take building blocks as a metaphor, "suppleness" is the wrong adjective, but the same notions of combination and recombination apply. Designs that demonstrate high cohesion and loose coupling invite change, rather than resist it. And Evans provides much good advice as to how to get there.
Evans is a fan of object-oriented design, and admittedly I am not so much. I appreciate his observation, though, that object-oriented design is not simply about objects. Evans provides a taxonomy consisting of entities, values, aggregates, and factories with notably clear explanations. His discussion of the need to manage inter-object relationships and how to do so is especially lucid.
Both Evans and Löwy write largely about line-of-business applications that model real-world processes. There are interesting similarities and differences in their conclusions. For example, both note that layering is a universally-applied technique—and then go on to apply it in different ways. In Löwy, the layers are Client, Business Layer, ResourceAccess, and Resource. In Evans, they are UI, Application, Domain, Infrastructure. It all depends on what one wants to emphasize, I suppose.
Evans also introduces a pair of terms that have entered the general software architecture lexicon and so deserve mention here. The first is ubiquitous language:
A project needs a common language that is more robust than the lowest common denominator.
p. 25
I agree, but I am not sure Evans goes far enough. I woudl argue that a project (or system) needs not just common language but common concepts, as Jackson describes in The Essence of Software. If you apply Jackson’s concept-based framework, you’ll back up ubiquitous language with both rigourous definitions of those concepts and do so in a manner that is not so tightly coupled to object-oriented design as what Evans presents here. That’s especially helpful if you’re not applying object-oriented design in your system!
The second term is bounded context:
A Bounded Context delimits the applicability of a particular model…
p. 336
Here Evans uses "model" in its traditional sense of a simplified and abstracted representation of some more complex thing. The observation in this definition is both obvious and subtle: it is in the nature of a model that it has limited applicability, i.e., within some bounds. Those limits are what allow for simplification and abstraction. Indeed, in some sense, these boundaries are defined by the complexities that a model does not capture.
What Evans observes is that models, if stretched too far, can become too complex to be wielded usefully. When that happens, architects can return the system to simpler but no less powerful form by separating their system into two bounded contexts, each using a different model. This design maneuver will require introducing a mapping any time the two come into contact. However, if the boundary is chosen carefully, even two models plus the mapping will be simpler than one model stretched too far.
Like any design maneuver, this one can be overplayed. If two systems can share the same model without making it more complex, they probably should. Two models that vary without good reason, plus a mapping between them, is not complexity that any project should want to take on. Do not let bounded contexts become an excuse for skipping the hard work of deriving a unifying model when one is available.
Unless you build work more-or-less exclusively on object-oriented systems, there are portions of Domain-Driven Design that probably won’t apply to your work. But read more broadly, Evans provides broad-reaching insights and advice on software architecture.
© 2025 by Oliver Goldman