Trendyol Tech
Published in

Trendyol Tech

Take a look at CQRS and Event Sourcing with DDD — Part 2

Once we have an idea about Event Sourcing, CQRS and DDD, we can now implement them. Since we adopt the DDD approach, we will create our project and layer structure according to.

In a simpler way, I will try to explain it without increasing confusion.

If you haven’t read the previous article, you can read it here.

Funkhu — Kemal Sunal, Şener Şen

Let’s start, Funkhu!

When we start doing Event Sourcing and CQRS, we should now consider all transactions as events. And we have to make the transition between layers loosely coupled by doing events. On the other hand, we hit from the service layer to the domain layer, and after every changes we make to the domain, we must throw the event(s). In this way, events has been thrown for all transactions that are performed, and the reliability of the transaction is also ensured. If an error occurs during the transaction, it will be easier for us to follow it because we can store every event and log the necessary about it.

So how do we implement it?

First, I start by creating the project structure. I preferred to proceed using onion architecture. Because Onion Architecutre, which is very convenient for DDD, it will provide you to separate the layers more accurately and responsibilities more. For more information on Onion Architecture, look at here.

Understanding Onion Architecture

As seen in the onion architecture diagram above, I have created a focused structure for Domain, Domain Services and Application services for Application Core as follows.

According to the above drawing, I created the layers as follows.

Api Layer: It accepts incoming requests and throws events for the application layer for commands and queries.

Application Layer: Validations, a layer without domain rules where specific things to be done in the application (mobile, web) are realized. We now use CQRS on this part. We will operate on the database with commands and queries. According to CQRS, the databases for Commands and Queries should be separated, but I went with a single database to make it simple.

Application Contracts Layer: Includes interfaces for the layer that wants to communicate.

Domain Layer: The part where we manage the domain rules, which is the main philosophy of DDD, and throw events for the changes made.

Persistence Layer: Includes infrastructure sides. I used it for database abstraction.

Persistence EFCore Layer(optional): The layer that contains the specific changes I made about the infrastructure. I made it for ORM.

An Example: Creating User Lifecycle

I used mediatR for events in all layers. If desired, message broker or alternatives can be used according to the needs.

  1. A new request comes to the controller to create the user by the client.
Api Layer

2. This incoming request is met on the Application layer and Application rules are now being processed (not Domain rules). Here, we want to add a new record to the database without having a rule.

Application Layer Command Handler
Application Layer Service

3. Transaction completed successfully. But just a second. According to Event Sourcing, changes in the domain may also require events from other layers. For this reason, we will throw events in the domain layer. Finally, We add the changes we made in the domain layer to a list as an event.

User entity

4. Not finished yet. We made changes related to the domain, but we haven’t thrown the events yet. The choice here is entirely up to you. If you want, you can throw events at the same time for changes in the domain. I will throw the changes made in the domain after the operation has been successful in the database.

Abstracted layer for repository
A mediatR extension for domain events
Console log for domain events

5. We have now throw domain events. According to our example here, when a user is created, we can send her/him a welcome email.

Application Layer — Domain Event Handler

As in the example above, we have done both CQRS and Event Sourcing only according to the desire to create a user.

I write when I learn, I learn as I write. I may have made mistakes in many places because I am just a human. I would be glad if you correct it when you see any mistakes.

You can access the source code from here. Thank you for your interest. See you in the next post :)

Follow me;

--

--

--

Trendyol Tech Team

Recommended from Medium

Building Pairs Trading Strategy with PHI 1 | PHI 1 Blog

Basic Nested Forms…Made Basic

We love our work! PromoTeam results for the 5 month.

Building a cargo ship — Containerized apps + nginx-proxy + letsencrypt

Pandas 102: Mapping & Descriptive Stats

AUDIT: Service Agreement Signed With CERTIK.IO

The story of one team’s evolution with Scrum

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Furkan Bozdag

Furkan Bozdag

I don’t know what’s happening here? | sr. software engineer

More from Medium

SOLID Design Principles: The Dependency Inversion Principle

Why Domain-Driven Design & Event Sourcing and its Benefits

Single UI solution for CAP library dashboards in microservice architecture

Loosely Coupled Environment for Microservices