CQRS – example of implementation

What is CQRS?

Let’s start with what is CQS (Command Query Separation) because CQRS (Command Query Responsibility Separation) are derived from it.

CQS (Command Query Separation)

This approach says that each method should be divided into two types:

  • Command -the method performs operations, but does not return anything.
  • Query –the method return something but do not perform any operations on them.

In brief, you should not have methods such as “UpdatePriceListAndGetProduct“.

“The question should not change the answer.”

CQRS (Command Query Responsibility Separation)

Greg Young and Udi Dahan suggested why not to introduce this division into entire objects instead of individual methods and so the CQRS pattern was created.

The difference between CQS and CQRS is that in CQS we think about methods and in CQRS we think about objects

So the system should be subdivided into the command and query objects.

I will show you how to easily implement the CQRS pattern.

Command

First thing is that we need to create command marker* interface.

*this approach will give us so much that we can easily find our commend in the system, eg. through the reflection system.

Commandit is an object that represents the intentions. For example – CreateUser.

We have commend, now we need a class that invoke command and it will be CommandHandler.

Command Handler – is responsible for the initial validation of the commend. Then it performs some operations on Domain Object. The last step is to save changes to the database (write) via repository.

Each command has only one handler. This is a generic version of the handlers implementation so we know what type of command it supports.

To handle commends from system, we need a Command Bus.

CommandBus – in the simplest version – looks for the appropriate Command Handler for the given command and calls the Handle method on it.

Example implementation of such a bus:

In the first place, I downloads all handlers registered by Autofac* to a given commend. Then I check the assumption that each commend can have only one handler and calls operation.

*code for registering commend handlers using autofac on the github repository.

Now we can create a Command – CreateUserCommand

With command handler – CreateUserCommandHandler:

Now, we have everything what we need. It remains only to check if it works via console applications to see how easy it is now. 🙂

First configure IoC and then call the Command Bus with the appropriate commend.

After starting the application we get the result:

cqrs-command

Now we can simply add new commands to the system and we can easily handle them.

Event

The command concept can be extended with events. Events can serve many purposes (eg. Event Sourcing), including informing the system that something has happened. Implementation is analogous to commend:

The difference in implementation is on the bus.

The reason is that events can have many handlers.

Now we can create a event – UserWasCreated.

To this event we can assign two event handlers for example UserWasValidetedEventHandler and UserWasCreatedEventHandler. Therefore, we want to inform the system at the UserWasCreatedEvent event that it was properly validated and created correctly.

Exaggerated example, but I hope you know what I mean. 😉

Now we can inject event bus to our command handlers.

And we have result as:

cqrs-event

The whole code is on github.

 

3 Comments on “CQRS – example of implementation”

  1. I always was wondering what CQRS means and after reading your post I found out many interesting and helpful things. Thanks!

  2. Hi,
    I was also digging a little bit in CQRS and have one comment about your EventBus implementation. It is tightly coupled with your DI container. I think I know why you did it this way.

    When you pass handlers collection via EventBus constructor as IEnumerable, you won’t be allowed to compile the code because of missing method in EventHandler unless method in IEventHandler interface and its implementation will be :

    public void Handle(IEvent @event) { }

    My attempt of EventBus implementation is also not perfect because of the reason I’ve mentioned and I don’t see a better solution than this.

Leave a Reply

Your email address will not be published. Required fields are marked *