Building applications with Microservices

Rebai Hamida
5 min readNov 12, 2020

Introduction

To build a successful microservices application, you need to make many key choices about which technologies you need to use. In this article, we will discuss about several patterns and practices that will enable developers to build microservices. First, we will discuss about how to structure domain logic and implement a data mapping layer. Next, we will discover the various ways to test microservices.

Microservices approach

In a microservices architecture, each microservice has clearly defined responsibilities to implement certain business capabilities, and this means that each of our microservices will contain some business logic or domain logic.

We are face many challenges of implementing the domain logic for our microservices, we began by taking decisions that is which microservice should contain the business logic. This is an important decision because we don’t want to duplicate business logic, and we also don’t want to bloat microservice with too many responsibilities, so sometimes we might find that we need to create a new microservice.

Domain Logic Patterns

When it comes to implementing the domain logic for a microservice, several patterns are available to us. And there are a number of ways that we could categorize the choices available, but I’m going to use some pattern names that come from a classic book called Patterns of Enterprise Architecture, written by Martin Fowler along with a number of other authors

We can mention three patterns:

- Transaction script pattern, which is the simplest approach, and may be suitable for microservices with minimal business logic, but this pattern can introduce problems with duplication over time.

- Domain model pattern makes use of object‑oriented programming techniques and fits well with the domain‑driven design approach. We saw this technique in action in the ordering microservice in eShopOnContainers.

- Table module pattern brings together all of the domain logic for the entities stored in a database table into a single class, and this option might be used as a way of eliminating the duplication from a transaction script approach.

Data Access Patterns and techniques

eShopOnContainers is an online shop, and so we’re in the e‑commerce domain. It’s also a non‑trivial application. It consists of several microservices, uses a number of different third‑party tools, and also has a couple of different frontend applications, including a mobile application. It’s also being actively maintained and updated to take advantage of new tools and best practices. It’s also containerized, each microservice is built into a Docker container, meaning that you can run it on any Docker‑hosting platform, such as Kubernetes. And whilst containers aren’t a requirement for microservices, they are a very good choice, and we’re going to be seeing some of the benefits of containerization when we see in our demo how to run it. Because it’s been containerized, we can also run it cross platform, so you can easily run eShopOnContainers on Windows or Mac, so long as you’ve got Docker installed. And the documentation for this project is very comprehensive, so you can dive deeper into how it works and why the various design decisions were made if you want to by visiting the project pages on GitHub.

In the ordering microservice in eShopOnContainers. We saw how it keeps the domain logic separate from the data mapping layer, which helps keep our code maintainable and testable. We saw how it used the CQRS pattern to separate commands from queries. In the implementation of the commands, we saw several patterns, including using an ORM, in this case, it was Entity Framework Core, using the repository pattern to encapsulate some of the ORM‑specific calls, and using the unit‑of‑work pattern to save all the changes that we made in the command handler in one go.

Data separation is beneficial because it makes our domain logic simpler and easier to test. Object relational mappers are very popular for mapping data stored in relational databases into objects, and we saw an example of this approach with Entity Framework in eShopOnContainers, but alternatives are available, such as using micro‑ORMs or even handcrafting raw SQL directly. And these approaches can give us more control over the performance of our queries.

Test Patterns for Microservices

We need to understand the importance of having a comprehensive testing strategy for your microservice applications using the concept of the test pyramid as a guide. We can implement unit tests for high code coverage of our business logic, and these can provide us with very rapid feedback if we’ve broken any key functionality, as well as protecting us against regressions. We can adopt the discipline of test‑driven development, it will not only lead to code with higher test coverage, but generally improve the overall structure and design of our code. Then we have the service‑level integration tests for each microservice, allowing us to verify that its public API behaves as expected and that it can communicate properly with its data store. And we shouldn’t forget the end‑to‑end or user interface tests, which are harder to write and slower to run, but they allow us to verify that all the parts of our microservices application are properly interacting with each other. Finally, we need to focus on the importance of automating the running of all of these types of tests so that you get feedback as soon as possible if something has been broken in your system. If you have taken the trouble to create good tests at each of these levels, then that will give you a high degree of confidence that your microservices are ready for delivery to production when all the tests are passing.

--

--

Rebai Hamida

Senior Cloud Application Architect, Microsoft MVP in Developer Technologies, MCT, Technical writer, Speaker