Aug 10, 2022

Principles of Domain-Driven Design for Microservices

Microservices are the best way to make software that can be used on a large scale.

Principles of Domain-Driven Design for Microservices

Principles of Domain-Driven Design for Microservices

Microservices are the best way to make software that can be used on a large scale. But you need a good design that lets developer teams work independently and deploy without stepping on each other's toes. If you don't have a good design, you might lose the benefits of scalability.

By separating a huge system into smaller, self-contained sections, working out what each element does, and figuring out how it functions with the others, domain-driven development enables us to create a microservice architecture. In this article, we will  cover the fundamentals of domain-driven design and how to apply it to microservices.

How does Domain-Driven Design work?

Domain-Driven Design (DDD) is a method for making software in which developers build models to learn about the business needs of a domain. These models are the basis for the ideas that go into making software.

According to Eric Evans, author of the book Domain-Driven Design, "a domain is a realm of knowledge, influence, or action." Tackling Complexity at the Heart of Software. The topic area that the user uses the program for is referred to as its "domain".

Whether or not you can solve a problem well depends on how well you understand the domain. Even though developers are smart, they can't be experts in everything. They need to work with experts in the field to make sure the code matches business rules and client needs.

Developers and domain experts use a single language to share information, write documentation, make plans, and write code.

Bounded contexts and context maps are the two key DDD concepts for microservice design.

Bounded Context (BC): The meaning of a word is based on where it is used. Depending on the situation, "book" can mean either a written work or "to reserve a room." The area in which a word has a clear and precise meaning is called its "bounded context," or BC.

Before DDD, people usually tried to find a model that covered the whole domain. The problem is that it's harder to find a consistent and unified model the bigger the area of study is. DDD's plan is to find the BCs so that the domain can be split up into subdomains that are easier to handle.

When making software, we have to be precise. Defining BCs is important because it gives us a precise vocabulary, called ubiquitous language, that developers and domain experts can use to talk. The language is used in the design process, in the project documentation, and in the code.

Context Map

Channels for communication have already been developed since there is a BC. When doing online business, for instance, the salesperson should verify the inventory before making a transaction. After it has been sold, shipping is responsible for ensuring that it reaches its destination. These connections are shown in a context map for DDD.

For small services, Domain-Driven Design is used.

DDD is made up of two parts:

During the strategic phase, we find the BCs and draw a map of them.

During the tactical phase, each BC is modeled based on the business rules of its subdomain.

Let's look at how each phase affects the design of a microservice architecture.

The planning stage

During this phase, we get developers, domain experts, product owners, and business analysts together to share ideas, learn from each other, and make an initial plan. With the help of a facilitator, this can take the form of an Event Storming workshop session, where we use important events in the domain to build models and figure out business requirements.

In strategic DDD, we look at design from a high level and work our way down. First, we look at the domain to figure out what its business rules are. We can make a list of BCs from this.

The edges act as natural walls to keep the models inside safe. So, every BC is an opportunity to put at least one microservice into place.

Different kinds of ties

Next, we need to figure out how BCs will talk to each other. Eric Evans talks about seven different kinds of relationships, while other writers only talk about six. A microservice architecture avoids the tight coupling that comes with a monolithic architecture because it doesn't use any of these three concepts (shared kernel, customer/supplier or conformist).So, there are four kinds of relationships:

Open Host Service (OHS): The service provider sets up an open protocol that other people can use. This is a relationship with no end date, since it is up to the consumers to follow the protocol.

A well-known language like XML, JSON, GraphQL, or any other that suits the domain is used in this relationship.

Anticorruption Layer (ACL): This is a way for service consumers to protect themselves. The anti-corruption layer is a translation and abstraction layer that is put in front of a service further down the chain. When something changes upstream, all the service that uses it needs to do is update the ACL.

Separate ways: This is what happens when it turns out that integrating two services doesn't add much value. In other words, this is the complete antithesis of a romantic relationship. This implies that the BCs have nothing in common and are therefore under no obligation to communicate with one another.

At the end of our strategic DDD analysis, we get a context map that shows the BCs and how they are connected to each other.

Phase of action

Deep down, making software is an exercise in modeling. We make a model of a real-life situation and then write code to solve it. In the last step, we found BCs and figured out how they related to each other. At this stage, we'll focus on each context to build a detailed model. To do this, we'll need developers who understand DDD theory.

Models made with DDD are technology-agnostic, which means they don't say anything about the stack underneath. Instead, we put our attention on modeling the subdomain. Most of our models are made up of:

Things with names that remain constant across time are called entities. Entities need special IDs (for example, the account number for a customer). The entities don't need to be the same in every BC, even if entity IDs might be shared across context borders. Every context may include a unique private copy of a certain entity.

Value objects are values that can't change and don't have an identity. They stand for the most basic parts of your model, like dates, times, coordinates, or currencies.

Objects and entities are joined via aggregates. They stand in for an object whose state is constant. One option is to handle the customer, order, and book together. To aggregates, root entities point.

Domain services implement business logic or functionality. An entity-spanning domain service.

Domain events are important for designing microservices because they tell other services when something happens. For example, when a customer buys a book, when a payment fails, or when a user signs in. Microservices can both send and receive events from the network at the same time.

Repositories: Repositories are long-term storage places for aggregates, and they usually look like databases.

Factories: It is the job of factories to make new aggregates.

Domain-Driven Design is an ongoing process.

Even though it may seem like we need to write a complete description of the domain before we can start writing code, DDD, like all software design, is an iterative process.

On paper, bounded contexts and context maps may look fine, but when they are put into practice, they may lead to services that are too big to be called microservices. On the other hand, microservices that talk a lot and have jobs that overlap may need to be combined into one.

As development goes on and you learn more about the domain, you'll be able to make better decisions, improve models, and talk to people better.

More ways to design microservices. DDD is definitely a design pattern with a lot of theory. So, it is only suggested when the system being built is complicated enough to warrant the extra planning work.

Smaller, simpler systems may need TDD or BDD. TDD is the quickest way to start and works best with a single microservice or a few services.

For the behavior of the whole system to be validated, BDD calls for integration and acceptance tests. Maintaining BDD tests after you've reached a specific stage might make you go more slowly.

These three patterns may be combined, with the best one being used at each level. Examples:

Find out what microservices are and how they relate to strategic DDD.

Tactical DDD is used to model each microservice.

Since each team is independent, they can choose to use BDD, TDD, or a combination of the two to build a microservice or a group of microservices.