DDD is domain driven design. It comes from the very influential book “Domain Driven Design – taking complexity in the heart of software” published by Eric Evans, a famous modeling expert. It was first widely used in traditional software architecture design.
In April this year, InfoQ released a trend report on software architecture and design. It can be seen from the report that micro service and domain driven design have become the mainstream trends in the software development industry. The author also understands that DDD has become the guiding ideology for the landing of micro service and the construction of middle platform in most enterprises.
(photo source: InfoQ)
Isolation of change and precipitation reuse
In the Internet era, in the early stage of business system construction, the scene is usually simple and clear. Based on database table design + crud, business agile iteration can be supported. With the passage of time, the scene and business logic become complex and customized, and the modules are coupled with each other. The system becomes more and more bloated, which often affects the whole body. Even if the seemingly simple logic of adding a field is to sort out the impact on other function points and modules, it needs at least an old member of the team who is familiar with the business and code to make a firm decision. I believe that the architecture and code of a business system that has been implemented for more than one year may be experiencing the above and begin to decay slowly.
One of the most classic examples is the design of products in e-commerce system (the number of fields may be several hundred in reality), which does not conform to the architectural design principle of high cohesion and low coupling
- The product class is all inclusive and knows all kinds of knowledge in any field; its responsibilities are not clear, and its functions are not clearprecipitatemultiplexingOn the other hand, the expectations of team members are not consistent, and the realization of posture may be strange;
- The logic changes in purchasing, warehousing and distribution business may have to modify product. A highly cohesive system design needs to be implemented as far as possibleIsolate changesTo minimize the impact and control it within a certain boundary.
DDD is decoupled and reused by dividing the bounding context and breaking down the molecular domain
The following image is from the godfather of software development: Martin Fowler. It is true that in order to cope with more and more complex business logic, the top-down design of domain aggregation model instead of data table model can truly realize the flexible expansion with business entity as the core
- Process oriented scripts cannot be well extended;
- Data table oriented design pays too much attention to data ignoring behavior and cannot be reused well.
Above, let the Internet bubble survive the system tide gradually rekindled the enthusiasm for DDD, hoping to use DDD to restore the confidence of building a more reasonable software architecture. However, on the ground, there are many thorns and difficulties. Now let’s introduce the implementation practice of DDD in the cooperation field of Jingdong Devops project.
Applying DDD to componentization
Within JD, there are two systems with a wide coverage of user groups (the total number of users is 8W +): PMP and Xingyun.
PMPIt is a project management software for project manager, including project process management, requirement management, milestone management, task management, man hour management, cost management, OKR management, ROI verification and satisfaction score. In architecture design, PMP is a very large single application, its front and back end are not separated, all business logic is mixed together, and the number of project form fields reaches 100 +. With the change of time and organization, it’s a disaster in terms of scalability and maintainability.
XingyunThe initial positioning is R & D oriented agile collaborative software, including cross department requirements management, agile iteration and task management. With the wide use of the cloud, the voice of integrating PMP function into the cloud is getting higher and higher.
At the same time, Xingyun provides tob services to the outside of the company. There are a lot of different scenes and businesses inside and outside. It is not feasible to add if else to knead the clay ball in the past. Under the new positioning and background, we must split the business logic into flexible components to achieve reuse and logic precipitation; on the other hand, the differentiated logic can be flexibly expanded. There are huge challenges:
The arc in the middle of the figure above describes the principles we refer to when splitting components (business can operate independently, high cohesion and low coupling, data integrity and gradualness). On this basis, we adopt relevant DDD strategies and tactics when dealing with the challenges from the perspective of business and technology.
Both PMP and cloud have requirements management and task management. Is requirement and task a concept? What is the relationship between projects, requirements, iterations, tasks, etc? How to precipitate a set of clear and reusable business components internally and externally?
There are many concepts in DDD, including bounding context, aggregation, aggregation root, entity, value object, etc
1. Divide boundaries, identify domain objects or domain classes, and ensure their responsibilities are clear and pure;
2. Make clear the association and dependence between domain classes, and define the calling relationship and method.
Through domain analysis and modeling, a unified language is formed. Finally, the whole project collaboration management is divided into business domains with complete functions and clear business logic, such as project domain, task domain, man hour domain, etc. Each business domain provides specific domain services, and a business domain can manage multiple business entities.
The challenge of Technology
After dividing the fields, the ideal situation is that each field has a high degree of autonomy and less dependence. Even each field can be realized by different teams, and each team focuses on the precipitation of the core competence in this field.
Finally, we form a componentization scheme: according to the divided fields, the system is divided into business components (core sub fields) and basic components (general and support sub fields), and the front and back ends of each component are separated. That is, there will be the following front-end applications: requirements management, project management, defect management, use case management, etc.; the back-end applications provide different domain services correspondingly, and the domain services adopt hierarchical architecture (interface, application, domain, infrastructure). Privilege management, gateway services, message services and other basic components sink to maximize component reuse.
It is divided into business components by domain,For the system, the final supply to the end users needs to be a whole. But componentization means separation. What kind of collaborative challenges does it face for the front-end and back-end applications of business components?**
Challenges of business component front end applications
In order to realize the parallel and independent evolution of each business component, ideally, the front-end application needs to be compiled, packaged and deployed independently, and finally integrated into a platform to present a unified UI style and consistent interaction experience.
The above industry attributed this to micro front-end architecture: to achieve an architecture style, many independently delivered front-end applications can be combined into a large-scale whole, which is a single and complete product for customers.
Finally, our Xingyun team implemented a jmodule micro front-end component framework.
The front-end application is registered to the platform through micro front-end architecture and front-end component framework. The system layer realizes component metadata management, runtime hot loading static resources and communication between components, and provides fully pluggable and configurable components for the user side. The specific principle and implementation will be carried out in another chapter.
Challenges of business component back end applications
At the beginning of the design, the back-end service of Xingyun adopted the architecture of micro service (using spring cloud gateway, Eureka, etc. to realize service registration, gateway call, etc.), which complements DDD. Within the core business components, domain services are organized according to the classic hierarchical architecture (interface, application, domain, infrastructure).
- Interface – user interface layer: controller, restful interface call, or Web UI interface, mobile UI interface, third party service, etc;
- Apllication application layer: provide various application functions for the presentation layer externally, call the domain layer (domain service) internally, and the application layer is more like the strategy of realizing a specific scenario, or the arrangement of the process, etc. It coordinates services in multiple fields,Realize the isolation of scene and business；
- Domain domain layer: responsible for expressing business concepts, business behaviors, business States and business rules. Domain model is the core of business software.It provides a series of atomic services, and provides rich open API in this layer, which is a crucial step to realize componentization；
- Infrastructure – foundation layer：Realize the isolation layer of business and technology. It generally includes: network communication, database persistence, asynchronous message service, southbound gateway service, etc. When landing, this layer can implement a variety of adapters to be compatible with internal, external, and multi cloud heterogeneous middleware environments.
In addition to defining the boundary of internal layers of components, it is also necessary to clarify the call and dependency relationship between components, and further clarify the responsibilities of components. In DDD, the mapping relationship between bounding contexts is defined
- partnership:The two contexts cooperate closely;
- Client supplier:There are organized upstream and downstream dependencies between contexts;
- Followers:Downstream context can only blindly rely on upstream context;
- Separation method:Two completely unrelated contexts;
- Shared kernel:Two context dependent partially shared models;
- Anticorrosive coating:One context interacts with another through adaptation and transformation;
- Open host service:Define a protocol to let other contexts access this context;
- Event publish / subscribe:Commonly used to define protocols for open hosts.
In terms of component invocation and dependency, we can learn from the above mapping concept.
For example, we have precipitated project components and task components. Suppose the business scenario to be implemented: when deleting a project, you need to check whether there are tasks in progress in the project. If there are no tasks, you need to delete them. If there are, you will be prompted not to delete them. According to the mapping relationship of DDD, the task is dependent by the project, and the task is in the upstream position. Ideally, it does not need to know the specific logical rules for deleting the project business domain, and at the same time, it tries to reduce the impact of the change of project business rules.
Therefore, when we landed, we eliminated the implementation method on the left side of the figure below – cooperation relationship (project and task network call each other, I have you, you have me), but added an adaptation layer in the downstream project field to isolate the impact of business changes on the upstream. At the same time, it also ensures that the logic of the task layer is clean and clear for reuse by more other components.
To sum up, this paper gives the guiding significance of DDD in the following aspects
- How to precipitate clear and reusable business components?
- How to isolate the impact of changes between components on other components?
Later, we will share the practice of DDD in plug-in implementation in the following chapters to solve the following problems:
How to quickly respond to various customized needs, while maintaining its own non-corruption?