I just wrapped up a four day Domain-Driven Design Immersion class with Eric Evans (author of Domain-Driven Design) and Paul Rayner. The class was put on by Eric’s company, Domain Language. If you’re looking for training or consulting in Domain-Driven Design, I highly recommend that you get in touch with them. I’d like to share some highlights of the class here.
Putting the Model To Work
Domain-Driven Design is a set of three guiding principles:
- Focus on the Core Domain as that is where the complexity is. Technology plays a supporting role, use it as needed.
- Explore the Model in a collaborative process involving both Domain Experts and software practitioners.
- Speak a Ubiquitous Language within an explicitly Bounded Context.
I should point out that the word “Model” has many different meanings in software development. Within Domain-Driven Design a Model is a “system of abstractions that describes selected aspects of a domain and can be used to solve problems related to that domain.” Those familiar with the Model–View–Controller (MVC) pattern should note that the word “Model” within the MVC pattern has a different meaning than “Model” within Domain-Driven Design. Within Domain-Driven Design a Model is a conceptual tool used to understand a Domain. An example that was used in the class was the game of baseball. A Model of the baseball Domain would include concepts such as strikes, balls, and outs. The classes and objects representing these concepts would not be the Model.
You might be wondering what the difference is between the Domain and the Model. The goal with Domain-Driven Design is not to create a Model of reality. Even if you could come up with some objective view of reality this would not be very useful. Instead, we are trying to understand (and perhaps develop) the Models that Domain Experts already use to understand the Domain. It’s important to note that Models are only useful for a particular purpose. What are you trying to do with this Model? Trying to use a Model designed for a different purpose will lead to a less than optimal outcome.
The Model Exploration Whirlpool might be a useful reference if you’re looking for concrete guidance on how to explore Models, especially in an Agile or Lean setting.
Group Entities and Value Objects into Aggregates. Entities are objects defined by a thread of continuity and identity. Their only responsibilities should be around identity and life cycle. Within a customer relationship management (CRM) system a person would likely be an Entity. Note that context matters: a person in another context may be a Value Object. A Value Object “is an object that describes some characteristic or attribute but carries no concept of identity.” Using the CRM example again, a phone number might be a Value Object. Again, context matters: if you’re a telephone company then a phone number may very well be an Entity. Treat Value Objects as immutable. Delegate business logic to Value Objects, identity and life cycle are plenty of responsibility for Entities. Grouping these Entities and Value Objects into Aggregates is useful when defining transaction, distribution, and concurrency boundaries.
An interesting topic covered in the class that I don’t believe was in the book was the idea of Domain Events. A Domain Event is something important that happens within the Domain that may lead to a state change in a domain object. Instead of keeping track of the current state of an Entity, you can instead compute this state from the currently known Domain Events. Using a baseball analogy again, a Domain Event might be a strike. Domain Events can trigger other Domain Events: three strikes triggers an out. The current state of the game can be computed from all of the Domain Events.
Since this has been a topic of conversation here on my blog and on Twitter, I plan on writing another blog post on why Value Objects need to be immutable. However, I want to point out here that if you think you need to change the state of a Value Object then instead have a method on that Value Object that returns another instance of the same type with the new state. If your method takes any arguments then have these arguments be of the same type as the Value Object. This concept is called “closure of operations” and is covered in Chapter 10 of the book, Supple Design.
While I won’t go into the details here, there are several other useful patterns in creating supple designs including intention-revealing interfaces, side-effect-free functions, and assertions. Note that “supple” is not the same as “flexible”. A flexible design can be easily modified, but a supple design is a design that fits comfortably with the Domain.
Strategic Design involves managing the interactions between Bounded Contexts. In my understanding, strategic design is most applicable in large teams or groups of teams. It starts by drawing a Context Map of the actual current Bounded Contexts, not what you want the Bounded Contexts to be. Some patterns to describe these relationships include Partnership, Shared Kernel, Big Ball of Mud, Customer/Supplier, Conformist, Anticorruption Layer, Separate Ways, Open Host Service, and Published Language. The details of these patterns can be found in the book.
There are always multiple Models. Some of these Models my represent your Core Domain. Others may represent a Supporting Domain or a Generic Subdomain. Work with business leaders to create a Domain Vision Statement so that you can identify which is which. One good question to ask a Domain Expert at the outset of a project to get at the Core Domain is, “What keeps you awake at night?” Other questions to ask include:
- “What makes your system worth writing?”
- “Why not buy it off the shelf?”
- “Why not outsource it?”
Once you’ve identified your Core Domain this is where you should focus your modeling efforts. Put your best available internal developers and modelers on the Core Domain and make sure that the Core Domain is isolated in a clean, Bounded Context.
Don’t settle on not having access to a Domain Expert. Domain-Driven Design is a creative collaboration between Domain Experts and software developers. Cultivate strong relationships with Domain Experts, focus on the Ubiquitous Language, listen for clues in conversations, and be open to shifts in assumptions that destroy your understanding of the Model—this is where breakthroughs come from!
If you’re interested in learning more: