When I was planning and designing microservices architecture, I was given a reminder that STILL sticks in my mind: “Why don’t you see DDD in your design blueprint?”
With the deepening of my understanding of the domain of congestion model, I feel the importance of DDD more and more. So the net a sea search, and made study notes.
DDD has a variety of contents. In my humble opinion, the core point of DDD is to separate the business logic layer from the traditional anemia model and integrate it into the Domain layer. In this way, facing the large-scale change of complex business, we only need to focus on Domain.
Getting back to the topic, what does microservices have to do with DDD?
Because in the Internet age, the problem domain faced by software is much more complex than before, and this complexity comes from the expanding problem domain itself, as well as innovation and change, and the challenges brought by this scale growth.
However, there is a limit to how much complexity can be perceived by one person as a team, and the only way to deal with such complexity is to divide and conquer. Points mainly consider how to points; Governance means that each part should be able to operate independently, cooperate with each other, achieve the overall goal, and cope with the impact of external changes.
Limitations of microservices
Microservices architecture provides good theoretical guidance and best practices in both divide and conquer. Is microservices a silver bullet to solve complex problems? This is not the case. Many teams have applied microservices architecture to build their systems, only to find that this complexity has not been fully resolved, and some other problems have even been introduced. Such as:
-
Services do not solve the problem of how complex systems respond to changing requirements, and even exacerbate it.
-
When a requirement changes, it takes a lot of effort to identify which microservices are affected by the change, and there is endless wrangling between teams of those services to decide which services should be more and which should be changed less.
-
The test team then has to do expensive joint testing
-
Even so, the development team is still not at ease, but through a series of switch control, carefully to do cutting flow, to do grayscale release.
From a business perspective, the microservices architecture is not immune to this kind of scattershot modification. It even made him worse. Why? One important reason is that microservices architecture is not considered fully at this latitude.
DDD function
What dimensions do we need to consider when we’re doing this kind of dividing? I think we need to consider at least three dimensions:
-
Function of latitude
-
Quality latitude, like performance, availability
-
Engineering latitude
Microservices gives a good guide for the second, and some advice for the third. However, very limited guidance has been given to the first functional dimension, which is why domain-driven design (DDD) has received a renewed emphasis with the popularity of microservices.
DDD makes up for the fact that microserver does not provide a good guide to function partitioning. So they have a complementary relationship when facing complex problems and building systems, and can cooperate well when the system is split.
They just look at it differently. Services in microservices focus on the domain layer of the hexagonal architecture advocated by DDD.
Break up the case
Next, DDD and microservices are combined to break up a complex system.
On the field
We call the scope of an enterprise’s business and activities within this scope domains, independent of software systems. The domain will be divided into multiple sub-domains. For example, in our e-commerce system, there will be:
-
Commodity subdomains
-
Order subdomains
-
Inventory subdomains and so on.
Different concepts have different meanings in different subdomains. So when we do domain modeling, we must have a clear domain boundary, which is called bounded context in DDD, which is an architectural boundary inside the system that determines the architecture of the system.
Divide the internal architecture boundaries of the system
It is said in this book that “the architecture of a system is determined by the internal architectural boundaries of the system and the dependencies between the boundaries, and is independent of the communication and invocation of various components in the system”. The service invocation of microservices is itself a form of partitioning application behavior that is slightly more expensive than function invocation, regardless of system architecture.
Therefore, the first important thing to delineate a complex system is to delineate the internal architectural boundaries, that is, to delineate the context, and to clarify the relationship between them, which corresponds to the functional dimensions we talked about earlier. This is where DDD comes in. Then we think about the non-functional dimension, which is where microservices can play to their strengths.
For example, we divide the system into THREE contexts, ABC. The code of the three contexts can be run in a deployment unit, and operations can be completed through in-process calls. This is a typical singleton architecture.
They can also run in a separate deployment unit, with remote calls, which is the prevailing microservices architecture.
The benefits of clear boundaries
We are more of A hybrid of the two architectural patterns, such as A and B as one deployment unit and C as A separate deployment unit, often because C is very important, its concurrent traffic is very high, or its requirements change frequently. Splitting C has the following advantages:
-
Resources tilt
-
Use elastic design patterns: retry, fuse, degrade
-
Use special technologies: Go, for example
-
Independent code base: There are independent teams and operation personnel, and the runtime of A and B is isolated from each other
These four points are the focus of the service architecture, which takes a non-functional latitude view of fragmentation, focusing less on the logical boundaries of the system architecture and more on the separation of application behavior.
Why not split A and B into separate deployment units?
It will bring more benefits, also can bring additional costs, the evolution of architecture should be, in the early days of business development, should pay attention to logical boundary of system architecture, keep the logical boundary clear and relationship of right, with the increase of business volume, doing split step by step, this is a combined application of DDD and micro service architecture maximum benefit.
In a single architecture, it is difficult to keep the logical boundaries of the architecture intact. If the logical boundary is not clear, when the server needs to be split, it may not be able to be torn out. In addition, no one can define logical boundaries correctly all at once, even if the context is not quite correctly defined, and the concept of aggregation roots in DDD ensures that we can evolve a more appropriate context.
The DDD bounded context internally models domain concepts through entity and value objects, a set of entity and value subobjects belonging to an aggregate root. That’s according to DDD
-
The aggregation root is used to ensure correctness of internal entity rules and consistency of data
-
External objects can only refer to the aggregate root by ID, not entities inside the aggregate root
-
Aggregation roots cannot share a database transaction, and data consistency between them needs to be guaranteed through final consistency
With aggregate roots, based on these constraints, it will be easier in the future to upgrade the aggregate roots to context and even split them into microservices as needed.