Book description
Eric Evans’s domain-Driven Design: Solutions to Software Core Complexity has had a worldwide impact since its publication in 2003. As the first work of DDD, even after 18 years, the ideas in it are still very meaningful, and they are the only way for us to learn DDD.
The book is divided into four parts:
The first part, “Applying domain Models,” presents the basic goals for domain-driven development that drive the practices discussed in later sections. Because there are many approaches to software development, the first part also defines some terms and gives an overview of what it means to use domain models to drive communication and design.
The second part, “Building Blocks for Model-driven Design,” distills some of the core best practices in object-oriented domain modeling into a set of basic building blocks. This part is about bridging the gap between the model and the actual running software.
Part 3, “Understanding through Refactoring,” discusses how building blocks can be assembled into practical models to realize their value. Instead of directly discussing esoteric design principles, this section focuses on a discovery process. Valuable models are not immediately available, and the model design needs to be refined repeatedly in order to understand the domain step by step.
Part 4, “Strategic Design,” discusses the complexities that arise in complex systems, large organizations, and interactions with external and legacy systems. This section explores three principles that apply to the system as a whole: context, refinement, and large structure.
Let’s read the book with questions.
What problem does this book solve
In his introduction, Martin Fowler pointed out that the root cause of software development complexity is the complexity of the problem domain itself. Eric also clarified in the preface:
There are many factors that can derail a project, such as bureaucracy, unclear goals, and lack of resources. But it’s the design approach that really determines software complexity.
However, the primary complexity of many applications is not technical, but comes from the domain itself, user activities, or business. When this domain complexity is not addressed in the design, it does not matter how well the underlying technology is conceived.
Therefore, this book hopes to solve the problem of how to use good design methods to solve the problems caused by the complexity of the domain.
The discussion in this book is based on two premises:
(1) In most software projects, the primary focus should be on domain and domain logic;
(2) Complex domain design should be model-based.
The author Eric gave the answer to the question in the premise, that is, model-based design method.
What is a domain model
According to Wikipedia, a model is a representation of something simpler than another. The definition of Eric is:
A model is a simplification. It is an interpretation of reality — abstracting out the aspects that are most relevant to solving the problem and ignoring irrelevant details.
In short, pull out what’s important and ignore what’s irrelevant. Eric also describes the role of models in domain-driven design as follows:
(1) The core of the model and the design interact.
(2) The model is the backbone of a common language used by all team members.
(3) Models are condensed knowledge.
There is a strong link between the model and the code implementation, but it is also a common language for developers and domain experts to communicate, and it is a concentrated domain knowledge that the whole team agrees on.
How do you approach modeling
Since models play such an important role, how should software developers use models?
Eric points out that software developers like to improve their skills, especially the quantifiable ones, such as mastering a programming language, learning a development framework, learning a database, etc. However, they do not care much about the knowledge related to the work field, such as the manufacturing, catering, financial and other fields in which the technical personnel themselves work. They think that the study of the field knowledge is not useful for improving the ability of computer talents, and they are not interested in the field modeling.
We need to understand what is the core of software? It’s not a stack of computer technologies, it’s like Eric said:
The core of software is its ability to solve domain-related problems for users. All other features, no matter how important, serve this basic purpose.
Developers cannot leave domain learning and domain modeling to someone else and try to solve domain problems with pure technology. To solve the complexity problem of software core, developers need to face and solve it directly. Eric also persuadesthat mastering modeling skills can make software more organized, and can multiply the value of developers.
How to build domain models
The book gives a vivid metaphor:
Modeling is more like making a movie — reflecting reality in general for some purpose.
If it’s a movie, who will write and direct it? In other words, who’s going to create the complex stuff? In a traditional waterfall approach, there are generally three roles, business expert and analyst and programmer. The business expert discusses with the analyst, who digests and understands this knowledge, abstracts it and passes the results on to the programmer, who writes the software code. Here the business expert describes the reality, the analyst generalizes, the programmer produces, and the director seems to be the analyst. Eric pointed out:
This approach always fails because there is no feedback at all. Analysts are solely responsible for creating models, but the models they create are based on the advice of business experts. They have neither the opportunity to learn from programmers nor the experience of early versions of software. Knowledge flows in one direction and does not accumulate.
If the programmer simply builds the software as described by the analyst, without understanding the reasons behind it and without learning the domain knowledge, the software may work at the time, but will get bogged down as the changes increase. Modeling solely by technical personnel is not enough without the support of domain experts. The director should be a team effort.
As all team members digest and understand the model together, their interactions change.
Team members need to model as they learn from each other. Developers learn business principles, and domain experts learn the rigor required for software projects. Eric also quotes Kerievsky as saying:
Effective teams require a conscious accumulation of knowledge and continuous learning.
In Eric’s view, the domain model and the corresponding design are the accumulated knowledge of the team. In order to better carry these accumulated knowledge, he proposed the UBIQUITOUS LANGUAGE:
Domain models can be the core of a common language for software projects. The model is a set of concepts drawn from the minds of the project staff, as well as terms and relationships that reflect the deeper meaning of the domain. These terms and interrelationships provide the semantics of the model language, which is domain-specific but accurate enough for technical development. It is this vital link that binds models to development activities and binds them tightly to code.
Generic languages are not natural languages such as Chinese, English, and Japanese, but vocabularies that describe domain models, including the names of classes and major operations. If common speech is not used and domain experts and developers use their own terminology, communication between team members will need to be translated. Translation work leads to a failure to combine knowledge and ideas that promote a deeper understanding of models. What are the consequences of this indirect communication?
Because the pieces of software do not fit together, this makes it impossible to develop reliable software.
In order for the model to become a language for communication between domain experts and developers, we need to use this voice in various development activities. Developers use this language to describe the components and functions in the system. Domain experts use this language to describe requirements, development plans, and features.
Model as the backbone of the language. Make sure the team sticks to the language in all internal communication as well as in code. Use this language when drawing, writing, and especially when speaking.
Eric also gave a tip about discussing models out loud. Use model elements to describe scenarios out loud and tie concepts together in the way the model allows. Find easier ways to say what you want to say, and then implement those new ways into your diagrams and code. Although the detailed modeling steps have not been given yet, we know that we need to use common language to model in mutual communication and learning.
A sample using a common language
The book presents two scenarios for comparison.
Scenario 1: Minimized domain abstraction
User: So, when the customs clearance location is changed, the whole route plan needs to be reworked. Developer: Yes. We remove all rows associated with the shipment ID from the Shipment Table, and then pass the origin, destination, and new clearance point to the RoutingService, which repopulates the shipment table. Cargo must have a Boolean value that indicates whether there is data in the Cargo table. User: Delete rows? All right, we’ll do it your way. But is it necessary to do this if the place of clearance was not previously specified at all? Developer: Yes, whenever the origin, destination, or customs clearance point is changed (or entered for the first time), shipping data is checked to see if it already exists, deleted if so, and then regenerated by the RoutingService. User: Of course, if the original customs clearance data happens to be correct, we don’t need to do that. Developer: Oh, no problem. But it’s easier to have the RoutingService reload or unload the data each time. User: Yes, but it takes a lot of work to make all the support plans for a new route, so we generally don’t want to change routes unless we have to. Developer: Oh, ok, when the first clearance point is entered, we need to query the form to find the previous clearance point and compare it with the new clearance point to determine if it needs to be redone. User: This process does not take into account the origin and destination, because the route always changes here. Developer: OK, I see.
Scenario 2: Discussion using domain models
User: So, when the location of customs clearance is changed, the whole route plan needs to be reworked. Developer: Yes. When changing any of the RouteSpecification’s attributes, the original Itinerary is removed and the RoutingService is required to generate a new Itinerary based on the new RouteSpecification. User: Is it necessary to do this if the place of clearance was not specified at all? Developer: Yes, any time you change any of the RouteSpec properties, Itinerary is regenerated. This also includes entering certain attributes for the first time. User: Of course, if the original customs clearance data happens to be correct, we won’t need to do this. Developer: Oh, no problem. But it would be easier to have the RoutingService regenerate Itinerary one at a time. User: Yes, but it takes a lot of work to make all the support plans for a new route, so we generally don’t want to change the route unless we have to. Developer: Oh. You need to add some functionality to RouteSpecification. Thus, when changing the properties in the RouteSpecification, check to see if Itinerary still satisfies the Specification. If not, the RoutingService needs to regenerate Itinerary. C: Don’t worry about the origin and destination, because Itinerary is always changing here. Developer: Ok, but it’s much easier to just compare each time. Only when RouteSpecification is not satisfied, Itinerary is regenerated.
It’s not hard to see that the terms RouteSpecification and Itinerary based on domain model are used in scene 2, which is a more accurate description.
What is the relationship between the model and the document
What should the model look like? Many people think of the UML Unified Modeling Language. UML can help us discuss domain models by graphically representing the relationships between objects. But Eric reminds us:
The trouble comes when one has to represent the entire model or design through UML diagrams. Many object model diagrams are too detailed in some ways and too missing in others.
UML diagrams fail to convey two of the most important aspects of a model, the meaning of the concepts it represents and what objects should do.
So we need to use other natural language as a complement to express the exact meaning of the model. UML is a means of communication and interpretation, not the model itself. You cannot force diagrams to represent the entire model or design, as this would reduce the ability of diagrams to be clearly expressed. So models can be represented as UML plus natural language documents.
But in today’s world of agile development, documentation is in an awkward position. Many extreme programming advocates even advocate no documentation, code is documentation. In fact, a close look at the Agile manifesto, which says that working software trumps detailed documentation, does not completely negate the meaning of documentation. So where does the document fit in? Eric told us that documentation should complement code and verbal communication.
Documentation should not repeat what the code already explicitly says. The code already contains all the details and is itself an accurate description of the program’s behavior. Other documents should focus on meaning so that people can understand the large-scale structure in depth and focus on the core elements. Documentation can clarify design intent when the programming language cannot directly and clearly implement concepts.
The greatest value of the design document is in explaining the concepts of the model and helping to guide the details of the code.
The main reason many people advocate code as documentation is this: Code doesn’t cheat, and documentation does. Many times documentation is not updated as the code evolves, and using such out-of-date documentation can be detrimental to the project. So documentation should be alive and up-to-date. But if you have to constantly update all the documents, will the developer want to put aside the workload? How do you balance this? Eric recommends minimizing documentation and making sure it is only a supplement to code and verbal communication to avoid disconnection from the project.
What is the relationship between model and code
Martin Fowler notes in the preface:
Concepts should not be separated from implementation during domain modeling. An effective domain modeler should not only be able to discuss with an accountant on a whiteboard, but also be able to write Java code with programmers.
The model and code implementation should be closely linked, and the person who creates the model and the person who writes the code should not be separated. However, many design approaches outside of domain-driven design advocate the use of an analytical model, a model that has nothing to do with programming and serves only as an analysis of the results of the business domain. Typically created by analysts and passed on as requirements to developers. There is only a loose correspondence between the analysis model and the final program design. Because the analysis model was created without programming in mind, once the coding started, the details started piling up and slowly the pure analysis model fell by the wayside. This development model is still common today. Eric pointed out:
If the entire program design or its core does not correspond to the domain model, then the model is worthless and the correctness of the software is questionable. At the same time, the overly complex correspondence between the model and the design function is difficult to understand and cannot be maintained in real projects when the design changes. If there is a serious divergence between analysis and design, the knowledge gained in analysis and design activities cannot be shared.
How to solve this problem? Eric put forward MODEL DRIVEN DESIGN at the right time, trying to find a single MODEL that can meet the needs of both analysis MODEL and program DESIGN. The binding model and programming proved to be feasible, but with caution:
Such binding should not compromise analysis for technical reasons, nor should we accept poor design that reflects domain concepts at the expense of software design principles.
These are the two basic elements of MODEL DRIVEN DESIGN, that is, the MODEL supports effective implementation and abstracts key domain knowledge.
In terms of development languages, object-oriented languages like Java are a natural fit for expressing models. And it is only when model concepts are represented in code that the breakthrough of object-oriented design really becomes apparent. Object-oriented design is the modeling paradigm used in most projects today and is the main approach used in this book.
There is a question in the book that has puzzled Eric for many years: should the analyst responsible for creating models be separated from the developer responsible for programming? He was in charge of developing domain models to guide programming on a project, but the project management forbade him from writing code or discussing details with the programmers, believing that the analytics people focused on modeling and writing code was a waste of time. Eric analyzed the domain knowledge and refined a good domain model, but it ended up being useless. Because part of the intent of the model is lost in transit, and there is no feedback on the impact of the code implementation on the model. So Eric came up with the Hands-on MODELER pattern, which has also been translated as MODELER involvement in program development.
If the person writing the code doesn’t feel responsible for the model, or doesn’t know how to make it work for the application, then the model has no relevance to the program. If developers don’t realize that changing the code means changing the model, their refactoring of the program can actually weaken the model rather than enhance it.