Microservices Patterns: Business Service Patterns

Microservices Patterns Series — Part 05: Hexagonal Architecture, Domain Model Pattern, Domain Driven Design (DDD), Aggregate Pattern and more.

Crishantha Nanayakkara
Cloud Native Daily

--

Building business logic/service for an enterprise application whether it is a monolithic or microservice has more similarities than differences. In both approaches, it will comprise classes such as services, entities, repositories, etc. However, you will find some distinct differences as well. In this blog, I will try to emphasize those differences in a conceptual manner by revisiting some of the core design patterns and principles built into each architecture.

So, let's start with Hexagonal Architecture and how it relates to the enterprise application business logic.

Hexagonal Architecture

Any business service in an enterprise application theoretically leverages the Hexagonal Architecture at its core.

The Hexagonal Architecture / Ports and Adapter Architecture is an architectural pattern used in software architecture design. It aims at creating loosely coupled application components that can be easily connected to their software environment by means of ports and adapters. (Wikipedia)

Figure 01 — Hexagonal Architecture

As you can see in Figure 01, the business service logic is the core of the Hexagonal architecture.

Domain Model Pattern

The traditional procedural Transactional Script Pattern is often a good way to implement “simple business logic”.

Transaction Script Pattern: Organize the business logic as a collection of procedural transaction scripts, one for each type of request.

But when implementing a “complex business logic”, you should consider using the Domain Model Pattern, which is basically using the Object Oriented Design (OOD).

Domain Model Pattern: Organize the business logic as an object model consisting of classes that have state and behavior [1].

Domain Driven Design (DDD)

However, the Domain Model Pattern works well with a typical monolithic application back-end, it has certain limitations in Microservice applications, which is basically covered by the Domain Driven Design (DDD).

DDD is a refinement of OOD and it is an approach for developing the complex back-end business logic.

When using DDD, each service has its own domain model, which avoids the problem of having a single unified domain model for the whole application.

Strategic Patterns vs Tactical Patterns

DDD comes up with multiple strategic and tactical patterns.

Two of the key strategic patterns are Subdomains and Bounded Contexts. These patterns are basically useful to decompose the business logic in an application.

According to Vaughn Vernon’s book of “Implementing Domain Driven Design” [5], The subdomains live in problem space and the bounded contexts in the solution space.

In other words, while bounded contexts help you to manage the complexity within an application, Subdomains help to structure and organize the different aspects of the business domain.

In practice, bounded contexts often align with a subdomain, but it is also possible to have multiple bounded contexts within a single subdomain or to have a bounded context that spans multiple subdomains.

In each bounded context, we can build teams who are specialized in the respective domains to govern. These teams are there to build artifacts, requirements, specifications and services for the given domain.

The tactical patterns are basically building blocks of the domain model that you define in your service. Some of these tactical design patterns are Entity, Value Object, Factory, Repository, Service and Aggregate.

In this blog, let's dive a bit deeper into the Aggregate Pattern and its usefulness in a typical microservices design.

Aggregate Pattern

Aggregator Pattern: Organizing a domain model as a collection of aggregates, each of which is a graph of objects that can be treated as a unit [1]

A “traditional domain model”, is a collection of classes and relationships among them. In this model, all of classes and relationships are interconnected and it is relatively hard to find boundaries of each business object, which is the key requirement in a complex microservices design. The Aggregate Pattern in DDD can help you to solve this problem.

In the Aggregate Pattern, as per the definition, structuring a domain model as a set of aggregations makes their boundaries explicit and easier to understand.

Figure 02 — A Domain Model with Aggregates

Each Aggregate has a Root Entity (Aggregate Root) and possibly one or more value objects.

However, that does not mean one Aggregate can have only one entity. You can have multiple entities within an aggregate. But the best practice is to have fine-grained services with a minimum number of entities within an Aggregate to improve the scalability of each transaction.

The Aggregate Root is the main entity that holds references to the other aggregates in the domain model and it is the only entity in the aggregate that can be used for a direct lookup. Components such as value objects within the aggregate will have object references with each other. In figure 02, you will see this and each referred aggregate primary key ids are stored in the main aggregate, which is Aggregate 01. This allows to have a more loosely coupled architecture within the domain model.

An aggregate is often loaded entirely from the database (to avoid any lazy loading). Even while it is being deleted, the aggregate removes all of its objects from the database within its boundary. In addition to that, it is easier to store them in NoSQL databases such as MongoDB.

In a nutshell, applying the DDD Aggregate Pattern will,

  1. Modularize the domain model in the service
  2. Eliminate the possibility of object references between services (In DDD, references between classes in different aggregates are in terms of primary key value rather than object references)
  3. A transaction can only create or update a single aggregate. This allows the application to use the Saga Pattern to update multiple aggregates (I discussed Saga Pattern in detail in one of my previous blog articles)

Aggregate and Saga Patterns

A Saga orchestrates a sequence of local transactions within a sequence of (micro)services in order to maintain data consistency. Each local transaction is having an Aggregate mapped to it. (See Figure 03).

Figure 03 — Connecting the Aggregate Pattern and the Saga Pattern

Aggregate vs Bounded Context

In technical theory, there is a bit of a misconception about the difference between a bounded context and an aggregate. Therefore, it is imperative to understand the difference between them and their association with microservices.

As explained earlier, a microservice could be explained by a bounded context or a domain. Each bounded context will have one or more aggregates.

Therefore, in practice, a microservice should not be smaller than an Aggregate and should not be bigger than a bounded context.

Figure 04 — Bounded Context vs Aggregates

Domain Event Pattern

Conceptually domain events are published by aggregates whenever they get created and updated. An aggregate knows when its state changes and hence what event to publish.

These domain events are ultimately published as messages to a message broker such as Kafka.

Domain Event Pattern: An aggregate publishes a domain event when it is created and undergoes some other significant change [1].

Event Storming

There are a few strategies for identifying domain events. One popular strategy is Event Storming, which can be performed via a workshop sort of an arrangement to understand a complex domain with many events. The end result of such a workshop is an event-centric domain model with aggregates and events.

Conclusion

That’s it! Hope you got some good insight into Microservice Business Service Patterns and other related concepts by reading this blog. You can find my other blogs related to Microservices Patterns and Concepts using the following links:

  1. Microservices Patterns: Inter Process Communication
  2. Microservices Patterns: The Circuit Breaker Pattern
  3. Microservices Patterns: The Service Discovery Patterns
  4. Microservices Patterns: The Saga Pattern

Thank You!

References

  1. Microservices Patterns: with Examples in Java [Book] — By Chris Richardson, Manning Publications, 2018
  2. Domain Model Pattern: https://martinfowler.com/eaaCatalog/domainModel.html
  3. Aggregate Pattern: https://microservices.io/patterns/data/aggregate.html
  4. Domain Event Pattern: https://microservices.io/patterns/data/domain-event.html
  5. Implementing Domain Driven Design [Book] — By Vaughn Vernon, Pearson, 2016

--

--

Crishantha Nanayakkara
Cloud Native Daily

Enterprise Architect, Consultant @ FAO (UN), Former CTO, ICTA Sri Lanka