Before we start , Let's look back at the root of all evil :
It takes a few steps to put an elephant in the refrigerator ?
There should be many friends in the computer department who are deeply impressed by this problem , It is the first question that most universities ask when they teach object-oriented courses .
And we usually get two answers :
- It takes three steps , Open the refrigerator door first , Then put the elephant in the fridge , Then close the refrigerator door .
- It takes three steps , Refrigerator open door , The elephant goes into the refrigerator , The refrigerator closes the door .
These two answers , It's essentially a difference in thinking , The first answer is to examine the problem from the perspective of the first person , This way of thinking we call it Process transaction script .
The second answer is to stand in different positions thing From the perspective of , This way of thinking we call it Object oriented idea .
Process transaction script , In fact, it is a listing of the problem-solving process , There are advantages , For example, there is no additional cost of thinking , It's easy to write , Low entry threshold, etc . But from the perspective of complexity and the objective law of affairs development , It is not the most appropriate .
notes :‘ The objective law of the development of things ’ It means things are complicated 、 The direction of entropy increase .
Why do you say that? , Let's look at a practical problem .
Starting from the problem
Suppose we want to develop a mall system , At the beginning of the design , The product gives the following requirements :
After the user submits the order , Calculate the total amount of order goods in the background , Save a snapshot of the order line item , Lock the inventory, then generate the order and echo .
So the R & D department wrote the first version of the program according to the requirements :
class OrderService is
method createOrder(createOrderInputDto): Order is
// Deconstruct the data needed from the order creation object
// Calculate the total order amount
// Save a snapshot of the order line item
// Lock in inventory
// Create an order and return After the program goes online , Due to the proliferation of users , Single applications can not meet the needs of a large number of users very soon , So the product department asked the R & D department to split the service , Further increase the system concurrent requests , Then the second version of the program came out :
class OrderService is
method createOrder(createOrderInputDto): Order is
// Deconstruct the data needed from the order creation object
// + Call the remote service to get the product data
// Calculate the total order amount
// Save a snapshot of the order line item
// - Lock in inventory
// + Call the warehousing service to lock the inventory
// Create an order and return And then one day , Run a pat on the thigh , Decided to hold a special event :
When users consume , Rebate shall be made according to the user's membership level and single consumption amount , The rebate is directly subsidized into the total amount of a single consumption order , It also allows users to use the coupon stack to calculate the discount amount .
Busy program apes once again carry the keyboard ready to fight , So the latest program came out again :
class OrderService is
method createOrder(createOrderInputDto): Order is
// Deconstruct the data needed from the order creation object
// Call the remote service to get the product data
// + Call the remote service to obtain the user member level benefit information
// Calculate the total order amount
// + Calculate member grade discounts and rebates
// + Calculate the total order amount again
// + Calculate the amount after the coupon is superimposed
// Save a snapshot of the order line item
// Lock in inventory
// Call the warehousing service to lock the inventory
// Create an order and return After this , Some new ideas come to mind from time to time in the operation of brain opening , The R & D department is full of happy air ...
What's the problem with this ?
On the whole , stay Service Layer stacked code , Not just business code , It also includes application service scheduling , Database operation , The authorization authentication of the framework is not related to the business , But the logic that is strongly related to the technical level . Database operation and application service scheduling are highly coupled to this service , This is obviously not good in the long run .
Let's go deep into createOrder This method , Take a look at some of the code :
It is assumed here that we have started to create orders Model 了
Order order = new Order();
order.setUserId(xxx);
order.setItems(xxx);
order.setPrice(xxx);
...
...The above code is a description of the business requirements , In the mall system, it is expressed by the semantic behavior corresponding to an order creation , But here it turns out to be true Model Assignment of , And these assignment operations are not limited to processing values , This is likely to produce a wrong result , For example, we will Price This unit of value gives a negative value .
Some people may say setPrice Is the encapsulation of variables in a class , We can verify the assignment in this function . But most of the practices given by the community , Still service There are many business level verifications .
Consider from another angle , Such code depends on the developer's understanding of the business , But we can't guarantee that every developer's understanding of the business is correct , So it's easy for developers not to know whether a field should be assigned a value , Or wrong value .
This is essentially because The expression of business is transforming into <u> Process transaction script </u> Lost in this process , We are writing business code , Naturally describe the behavior with semantics in the business , It turned out to be right Model Assignment of some variables in , This leads to the loss of semantics .
Process transaction script and object-oriented thinking
As mentioned above , Process transaction scripts tend to lose semantics , Is there any way to solve this problem ? The answer is yes. , Is the object-oriented idea .
The traditional object-oriented thinking holds that :
The essence of a program is to model and abstract reality
Let's take a look at the conventional practices of modern communities to see if they are in line with the current situation object-oriented The concept .
In the field of traditional software development , The usual way to deal with business is According to the business requirements and interaction prototypes given by the product manager , Divide the system function modules and design the database tables corresponding to each function module . In this design process, we mainly consider the attributes hidden in the business , The specific business interaction process and the behavior of its objects are separated into MVC In the controller in the third layer .
In the field of game development , The conventional approach is to model based on the main object designed in the game , The final result is a system with attributes and behaviors The object model , A very vivid example is as follows :
In this case , We are going to design a game modeled after the League of heroes , The requirements for heroes are described as follows :
- Heroes have HP and mana
- The hero's HP and magic value will slowly recover over time
- Heroes lose a certain amount of mana every time they cast a skill , Magic value is 0 You cannot release skills
- Heroes can use normal attacks to inflict heavy damage on their opponents
- When HP decreases to 0 when , The hero dies
We can meet the above requirements for “ hero ” Modeling of this object :
class Hero is
// Hero's HP
property Blood: Float
// The magic value of the hero
property Magic: Float
// timer Used to control the hero's HP and mana recovery
var _timer: Timer
/**
* The hero is attacked
*/
method UNDER_ATTACK(who, how) is
// Calculate new HP
/**
* Heroic death
*/
method HERO_DIED() is
// Call destructor , Destroy a hero object
/**
* Build a new hero
*/
method constructor is
// Initialize auto reply timer
/**
* Hero's attack method
*/
method attack(target) is
// Release the event of attacking the hero
/**
* How heroes release their skills
*/
method release(skill) is
// Generate skill release effect
// collision detection
// Trigger attack effect
/**
* Initialize auto reply timer
*/
private method initialTimer()From the above code, it is not difficult to find , hero There are more than attributes inside this model , There are actions and events , It is obviously more natural to encapsulate the business behavior of objects into the model , The subsequent business iterations and changes are obviously better maintained .
So if we use the design method to deal with traditional software to design the above game , What will happen ?
First we need to traverse all the heroes in the whole map , Then deal with their health and magic value recovery logic one by one . When a hero has an attack state , We need to traverse all the heroes in the whole map again , Conduct collision detection one by one , Then deal with the logic of blood deduction and death determination . I don't need to say more about the rest. I think you can imagine it ...
also , When we build the action behavior using the process transaction script , The business has obviously become more complicated , Also produced a lot of unreasonable , Difficult to maintain .
therefore , When we look back and reflect , Whether the traditional software industry has achieved Traditional object-oriented The concept of , We already have the answer .
Anemia model and congestion model
Said so much , In fact, there is only one fundamental reason for the development of design towards process transaction scripting or object-oriented thinking , That's it Model .
As I said before , A program is an abstraction and modeling of the real world , Computers were originally created to meet the basic needs of life . Under the traditional development mode , We have always adhered to the principle of giving priority to databases , All coding ideas are implemented around the established database tables , So we separate data from processing logic , The data is controlled in Model Intralaminar , Logic is separated into Controller Layer , In this way Model We call it Anemia model , Because it has only properties and no behavior .
A model based on object-oriented thinking , It contains both attributes , It also contains the behavior and events of the target object , So it's also called Congestion model , The hyperemia model has the following advantages :
- Independent , portable
- complete
- Self contained
Therefore, the congestion model can be tested separately during development , To determine the correctness of domain business logic processing , The same as the traditional principle of throwing the pot .
The traditional principle of throwing the pot : Front-end based Mock Data completion page requirements , Without cross domain problems , If there is a problem after the backend is connected , The pot must be at the back .
That means , On the premise that unit testing can ensure that there is no problem with the congestion model of domain objects , If there is a problem with the final interface implementation , The problem must lie in the division Model On a level other than a level , This well isolates the concerns of domain business and technical logic .
The father of modern software architecture Martin Fowler It is considered that anemia model is an anti model , Because the modeling in the software development process needs to correspond to the business in a specific field , This separation of domain logic and data expression , Contrary to the design rules derived from nature .
For continuous evolution , For a business that iterates frequently , Hyperemia model is a good choice , But it also has the following disadvantages :
- The design is very difficult
- Designers need to be highly familiar with the business
- Unstable congestion models can cause frequent changes in code at other levels
Relative , If the business needs are relatively simple , Obviously, anemia model is a better choice .
Domain-driven design
Domain-driven design 【Domain Driven Design】( Hereinafter referred to as" DDD), yes :
- A complete set of model driven software design tools , Used to simplify the complexity of large software projects .
- A design idea , It can be applied to the software design of complex business , Accelerate delivery .
- A set of refined principles and models , It helps to improve the software core business design ability of team members .
Why do we have to learn DDD
It helps to divide micro services
DDD By dividing the fields , And confine the divided domain to the context , To isolate concerns . The context here , stay DDD Is called Bound context .
Just like cells in biology , The reason why cells can exist , Because the cell membrane defines what's inside the cell , What's out of the cell , And identify what substances can pass through the cell membrane .
Each domain model in the subdomain has its corresponding bound context , All bounding contexts in the domain ( Contains internal children · Domain model ) Together, they form the domain model of the whole domain . We map the bound context to the microservice , This completes the division of the entire microservice .
Reduce the difficulty of complex system iteration
The reason why complex systems are difficult to iterate , The reason is that the traditional design method based on database can not limit the “ Variable ”, These variables may become the key to domain collapse at any stage of system iteration .
The meaning of software is that it can solve the problems in reality ,DDD One of the main steps in is to sort out and divide the problems of business expression , Divide the big problem into several small problems , Then solve it one by one .
This method can limit the variables in the subproblem to the greatest extent , So as to reduce the iteration complexity .
Improve the efficiency of R & D team collaboration
The traditional design idea follows DDD The biggest difference is :DDD Focus on business semantics , Advocate the establishment of a unified description language for business , The design of the system is based on the team members' consistent understanding of the business , This is conducive to the communication and exchange of the team .
Books & Article recommendation
Books
- 《 Domain-driven design : How to deal with the complexity of software core 》- Eric Evans
- 《 Implement domain-driven design 》- Vaughn Vernon
- 《 Deconstruction Domain Driven Design 》- younglab
article
- from CQS To CQRS ( translate )
- DDD The patterns in — CQRS
- [ABP Official Guide to the framework ](








