Building microservices through Event Driven Architecture part1 : application specific business rules

Today, architectures such as the onion or hexagonal, provide an important help for  testabillity and maintenance of code, independence with external frameworks. etc …
In this tutorial, I will show how to use the clean architecture, with methods and tools such as domain driven disign (DDD), Test (Behavior) Driven development (TDD), CQRS, Event Sourcing, Containerization, Oauth2 & Oidc to build a microservices architecture

For more information on clean architecture, I suggest you read this article by Robert C. Martin (Uncle Bob):

https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

Building microservices through Event Driven Architecture part1: application specific business rules

 unclebobs

https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

The Dependency Rule

The concentric circles represent different areas of software. In general, the further in you go, the higher level the software becomes. The outer circles are mechanisms. The inner circles are policies.

The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circle. In particular, the name of something declared in an outer circle must not be mentioned by the code in an inner circle. That includes, functions, classes. variables, or any other named software entity.

By the same token, data formats used in an outer circle should not be used by an inner circle, especially if those formats are generate by a framework in an outer circle. We don’t want anything in an outer circle to impact the inner circles.

Robert C. Martin (Uncle Bob)

COMMAND QUERY RESPONSABILITY SEGREGATION (CQRS)

CQRS Separate Commands From Queries.
Commands are operations that change the application state and return no data. Queries are operations that return data but do not change application state.
So, CQRS will be a very usefull concept, in the world of microservices by creating our application with two databases:

  1. a relational datadase, which is optimized for writing on the command side.
  2. a NoSQL database on the query side so as to read data as fast as possible.
    Since most applications read data much more often than they write data, in our approach of containerization, we can scale the command side on 2 pods and query side on 10 pods for example

DOMAIN DRIVEN DESIGN

CQRS fits in domain-driven design . DDD focuses on building rich domain models to tackle complex business logic.

Changing the data causes more bugs. So, having a clear perception of which part of the application change the data and which part of the application does not change the data will help with maintainability and debugging

EVENT SOURCING

Event sourcing  stores all changes to an object as a series of events in an event store
https://eventstore.org/

I will use this concept to build the following :

  •  Domain service implements domain-related concepts (entity, value object, aggregates, domain events), records a command in a relational database, and an event in the event store. all as a Unit for the purpose of data change.
  • a producer takes the event from the event store and sends it to the service bus ( eventstore is a append only table and use ubiquitous language)
  •  a consumer, subscriber to service bus, takes the event from the service bus and register it as pre-computed data to a nosql database
  • ReadModel service query the NOSQL database.
  • Everything that happens is saved in the event store

domainreadmodelarchi

I will build a system that helps speakers and attendees to register and follow events (conferences, talks, meetups, etc…)

My project is structured as follows :

  • EduSync.Speech.Domain

The innermost layer that holds the core domain. It contains our domain objects and business rules. and defines our External Interfaces.

Databases, network connections, filesystem, UI or special frameworks. are not allowed.

The core domain  have no knowledge of anything outside of themselve

Those dependencies, and their implementations are injected into our core domain using Interfaces.

  • EduSync.Speech.Application

This lawyer point to core domain and contain the application specific business rules.

Orchestrate the data flow and use the domain model

Have no dependency to a database, UI or special frameworks

  • EduSync.Speech.Presentation

This layer holds the Web, UI and Presenter concerns. In the context of our API, this means it accepts input in the form of http requests over the network (POST/PUT/PATCH/DELETE) and returns its output as content formatted as JSON.

  • EduSync.Speech.Infrastructure

This layer holds the Database and Gateway concerns. In here, we define data access layer, repositories, etc.…

It contains the physical implementation of the interfaces defined in our domain layer

Archit

TEST DRIVEN DEVELOPMENT

Implementing the “Speech Registration” use case

To make my tests green, the first thing I need to implement is RegisterSpeechUseCase

The overriding rule that makes this architecture work is The Dependency Rule. This rule says that source code dependencies can only point inwards. Nothing in an inner circle can know anything at all about something in an outer circl

Robert C. Martin (Uncle Bob)

  • So, let us define IRegisterSpeechUseCase interface its implementation RegisterSpeechUseCase. These types belongs to EduSync.Speech.Application

It takes an input object as a command,

RegisterSpeechCommandMessage

Then the interface

ICommand

Then RegisterSpeechUseCase will look like this:

RegisterSpeechUseCase

Let us defines dependencies such as IUnitOfWork and ISpeechRepository, these interfaces belongs to core domain and will be implemented on infrastrucrure.

ISpeechRepository need a Speech Entity, so let create it on core domain

IRepository

In this stage, evry thing compile succesfully but my tests failed

testfailed

 

As you can see, tests fails because I verify that CreateAsync and commit are called, so let us  call

SpeechRepository.CreateAsync   and IUnitOfWork.Commit  on RegisterSpeechUseCase class

RegisterSpeechUseCase_green

then create a mock of SpeechRepository.CreateAsync  and IUnitOfWork.Commit  on arrange section of my unit test

fffff

fffffffffffffffffffffffff

At this stage all tests are green but my code coverage is not enough :

for example if I comment out this  block my tests will succeed but my app will crash at runtime if command is null

succestesterror

 

Code coverage

Let us add a new test to fix it

RegisterSpeechUseCaseWithNullSpeechThrowsExceptionTest

Finally code coverage is 100% for LogCorner.EduSync.Speech.Application

RegisterSpeechUseCaseSuccessTest100

But what happend if I permute values ?

var title = command.Type;
var urlValue = command.Title;
var description = command.Url;
var type = command.Description;

permutatevalues

All test will succeed but my application will be in a invalid state because it will insert the title instead of the url,  ….

I can fix it using  moqSpeechRepository.Verify in test assertions but I’ll leave it like that and fix it when implementing my domain with the introduction of the values objects

Code coverage aplication

On next step, I will implement domain model

Source code is available here : RegisterSpeechUseCase

Best regards,

 

Gora LEYE

I'm a microsoft most valuable professional (MVP) .NET Architect and Technical Expert skills located in Paris (FRANCE). The purpose of this blog is mainly to post general .NET tips and tricks, www.masterconduite.com Gora LEYE

Support us

BMC logoBuy me a coffee