Design a DDD-oriented Microservice

What is Domain Driven Design (DDD)

Modelling based on the reality of the business that is relevant to the use cases is a core principle of domain-driven design (DDD). When discussing context development, DDD refers to issues as domains.

Each unique language is referred to as a Bounded Context, and each Bounded Context corresponds to a microservice. It also provides several technical ideas and patterns to back up the internal implementation, such as domain entities with rich models, value objects, aggregates, and aggregate root rules.

This blog design will explain how those internal patterns were developed and implemented.

Some developers see the learning curve for DDD techniques as being too steep because of the technical principles and patterns of DDD. The patterns themselves are unimportant; what is crucial is writing the code such that it is aligned with the business concerns and use the same business words throughout (ubiquitous language).

Further, DDD techniques should only be used when creating sophisticated microservices with substantial business rules. An example of a responsibility that may be handled with relative ease is a CRUD service.

Finding the right boundaries is the most important part of creating and defining a microservice. DDD patterns facilitate comprehension of the domain’s inherent complexity. Each Bounded Context has its own domain model, for which you must specify the entities, value objects, and aggregates that make up your domain.

Your work involves creating and refining a domain model that operates within a boundary that specifies the context of your work. This is made clear using a microservice. Your microservices are the microservices that fit inside specified boundaries; note that a business microservice may really be made up of many physical services. Boundaries are an important concept in both DDD and microservice microservices.

Maintain small context boundaries for microservices

Boundaries between Bounded Contexts must be determined by weighing two opposing considerations. Create a border around items that need coherence by starting with the smallest feasible microservices; however, this should not be the primary motivation.

The second thing you should do is limit the amount of communication that occurs between microservices. It is possible for these targets to clash with one another. You may strike a compromise between them by breaking the system down into as many tiny microservices as possible, stopping when you see the communication boundaries expanding rapidly with each effort to split off a new Bounded Context. Within a limited setting, consistency is of the utmost importance.

When implementing classes, this is analogous to the Inappropriate Intimacy code smell. It is recommended that two microservices are the same if they need to cooperate often.

The concept of autonomy is another lens through which to examine this component. A microservice cannot be considered fully autonomous if it must rely on a different service to handle requests on its behalf.

DDD Microservices Layers

Most enterprise applications with a lot of business and technical complexity are made up of multiple layers. The layers are a logical artefact that has nothing to do with how the service is set up. They are there to help developers deal with how complicated the code is. Different layers, such as the domain model layer and the presentation layer, might have different types, which would require translations between those types.

For example, a database could be used to load an entity. Then, through a REST Web API, part of this information or a group of information that includes data from other entities can be sent to the client UI. The point here is that the domain entity lives in the domain model layer and shouldn’t be sent to places where it doesn’t belong, like the presentation layer.

Also, you need always-valid entities that are controlled by aggregate roots (see the section on Designing validations in the domain model layer) (root entities). So, entities shouldn’t be tied to client views because some data might not be validated at the user interface level. The ViewModel is for this reason. The ViewModel is a data model that is used only for the needs of the presentation layer. The domain entities are not part of the ViewModel in a direct way. Instead, you need to translate between ViewModels and domain entities and vice versa. When dealing with complexity, it is important to have a domain model that is controlled by aggregate roots. These roots make sure that all the invariants and rules for a group of entities (an aggregate) are done through a single-entry point or gate, the aggregate root.

The Domain Model Layer

In charge of representing the business’s ideas, the business’s situation, and the business’s rules. State that reflects the business situation is controlled and used here, but the infrastructure oversees the technical details of how it is stored. This layer is where business software starts and ends.

The business is written down in the domain model layer. When you set up a microservice domain model layer, this layer is coded as a class library with the domain entities that capture data and behaviour (methods with logic). This layer must not care at all about how data is stored. The infrastructure layer should take care of these persistence tasks. So, this layer shouldn’t depend directly on the infrastructure. One important rule is that the entity classes in your domain model should be POCOs (Plain old class object).

It is important to understand the physical data model and how it relates to your entity object model. If not, you can make designs that can’t be made.

Also, this doesn’t mean that you can directly move a model made for a relational database to a NoSQL or document-oriented database.

The model might fit in some entity models, but most of the time it doesn’t. Still, there are rules that your entity model must follow.

The Application Layer

Defines the jobs the software is supposed to do and tells the expressive domain objects how to solve problems. This layer oversees tasks that are important to the business or are needed to work with the application layers of other systems. We keep this layer thin.

It doesn’t have any business rules or knowledge. Instead, it coordinates tasks and gives work to collaborations of domain objects in the next layer down. It doesn’t have state that shows how business is going, but it can show how far along a task is for the user or the programme.

The application layer of a microservice is often written as a Web API project. The project sets up how the microservices talk to each other, how they access the network remotely, and how the UI or client apps use external Web APIs. It includes queries, commands that the microservice will accept, and even event-driven communication between microservices if CQRS is used (integration events).

The business rules and domain knowledge should be in the domain model class library, not in the Web API, which is the application layer. The application layer must only coordinate tasks and not hold or define any domain state (domain model). It gives the task of executing business rules to the domain model classes (aggregate roots and domain entities), which will then update the data in those domain entities.

Basically, all use cases that depend on a certain front end are implemented in the application logic. For example, the implementation was about a Web API service.

The goal is for the domain logic in the domain model layer, its invariants, the data model, and any related business rules to be separate from the presentation and application layers. Most importantly, the domain model layer must not directly depend on any infrastructure framework.

The Infrastructure Layer

The infrastructure layer is how the data that is initially stored in domain entities (in memory) is saved in databases or another persistent store. One example is using Entity Framework Core code to build Repository pattern classes that store data in a relational database using a DBContext.

According to the Persistence Ignorance and Infrastructure Ignorance principles, the infrastructure layer must not “contaminate” the domain model layer.

You must keep the domain model entity classes independent of the infrastructure you use to store data by not relying on frameworks in a hard way.

Your domain model layer class library should only have your domain code, just POCO entity classes that make up the heart of your software and are separate from infrastructure technologies.

So, as shown in the figure below, your layers, class libraries, and projects should depend on your domain model layer (library), not the other way around.

Final Words

In a DDD service, the Domain layer does not depend on any other levels, but the Application layer does rely on the Domain and Infrastructure layers. Each microservice needs its own customised stack of underlying components.

Smaller data-driven microservices (simple CRUD on a single layer) can be developed using a more straightforward technique, whereas larger, more complex microservices can be created utilising DDD principles.