I read Eric Evans’ Domain-Driven Design: Tackling Complexity in the Heart of Software nearly six months ago, but I wanted to take some time to mull over my response to it before posting a review.
Reading Domain-Driven Design can be a challenge. It’s taken me a while to sort through all the concepts in my head. It’s also taken me some time to chase down the references and articles related to the book. Eric Evans makes frequent references to design patterns and often cites other books in the software design canon. If you’re not familiar with these, you’ll find the book slow going. It’s definitely worth the effort, however, especially if you work with large codebases.
The key is large codebases. For simple software applications, a straightforward procedural approach to code works just fine. At larger scales, Object Oriented approaches to code work quite well. But neither procedural code nor OO principles give much guidance about large-scale software structures.
After your application grows beyond a dozen classes or so, you need to start thinking about the overall organization of your code. And once you start work on an application with different logical layers or physical tiers, or one that integrates with other software applications, you ought to give Domain-Driven Design a thorough read.
Software applications are tools that help people solve problems. The scope of the problem is called the problem domain, or simply the domain. The process of setting up your software to tackle the problem is called domain modeling. The domain model consists of the core concepts that help users of the software get the job done or the problem solved.
Domain-Driven Design recognizes that software applications have essential features needed to solve problems in the domain as well as supporting infrastructure. It places the core domain at the center of the design process and lets everything flow outward from that. It’s an approach sometimes called onion architecture, in contrast to the traditional “layer-cake” architecture diagrams you often see.
We write software to solve problems, so it makes sense that our software should model those problems as accurately as possible. It sounds so simple!
Sadly, in practice, it’s really hard to get right. Computers force us programmers to think about all sorts of things that have nothing at all to do with the problem we’re trying to solve:
These things can easily overshadow the problem we’re trying to solve. For many applications, the amount of infrastructure code you’ll write will far exceed the amount of domain logic required to solve the problem. And if you’re not careful, this infrastructure code can spread throughout your application, making it very hard to identify the core concerns of your system.
Eric Evans’ book describes how to see the forest for the trees in large-scale applications.
One of the things Eric Evans said after he wrote the book was that he wished he’d put it in a different order. I agree! Here are the three most important concepts discussed in the book, from back to front.
Bounded Contexts are a way to separate concerns within a software application. While the core of your application might deal with video editing or insurance claims processing, you will have other parts of your application that deal with corollary concerns.
If your system interacts with another software application or uses a web service, you obviously have a different context. These third-party components likely have different ways to model the domain, and you’ll need to translate these to your model.
But sometimes it’s not clear when you’ve moved from one problem domain to another. For example, within an employee timekeeping application you might have two subsystems that consider timesheets from a cost accounting perspective and a billing perspective. Though they might look at the same underlying data, the logic of how they work is different.
It’s important to explicitly recognize these boundaries. These edges will help determine the structure of your application.
Domain Modeling helps you determine the essential features of your system. Your code should be the literal embodiment of these features. If it’s a paint application, we’d expect to see concepts like Canvas and Brush and Color. If it’s a airline scheduling application, we’d expect concepts like Seat and Booking and Destination.
Software is an abstract thing. We humans have a difficult time thinking about abstract concepts. The more concrete you can make your core domain concerns, the easier it is for you to reason about.
Ubiquitous Language is the idea that your software development team should be using, as much as possible, the language of your customer. They need to understand the domain as completely as the client does — otherwise they’ll have a hard time designing software to solve the problem!
This is essentially another argument in favor of using real, concrete concepts from the problem domain in your application model. When the junior developer says, “I get exceptions when I assign this SpecialNeedsPassenger to an ExitRowSeat”, the airline executive will have some inkling what is going on. And when the customer says to the lead developer, “Oh no, we always show accumulated vacation within the current pay period” the developer will have some idea of what needs to change in the code.
Much of the book is an exploration of how these three principles can be used to design (or refactor) a software application so that it makes more sense. Eric Evans discusses several diagramming techniques that can be used to illustrate relationships and boundaries in the domain model. He also highlights several design patterns that are helpful as well.
You can get good advice on applying specific techniques from reading blogs and looking at programming Q&A sites like StackOverflow. But it’s worthwhile to explore Eric Evans’ take on these and to get a solid grip on the terminology used by the DDD community.
If you’re a C# developer in particular, it’s easy to get confused by DDD terms like “Value Object” and “Entity” which are also used within the Microsoft .NET Framework. They have special meaning to folks in the DDD crowd.
This is the single most important book I’ve read on large-scale software construction. But it’s a challenging read because you need to know quite a bit about design patterns and have had some experience working on large scale projects.
The book also suffers a bit from the way it’s organized. As Eric Evans mentions in the introduction, the most important parts of the book are Parts I and IV. It’s easy to get bogged down in all the detail in the middle.
But those issues shouldn’t stop you from reading the book or becoming familiar with the concepts of Domain-Driven Design. It’s quickly become an essential part of the software design canon. We keep it on our Infovark bookshelf among the other key technical books..
Software architects and software team leads will get the most benefit from the book, but if you’re a developer on a large enterprise software project or commercial product, you’ll find the Domain-Driven approach to software construction very useful in your work.
If you want to learn more, check out the Domain-Driven Design article on Wikipedia and the Domain-Driven Design Community. You can also listen to this short interview about Domain-Driven Design with Eric Evans on InfoQ.
But the best way to get started is to read the book itself.