CQRs Architecture by Fowler

This article is an answer to the benefits and drawbacks of CQRS under the light of the DDD practices.

The original article written by Hristiyan Pehlivanov can be found there.

Despite the provoking title, the article is well-balanced and you may find valuable insights there.

TL;DR : CQRS is a not a silver bullet.

CQRS is not a silver bullet

Well it’s obvious and despite what may say any Software Programming theorist, there is no perfect design pattern, architecture model that fits for all.

DDD, Onion Architecture, Clean architecture, both of these concepts relies on some good sense and one or two successful implementations in a given context.

CQRS has the same issue. Plus there are some misconceptions about it that confuses the practionners.

CQRS maturity level

As I understand CQRS and practice it, I usually distinguish four levels of maturity

  1. CQS : Command and Query Segregation
  2. Read and Write model
  3. Read and Write Datastores
  4. sourcing

Level 1 : CQS : Command and Query segregation

This part is easy to understand. In your code, you should distinguish read and write operations and avoid as much as possible mixed ones.Your write operations should follow the Command design pattern.

I also recommend to implement a Command Bus interface that will work for the next maturity levels.

In Java, you may add the following tricks :

  • read operations are read-only transactions
  • if you aren’t following DDD, read operations are performed directly in your controller. You don’t create services. You convert directly your queries into a JSON view.
  • write operations may use aggregates like offered by an ORM
Next to read  Developing with S3 and Java : useful links

Level 2 : Read and Write model

The second level of maturity requires to have two different models ( and possibly repositories ) : the read model and the write model.

The architecture keeps a single storage.

The read model is optimized to returns directly the data required by the API. Example you are using Spring JDBC or MyBatis for the read model and Hibernate for the write model.

The write model is created by following the actions required by the business. Each command is a business use-case or operation.

The BDD or approach will help you to the necessary commands.

The of the commands may trigger events. The event bus and the event are stored into the memory of the server. Nothing complicated there.

Level 3 : Read and Write Datastores

The third level of maturity takes the principles implemented in the previous stages and add another constraint : we have two separate data storages.

The implementation complexity increases and there is a major concept to be implemented :

  • model synchronization : synchronously or asynchronously, the events produced by the commands must trigger a refresh of the read database

Moreover your event system has to be externalized for example as a message bus (Kafka, Rabbitmq). It will help you to safely keep your messages being processed.

Level 4 / Optional Event-sourcing

Well it is not a maturity level but another practice that fits with CQRS. Your commands are using the writing model to modify the write storage. Instead your commands produce application events. These events stored into a log and can be used to replay the history of a database and eventually restore it.

Next to read  Codacy : an easy-to use code quality review solution

More details can be found there.

The usage of Event Sourcing, is totally optional to CQRS.

Conclusion

In my opinion, the benefits of CQRS are :

  • Testability : Command are objects and not parameters. This way the command handlers are easy to and to mock. The object validation is also possible on the commands using Hibernate validation.
  • Functionality/Maintainability : a CQS architecture is easy to read since everything is business oriented. No mega service or Godclass DDD repositories.
  • Productivity : CQS offers a big benefit that we remove almost all DTO/Value object code and respect DRY principle. No need to have two abstractions layers between your DAO, your value object and the JSON view you are returning. You should use a DAL optimized for read access and JSON conversion
  • Fun : almost everything has to be build from scratch. Ok it exists some (paid) frameworks but I wouldn’t use them

The drawbacks of CQRS are :

  • more code : yes instead of a basic function you have to write a command object, a command handler ( your tests), validation etc. But the code is easy to read and self-explanatory
  • asynchronism issues : since your write data storage and read data storage are separated, the data synchronization may be delayed and causing UI issues for your users.
  • more layers : command, command bus, event, event handlers are new concepts. Building a service or a DDD repository looks easier ( at the beginning)
  • technology abstraction : DDD modeling and CQRS are not quite compatible, more thought has to be provided on it and a compromise to be found.

Other resources

Next to read  Hexo plugin : hexo-generator-slideshare


 

 

 

By Sylvain Leroy

Senior Software Quality Manager and Solution Architect in Switzerland, I have previously created my own company, Tocea, in Software Quality Assurance. Now I am offering my knowledges and services in a small IT Consulting company : Byoskill and a website www.byoskill.com Currently living in Lausanne (CH)

Do NOT follow this link or you will be banned from the site!