37 First Focus on Ddd Before Discussing Microservices, as It Is Just a Deployment Form

37 Focus on DDD before discussing microservices, as it’s just a deployment option #

Hello, I’m Zheng Ye.

In the “Automation” module, let’s talk about a practice that many people are enthusiastic about discussing but haven’t done well: microservices.

In backend services today, there seems to be a tendency that if you don’t say you’re doing microservices, you’re too embarrassed to greet people when you go out.

At technical conferences, various large companies also come out in support of microservices, constantly emphasizing the benefits of doing microservices in their own companies. The audience below is also enthusiastic and ready to use microservices to save their businesses.

I have personally witnessed such examples. Several people who attended a technical conference returned to their companies and kept talking about the benefits of microservices, convincing their leaders to use microservices in the upcoming major project overhaul.

And what happened? After a few months, the independently developed microservices could not be integrated. In the end, the leader had to step in and spent another half a month to reassemble these “microservices” together, barely getting the system online.

Why are other people’s microservices so beautiful, but when they come to you, it becomes a mess? It’s because you only learned the form of microservices.

Microservices #

Most people’s understanding of microservices comes from an article written by James Lewis and Martin Fowler in 2014, in which they provided a clearer definition of microservices as a new architectural style.

However, in reality, many people had been discussing the concept of “microservices” years before that.

The idea of “organizing services within an enterprise” was derived from Service-Oriented Architecture (SOA), but SOA, which originated from the era of big enterprise-driven technologies, was too complex to become popular. Microservices, on the other hand, are more lightweight and appealing to programmers, which is why they have gained greater popularity.

When you think about microservices, what comes to mind? For many people, the understanding of microservices is breaking down a large backend system into small services, and then thinking about a bunch of tools.

Therefore, most of the content available on the market that introduces microservices mainly focuses on discussing how to use specific tools or technologies. For example, using Spring Boot to quickly build services, using Spring Cloud to establish a distributed system, using Service Mesh technology as the infrastructure for services, and how to ensure transaction consistency in a microservices architecture, among others.

Indeed, this content is valuable when implementing microservices. However, we must first answer one question: why do we need to do microservices?

The standard answer to this question is that compared to a monolithic service, microservices are small enough, making the code easier to understand, testing easier, and deployment simpler.

All of these reasons are valid, but they are the result of successfully implementing microservices. So, how can we achieve this state? There is a key factor involved: how to divide microservices, in other words, how to decompose a large system in a specific way.

This is the most lacking aspect in many discussions about microservices, and it is the fundamental reason why many teams fail miserably when implementing “microservices.”

Without understanding this point, the services you write will either call each other, resulting in extremely low system performance, or you will need to put in a lot of effort to solve data consistency issues between services. In other words, if service division is not done properly, what awaits the team is an endless quagmire of accidental complexity. Only when microservices are divided correctly will they become what you envision.

So how should microservices be divided? You need to understand Domain-Driven Design.

Domain Driven Design #

Domain Driven Design (DDD) is a methodology proposed by Eric Evans for system analysis and software modeling. What problem does it solve? It is about converting business concepts and rules into concepts and rules in software systems, thereby reducing or hiding the complexity of the business, and making the system more scalable to deal with complex and changing real-world business problems.

This sounds natural. Shouldn’t problems be solved this way? Not necessarily, the reality is not so ideal.

Before DDD, people mostly used data-oriented modeling. Even today, many teams still think of creating database tables as their first reaction when modeling. This practice is a typical technology-driven approach. Once the business changes, teams are usually caught off guard.

So what does DDD talk about? It shifts your thinking from a technical perspective to a business perspective.

Getting closer to the business and getting closer to the customer’s needs is something we have mentioned many times in this column. However, it may still be something that many people are not accustomed to when it comes to code. The foundation of DDD is the Ubiquitous Language, which allows business people and programmers to speak the same language.

I have mentioned this in “Chapter 21 | Who Are You Writing Your Code For?”. By using a Ubiquitous Language, the level of thinking is shifted from the details of the code to the business level. Higher-level abstractions are more stable, while details are more prone to change.

With a Ubiquitous Language as the foundation, we then move on to the practical implementation of DDD. DDD consists of Strategic Design and Tactical Design.

Strategic Design is top-level design that helps us divide the system into different domains and handles the relationships between different domains. I gave you the example of “Order” and “User” in the previous content. Differentiating concepts based on the business and placing different concepts in different places is the fundamental solution. Otherwise, no matter how well your code is written, confusion is inevitable. This way of thinking about problems from a business perspective is what DDD’s Strategic Design brings to me.

Tactical Design typically refers to how to organize different domain objects at the technical level within a domain. For example, Chinese programmers often prefer to use MyBatis for data access rather than JPA, with the common reason being that JPA performs poorly in situations involving associations. But the real reason is that the associations were not designed properly.

If we can understand the Aggregate Root in DDD, we can find a suitable access point instead of allowing everyone to freely access any data. This is a problem that needs to be considered in Tactical Design.

Strategic Design and Tactical Design discuss different levels of issues. However, this was not initially clarified by Eric Evans, which led to people not understanding the value of DDD for a long time.

Towards Microservices #

After talking for so long, what does this have to do with microservices? The real challenge of microservices lies not in technical implementation, but in business division, which happens to be the strength of Bounded Context in DDD strategic design.

Although a common language breaks down the barriers between business and technology, computers are not good at dealing with ambiguous human language, so the common language must be expressed in specific contexts to be clear. Just like the example we mentioned earlier, the “order” for transactions and the “order” for logistics are different, and they each have their own context, which is the bounded context.

It sets the boundaries within which a common language can be freely used, and once crossed, the meaning can no longer be guaranteed. It is because of the existence of boundaries that a bounded context can become an independent deployment unit, and this deployment unit can become a service.

Therefore, to do well in microservices, the first step should be to identify bounded contexts.

As you can see, each bounded context should be independent, and there should not be a lot of coupling between each context. The problem of a large number of inter-service calls, which confuses many people in microservices, is itself a pseudo-proposition caused by not properly delineating boundaries. It is futile to try to solve business problems with technology alone.

Having bounded contexts, can we start doing microservices? Not so fast!

When Martin Fowler wrote “Patterns of Enterprise Application Architecture,” he proposed the first law of distributed objects: Don’t distribute objects. The same applies in the microservices domain. If you want to build a microservices architecture, the first step is to not use microservices. If you turn a monolithic service into microservices without careful consideration, the introduced complexity will eat away at the advantages you thought you had.

You might say, “I have already delineated the bounded contexts, so why are you telling me not to use microservices?”

Do you remember what I mentioned about modularization in “30 │ What Should a Good Project Automation Look Like?” If you have identified bounded contexts, try dividing them into modules first.

In my opinion, it is not easy to delineate boundaries all at once. It would be much easier to adjust if everything is within one process. Then, let the different bounded contexts evolve independently. When they have evolved to the point where they are worth deploying independently, then consider the issue of microservice decomposition. By that time, you will have also learned various technologies related to microservices, which will come in handy!

Summary #

Microservices are the focus of many teams’ efforts, but currently most introductions to microservices in the market only stay at the technical level. Many people see the benefits of microservices, but encounter difficulties when implementing them in their own teams. To do well with microservices, the key lies in the division of services, and it is best to learn DDD first.

In 2003, Eric Evans wrote “Domain-Driven Design” and introduced DDD methodology to the industry, immediately attracting widespread attention. However, to be honest, Eric’s ability to disseminate knowledge is average, and the writing quality of this seminal work on DDD is not commendable. It is very difficult to learn DDD well through it. Therefore, in the foreign technical community, many people gradually realize the value of DDD through various discussions, but DDD has hardly caused a stir in China.

In 2013, ten years after Eric Evans published “Domain-Driven Design,” DDD was no longer obscure, but had its own relatively complete system. Vaughn Vernon, after carefully organizing the essence of the past ten years, wrote “Implementing Domain-Driven Design,” finally giving ordinary technical personnel the opportunity to understand what makes DDD so good. So, you will find that in recent years, there has been a lot of discussion about DDD in the Chinese technical community.

Later on, because “Implementing Domain-Driven Design” was too thick, Vaughn Vernon wrote a condensed version called “Domain-Driven Design Distilled,” which allows people to quickly get started with DDD. This book is also my recommended choice for others to learn DDD.

Even if you have learned DDD and understand bounded contexts, don’t use microservices lightly. The approach I recommend is to first use modularization within a project to allow the services to evolve for a period of time. Only when you truly feel that a certain module can “graduate” should you embark on the journey of microservices.

If you can only remember one thing from today’s content, please remember: Learn Domain-Driven Design.

Lastly, I would like to ask you to share your understanding of DDD. Please write down your thoughts in the comments.

Thank you for reading. If you found this article helpful, you are also welcome to share it with your friends.