1 DDD
Domain Driven Design(DDD) is not a kind of architecture, but an architecture methodology. It is a method to disassemble business, divide business and determine business boundary. It is a kind of Domain Design thought.
- Core idea: Establish domain model, which is at the core of architecture.
- Core goal: Avoid confusing the complexity of business logic with the complexity of technical implementation.
DDD consists of tactical design and strategic design.
- Strategic design: Focus on high-level, macro partitioning and integration of bounded contexts.
- Tactical design: Focus more specifically on using modeling tools to refine the context.
2 Strategic DDD
2.1 introduction
-
Bounded Context: used to delimit domain boundaries.
-
Context Mapping: Describes the system relationship. There are mainly the following relationships:
- Shared Kernel
- Customer/Supplier
- Conformist
- Anticorruption Layer
- Open Host Service
- Published Language: Commonly used with the Open Host Service to define protocols for Open hosts.
-
Ubiquitous Language
The team’s unified language is a simple, clear, and accurate language that describes business rules and business implications.
2.2 Bounded Context(BC)
2.2.1 Start with a paragraph
Before we start, let’s think about a problem: when I get up in the morning, my mother asks Xiao Ming to wear as many clothes as he can. So xiao Ming should wear more clothes or less clothes? We can’t really tell without our environment. Because if it is in summer, mother means to let Xiao Ming wear less clothes; If it is winter, mother means xiao Ming to dress. In the world of programs, the purpose of Bounded Context is to determine the boundary of the field and to make the expression of each thing precise.
2.2.2 Take an example
If we want to design an e-commerce platform, we need to have modules such as commodity, transaction, payment and logistics, which are actually fields. In different fields, the meaning of the same thing is different because of different concerns, but in a definite context, its meaning is definite. Such as:
- In the field of commodities, we pay attention to the basic information of commodities (name, brand, model, price, etc.), and in the field of transactions, we pay attention to the transaction process (order creation, payment results, performance process, etc.). However, the same commodities are called order details or transaction details in the field of transactions. Therefore, when we talk about commodities in the field of trading, we refer to the details of the order (commodities), and generally only pay attention to the status of transaction performance, and naturally do not care so much about the attributes of commodities.
- For the same user, we pay attention to its basic information, account password and so on in the user domain, but in the permission domain, we pay attention to its menu, function permission and role.
In the example above this is directly reflected at the code level, where the difference is very obvious, and when discussing issues within a defined domain, it is also very referential.
We call the same thing differently in different situations. For example,
- Commodity, goods: the same thing is called commodity in the transaction field and goods in the logistics field.
- Channel goods and back-end goods: in the purchase, sale and inventory management, they are called channel goods in the sales test (they can be sold through multiple channels, such as Taobao and Jingdong Shang); On the purchasing side it’s called the back-end item.
2.2.3 What is Bounded Context
Bounded Context defines domain boundaries to ensure that each Context meaning has a unique meaning within its specific boundaries. Bounded Context defines the scope of application of the model so that all team members can clearly know what should and should not be implemented in the model. Note: Domain models must not be shared in different bounded contexts. For example, the goods/goods and goods/order details in the above example should not use the same model, but this should be obvious to experienced developers.
2.2.4 Domain split
Continuing with the previous example of e-commerce platform, e-commerce platform can be divided into commodity, transaction, payment and logistics, as shown in the figure:
With the development of business, these areas can be further divided into multiple sub-areas. For example, commodities can be divided into categories, inventory, commodities, etc. Transactions can be divided into: transactions, promotions, coupons, after-sales and other areas; Payment can be divided into payment core, payment route, payment channel and other fields. As shown in figure:
As the business continues to develop, all domains and subdomains may be split again. For those familiar with microservices development, it should be clear that a domain can be an independent microservice, and in fact microservices are the result of a domain split. A bounded context can theoretically be designed as a microservice if technology heterogeneity, team communication and other factors are not considered.
The above process of dividing a Bounded Context is actually the process of dividing a Bounded Context. Each Bounded Context is a field.
2.2.5 field
Domains are classified into Core Domain, Supporting Domain, and Generic Domain according to their Core degree.
-
Core Domain: The Core of a company’s business. For example, in e-commerce business, goods, shopping cart, transaction, promotion, discount, payment and so on are all core areas
-
Generic Domain: a Generic Domain that does not have personalized requirements, or even has similar functions that are available for purchase from different companies or can be used by multiple subdomains, such as users, permissions, authentication, and face recognition.
-
Supporting Domain: Generally, a module that is not the most core module in the system, nor a common component or service, but supports the core business.
2.2.6 Ubiquitous Language
The common language is a unified language that can describe business rules and business meanings simply, clearly, and accurately. The value of a common language:
- Solve communication barriers in all positions to ensure the correct expression of business requirements.
- Without a common language, because the business, product, development, and test roles and terms are different, you often run into battle for a long time and end up saying the same thing.
- Without a common language, production, development, and testing often fail to agree, resulting in different content and business needs.
- Common language throughout the design process, can accurately translate business requirements into code.
- Nouns in a common language can generally name domain objects. For example, orders, goods can correspond to an entity in the domain.
- A verb in a common language usually corresponds to an action or domain event. For example: Order paid, order shipped each corresponds to a domain event.
2.3 Context Map
Context Map describes the overall view of the relationships between systems, including the following relationships:
2.3.1 Shared Kernel
In the e-mall scene, the process of purchasing different types of goods will also be very different. For example, the process of buying and selling physical goods is generally: the buyer pays, the seller delivers goods, and the buyer confirms receipt of goods; The process of buying and selling hotel rooms is generally: buyers pay, sellers reserve rooms, buyers enter, buyers check out statement; The process of buying and selling tourist routes is generally: buyer’s payment, seller’s confirmation and service performance.
Although these business scenarios and transaction processes are quite different, they can reuse the core transaction process together, as shown in the figure below:
Can I not use a shared kernel? Or what are the architectural benefits of sharing a kernel?
- Reuse. The same set of abstract transaction processes can be used to support different scenarios, which can greatly save development costs.
- Extension. If there is no reuse process and each business scenario is developed separately, then if promotions, coupons, packages, etc., are to be supported over a period of time, they need to be developed separately in each business line.
- Maintenance. If a problem is identified in one set of processes that requires iterative optimization, it is likely that the other two will need to be adjusted as well.
In fact, there are many benefits, specific can refer to the advantages of the platform architecture, here is not discussed one by one. The above example is not a pure thought experiment of YY. In my previous work experience, A company engaged in tourism underwent online transformation and encountered the above scenarios at the same time.
In the example above, a shared subset stripped from multiple teams or businesses is a shared kernel.
2.3.2 Customer/Supplier
This is common in distributed development, where the interface Provider is the Supplier(or Provider) and the interface Consumer is the Customer(or Consumer).
2.3.3 Conformist
In some scenarios, the state change of one system (such as: A) will directly affect the results of another system (such as: B), and the state of system B must change after the state change of system A, and such system relationship is called Conformist. For example, if the payment system has completed the payment and the status of the payment order has changed to “Paid”, the order status of the transaction system must also change to “Paid by the buyer”.
2.3.4 Anticorruption Layer
If the relying system is inhospitable to the current system scenario and reduces inter-system dependence and coupling, you need to use Anticorruption Layer mode.
2.3.5 Open Host Service(Open Host Service)
Exposing a set of services to other systems. For example, in microservice development, interfaces (services) are used for other systems.
3 Tactical DDD
3.1 Content of tactical design
3.1.1 Aggregate & Aggregate Root
-
Definition: In the domain model, we bring together closely related individuals to accomplish specific business functions according to uniform business rules within the organization. This is called aggregation. For example, in e-commerce, master order and order details have the same business rules and are basically operated together. When an order is operated, the master order and order details are basically modified at the same time, so master order and order details are an aggregation. In this aggregation, the entry point of the action is basically the master order, so the master order is the aggregation root of the aggregation.
-
Note: the content within the aggregate is consistent, i.e. the content of an aggregate needs to be modified in a transaction. If there is no consistency requirement, then it should not belong to an aggregation. Reference to other aggregations or entities through unique identifiers. If the aggregation is complex to create, the factory approach is recommended to mask the internal complex creation logic. In the traditional data model, it is generally considered that each entity is equivalent and any entity can be modified individually. In DDD, the modification of objects in aggregation must be done according to uniform business rules. Aggregation is the basic unit of data modification and persistence.
-
Example: An order in a trading system consists of a master order, a detail, which is an aggregate, and the master order is the aggregate root of the aggregate. The items in the goods system include Item(goods) and SKUS (inventory units of goods), which are also aggregation, where Item is an aggregation root.
-
Principle of aggregate design: Design small aggregates. Small aggregation can reduce data conflicts and avoid excessive traffic. Reference other aggregations by unique identity. Data is strongly consistent within the aggregation, and data is ultimately consistent outside the aggregation. Cross-aggregation calls are implemented through the application layer.
3.1.2 Entity
- Definition: An object has a unique identifier (usually an ID) that remains the same after various state changes. For this object, it is the unique identifier that has continuity, not the attribute, that is important. Such objects in the domain are called entities. Entities typically correspond to business objects and have properties and business behaviors. Entities are the underlying Domain objects.
- Example: The data in a DB table becomes a single entity when loaded into memory. We use the DB primary key to distinguish different records.
3.1.3 Value Objects
- Definition: a simple object with no unique identity. Its unique symbol is not important, but its attribute, which describes a piece of information in the domain. This kind of object is called a value object. A value object is a collection of attributes and a description of entity information. Value objects are also basic Domain objects
- Example: The item information, address information in the order object is the value object.
3.1.4 Domain Services
Some important domain actions or operations can be categorized as domain services. It is neither an entity nor a category of value objects.
3.1.5 Domain Events
A domain event is a modeling of activities that occur within a domain.
3.1.6 Factory(Factory Mode)
When creating objects, aggregations require a large number of entity or value objects, or complex relationships. To ensure that all objects in the aggregation can be created at the same time, and to avoid adding content unrelated to its own domain to the root of the aggregation, these contents are generally handed over to the Factory. The main function of Factory is to encapsulate the creation process of complex objects in the aggregate, and complete the creation of root, entity and value objects in the aggregate.
3.1.7 Repository Model
In order to avoid the data processing logic of the base layer infiltrating into the business code of the domain layer, the Repository layer is introduced to form a tight coupling relationship between the domain layer and the base layer. Repository is divided into Interface and Implement, and the domain layer depends on the Repository Interface.
3.1.8 Modules(Module)
When creating a system, we usually divide a system into modules based on the content we are responsible for, and each module usually corresponds to a sub-domain.
4 from domain division to system implementation
Taking e-commerce platform as an example, DDD strategic design guides the implementation of micro-services as shown in the figure below.The e-commerce field is subdivided, and then the fields with similar businesses and close coupling are aggregated together to form our business system.
Each field has a lot of content. Taking the commodity field as an example, we further subdivide the commodity field into categories, attributes, attribute values, SPU, Item and SKU, and then combine the closely related content data to form aggregation one by one.
5 Domain Model
5.1 Anemia Model (Anemic Model)
Anaemic models are value domain objects: only data without behavior. That is, there are only properties, set and GET methods in the model, and the logic is placed in the Service/Manager layer. An object that has data but no behavior is not a real object, so the anaemic model is an anti-pattern that goes against object-oriented design. Domain objects are only used as save state or pass state, all business logic is handled in the business logic layer, and for fine-grained logic processing, a layer of Facade is added to achieve the effect of Facade wrapping.
This anemia model is common in projects using Spring. Here is a typical system structure diagram using the anemia model:
This system structure is simple and clear, namely: Consumer/Api -> Service -> Manager/Biz -> Dao -> Mybatis -> DB. Anaemic domain objects do what they do: pass data and contain no business logic. In [DDD-Domain Primitive](DDD-Domain Primitive. Md) there are some simple examples of how Domain objects without logic can cost a lot of development and maintenance over continuous iterations.
5.2 Hyperemia model
The essence of object-oriented design is that “an object has state and behavior”, and a congestion model is a class that has both properties and operations. Modify a user’s information and then save it. Example code for the anaemic model scenario is as follows:
user.setXXX();
userManager.save(user);
Copy the code
In the congestion model scenario, the code looks like this:
user.setXXX() user.save(); Save yourselfCopy the code
Typical system structure diagram:
Advantages: Object-oriented; Service conforms to a single responsibility. Disadvantages: Logic in Domain Objects, logic in services, vague. Coding costs are high, and transaction control costs increase.
6 CQRS mode
6.1 introduction of CQRS
CQRS(Command Query Responsibility Segregation) is a mode of Segregation between Command and Query. The basic idea is that any method can be split into commands and queries:
- Command: returns no result (void), but changes the state of the object. Command is a general name for an operation that causes data changes, such as adding, updating, and deleting data. Operations are encapsulated in Command. The user submits Commond to CommandBus, which is then distributed to the corresponding CommandHandler for execution. After Command execution, data is persisted through Repository. Event Source CQRS, Command sends a specific Event to EventBus, which is then processed by a specific EventHandler.
- Query: An operation that returns the result of a Query and does not change the data. Return the Query result based on the Query condition. Customize different facades for different scenarios.
6.2 CQRS three modes
6.2.1 CQRS of a single database
6.2.2 CQRS for read/write separation
CQRS is not only for the separation of data write and read, its fundamental purpose is to achieve multiple representations of data, each of which can meet the needs of some users. CQRS may have multiple query modes, using databases, Redis, ES, and so on. For example, for complex data Query requests, Command is responsible for dropping data to DB and then synchronizing data to ES, and the Query side queries the required data from ES.
6.2.3 CQRS of the Event Source
When the Command system completes the data update operation, it notifies the Query system through a “domain event”. The Query system updates its data source after receiving an event. All Query operations are done through the interface exposed by the Query system.
6.4 Advantages of CQRS architecture
- The architecture of Command and Query is separated from each other and not bound to each other. They are designed and extended independently
- The Command side usually combines DDD to solve complex business logic.
- The Query side is a lightweight Query where various Query views are updated by subscribes to events
- The Command side scales horizontally through distributed message queues and naturally supports peak clipping
- EDA Architecture (event-driven Architecture), all parts of the whole system loose coupling, good scalability
- Architecture level to achieve no concurrency, to achieve high throughput Command
- Technical architecture and business code completely separated, programmers do not care about technical problems, more convenient division of labor cooperation
6.5 Shortcomings of CQRS architecture
- Transaction issues need to be handled and development costs increase. For example, a Command may need to modify multiple DB databases, and data consistency processing costs are high. CQRS is not strong consistency, but towards final consistency
- Effectiveness. There may be a time difference between the Command end and the Query end after the modification. In this case, the Query end may Query the old data after the Command modification.
- Event delivery requires a stable and powerful distributed message queue
- It must have a strong and reliable CQRS framework, which is costly and risky to start from scratch
- It is best to combine the Event Sourcing mode, otherwise the separation of Command and Query is meaningless
- It raises the bar for developers
7 Reference Documents
“Chinese Architecture and Practice – Based on DDD and Microservices”
How to master DDD business domain modeling, database, and aggregation?
DDD domain-driven design: an in-depth interpretation of anemia models and hyperemia models
Summary of concepts of domain model, anemia model and hyperemia model
Three CQRS architecture patterns