Review Domain Driven Design
April 22, 2010Introduction
At JavaPolis 2006 I met Eric Evans where he gave a university session about his book Domain-Driven Design. The session was very intriguing and so I bought the book on the spot. It seemed to promise to teach me a lot about how to go about the difficult task of extracting a model from a real-life situation. Of course that same real life prevented me from reading the book for several years. So now I have finally found the time to actually sit down and read it. And just like it promised all those years ago, it gives a lot of hints, tips and tools to extract a model from a domain. An absolute must-read for programmers and architects. And preferably also to be read by managers, so they will hear from an experienced architect that modelling shouldn’t be done by ivory tower architects.
Part I: Putting the Domain Model to Work
This part of the book presents the basic goals of domain-driven development, it defines the terms used throughout the book and it gives an overview of the implications of using the domain model to drive communication and design.
Chapter 1: Crunching Knowledge
In order to get to a workable domain model which can be used to successfully build useful software, there are five necessary ingredients: binding the model and the implementation, cultivating a language based on the model, developing a knowledge-rich model, distilling the model into a deep model, and brainstorming and experimenting. These taken together can be labeled as knowledge crunching.
Chapter 2: Communication and the Use of Language
A domain model can and should be the core of a common language for a software project, the so-called ubiquitous language. The model is a set of concepts built up in the heads of people on the project, with terms and relationships that reflect domain insight. These terms and interrelationships provide the semantics of a language that is tailored to the domain while being precise enough for technical development.
Chapter 3: Binding Model and Implementation
If the model can not or simply is not be used for implementation, then a lot of knowledge the analysts had is lost. Therefore the model and implementations should be tightly bound together (Model Driven Design). If the people who write the code don’t feel responsible for the model, or don’t understand how to make the model work for an application, then the model has nothing to do with the software. Meanwhile, when a modeler is separated from the implementation process, he never acquires, or quickly loses, a feel for the constraints of the implementation. Therefore any technical person contributing to the model must spend some time touching the code and every developer must be involved in some level of discussion about the model and have contact with domain experts (Hands-On Modellers).
Part II: The Building Blocks of a Model-Driven Design
This part of the book condenses a core of best practices in object-oriented domain modeling into a set of basic building blocks. It focuses on bridging the gap between models and practical, running software. But the main point of this section is to focus on the kinds of decisions that keep the model and implementation aligned with each other.
Chapter 4: Isolating the Domain
The part of the software that specifically solves problems from the domain usually constitutes only a small portion of the software system, although its importance is disproportionate to its size. We need to decouple the domain objects from other functions of the system, so we can avoid confusing the domain concepts wit hother concepts related only to software technology or losing sight of the domain altogether in the mass of the system. One approach is to use a layered architecture.
Chapter 5: A Model Expressed in Software
This chapter focusses on the individual model elements, such as associations, entities, value objects and services. Finally a discussion of modules will drive home the point that every design decision should be motivated by some insight into the domain. The ideas of high cohesion and low coupling can be applied to the concepts themselves. In a model-driven design, modules are part o the model, and they should reflect concepts in the domain.
Chapter 6: The Life Cycle of a Domain Object
Every object has a life cycle. Many of these are simple, transient objects. But other objects have longer life, not all of which are spent in active memory. Managing these objects presents challenges that can easily derail an attempt at model-driven design. This chapter will address these issues through three patterns. First, aggregates tighten up the model itself by defining clear ownership and boundaries, avoiding a chaotic, tangled web of objects. Next the focus turns to the beginning of the life cycle, using factories to create and reconstitute complex objects and aggregates, keeping their internal structure encapsulated. Finally, repositories address the middle and end of the life cycle, providing the means of finding and retrieving persistant objects while encapsulating the immense infrastructure involved.
Chapter 7: Using the Language: An Extended Example
The preceding three chapters introduced a pattern language for honing the fine detail of a model and maintaining a tight model-driven desing. This chapter presents an elaborate example showing the forces that apply and how the patterns of part II can resolve them.
Part III: Refactoring Toward Deeper Insight
This part of the book is about the challenge of assembling the building blocks into practical models that provide the payoff. It delves into modeling principles that can guide choices along the way to gaining deeper insight, and techniques that help direct the search.
Chapter 8: Breakthrough
The return from refactoring are not linear. Usually there is a marginal return for a small effort, and the small improvements add up. But some of the most important insights come abruptly and send a shock through the project. This chapter tells the story of one project and how they arrived at a very valuable deep model.
Chapter 9: Making Implicit Concepts Explicit
Many transformations of domain models and the corresponding code happen when developers recognize a concept that has been hinted at in discussion or present implicitly in the design, and they represent it explicitly in the model with one or more objects or relationships. Most such discoveries come from listening to the language of the team, scrutinizing awkwardness in the design and seeming contradictions in the statements of experts, mining the literature of the domain, and doing lots and lots of experimentation. Three ways of modeling less obvious kinds of concepts are explicit constraints, processes as domain objects and specifications
Chapter 10: Supple Designs
The ultimate purpose of software is to serve users. But first, that same software has to serve developers. When software with complex behavior lacks a good design, it becomes hard to refactor or combine elements. To have a project accelerate as development proceeds – rather than get weighed down by its own legacy – demands a design that is a pleasure to work with, inviting to change. A supple design. In order to get to a supple design you can use several patterns: intention-revealing interfaces, side-effect-free functions, assertions, conceptual contours, standalone classes, and closure of operations
Chapter 11: Applying Analysis Patterns
Deep models and supple designs don’t come easily. Sometimes we can get a leg up from other people’s experience when they have recorded that experience in the shape of an anlysis pattern. It hardly ever is the answer to your particular needs, yet it offers valuable leads in your investigation, and it provides cleanly abstracted vocabulary.
Chapter 12: Relating Design Patterns to the Model
Most of the patterns published to date are more technical in focus than the patterns explained in the book so far. Some, not all, of these can be used as domain patterns. Doing so requires a shift in emphasis. A discussion on the composite and strategy patterns demonstrates how some of the classis patterns can be applied to domain problems by thinking about them in a different way.
Chapter 13: Refactoring Toward Deeper Insight
Refactoring toward deeper insight is a multifaceted process. It will be helpful to stop for a moment to pull together the major points. There are three things you have to focus on: live in the domain, keep looking at things a different way, and maintain an unbroken dialog with domain experts.
Part IV: Strategic Design
This part deals with situations that arise in complex systems, larger organizations, and interactions with external systems and legacy systems. This section explores a triad of principles that apply to the system as a whole: context, distillation, and large-scale structure.
Chapter 14: Maintaining Model Integrity
The most fundamental requirement of a model is that it be internally consistent; that its terms always have the same meaning, and that it contain no contradictory rules. Total unification of the domain model for a large system will not be feasible or cost-effective. This chapter lays out techniques for recognizing, communicating, and choosing the limits of a model and its relationships to others. It all starts wit hmapping the current terrain of the project. A bounded context defines the range of applicability of each model, while a context map gives a global view of the project’s contexts and the relationships between them. This reduction of ambiguity will, in and of itself, change the way things happen on the project, but it isn’t necessarily enough. Once we have a context bounded, a process of continuous integration will keep the model unified. Then, starting from this stable situation, we can start to migrate toward more effective strategies for bounding contexts and relating them, ranging from closely allied context with shared kernels to loosely coupled models that go their separate ways.
Chapter 15: Distillation
How do you focus on your central problem and keep from drowning in a sea of side issues? Distillation is the proces of separating the components of a mixture to extract the essence in a form that makes it more valuable and useful. A model is a distillation of knowledge. As with many chemical distillations, the separated by-products are themselves made more valuable by the distillation process (as generic subdomains and coherent mechanims), but the effort is motivated by the desire to extract that one particularly valuable part, the core domain. Strategic distillation does all of the following: aids all members in grasping the overall design of the system and how it all fits together; facilitates communication by identifying a core model of manageable size to enter the ubiquitous language; guides refactoring; focuses work on areas of the model with the most value; and guides outsourcing, use of off-the-shelf components, and decisions about assignments. Most of the distillation patterns in this chapter show how to change the model and distill the core domain. However, domain vision statement and highlighted core show how the use op supplemental documents can, with a very minor investment, improve communication and awareness of the core and focus development effort.
Chapter 16: Large-Scale Structure
Even with a modular breakdown, a large model can be too complicated to grasp. A “large-scale structure” is a language that lets you discuss and understand the system in broad strokes. Large-scale structure can save a project, but an ill-fitting structure can severely hinder development. This chapter explores patterns for successfully structuring a design at this level, like evolving order, system metaphor, responsibility layers, knowledge level, and pluggable component framework.
Chapter 17: Bringing the Strategy Together
The preceding three chapters presented many principles and techniques for domain-driven strategic design. In a large, complex system, you may need to bring several of them to bear on the same design. The three basic principles of strategic design (context, distillation, and large-scale structure) are not substitutes for each other; they are complementary and interact in many ways. When you are tackling strategic design on a project, you need to start from a clear assessment of the current situation. This can be accomplished by the following steps: draw a context map, attend to the use of language on the project, understand what is important, find out if the technology of the project work for or against a model-driven design, find out if the developers on the team have the necessary technical skills, and find out if the developers are knowledgeable and interested in the domain. Another important question is about who sets the strategy. Traditional handing down of architecture doesn’t usually work well. Strategic design, by definition, must apply across the project. Six essentials for making strategic design decision making work are: decisions must reach the entire team, the decision process must absorb feedback, the plan must allow for evolution, architecture teams must not siphon off all the best and brightest, strategic design requires minimalism and humility, and finally objects are specialists; developers are generalists.
Conclusion
Looking back on some projects described in the book and where they went after the involvement of the author ended, it can be concluded that wrestling a complex domain into a comprehensible software design is an exciting challenge for strong technical people. What is needed are tools that allow sharper ways of exploring domain models and expressing them in working software. But though improved tools will be valuable, we mustn’t get distracted by them and lose sight of the core fact that creating good software is a learning and thinking activity. Efforts to automate what must be the product of thought are naive and counterproductive. With the tools and technology we already have, we can build systems much more valuable than most project do today.
