Quick Start: A fictionalized CQRS design example — why / where / how

Ali Süleyman TOPUZ
.Net Programming
Published in
4 min readAug 11, 2020
Aren’t those little windows like queries?

In this article, I will share an application example, advantages and disadvantages about CQRS (Command Query Responsibility Segregation) architectural pattern. This is a design template and an efficient approach that can be used in command-query based applications.

We have all experienced the importance of logical coding architectures that are selected / shaped according to certain rules and application needs while developing applications. It is obvious that the applications developed with approaches such as “only SOLID principles are enough”, “It is enough to not repeat code”, without planning on paper, are obviously inefficient in terms of time and budget as the requirements become more complex. Not to mention the lost motivation of the developer towards the application.

On the other hand; It is equally important to determine and implement the most efficient approach according to the application requirements. In today’s conditions, there is no other choice but to make the right decisions at the beginning, in order to see a vibrant output and production result as soon as possible, remembering that the main thing is to achieve the most efficient production with optimum effort. Otherwise, as long as the application is developed, technical deficits caused by wrong decisions will not leave us alone.

The CQRS pattern is an approach that is shaped according to the area of use of the business model, in a way, at the idea level, where you can pluralize the model based on the business requirement within command and query perspectives. In line with the use of these models, other resources (storages etc.) can also be shaped as distributed and this offers a wide scalability options.

CQRS — Read Side (Query) Write Side (Command)

For example, if the action you want to do is read, you can use a model, or, if it’s an update, you can use another model, and this gives flexibility in terms of business rules and requirements. The important thing is; this flexibility should not turn into an unnecessary complexity. To understand this, it is useful to understand this pattern well at the name level. This pattern is more concerned with separating the responsibility rather than being able to use different models. Command and Query. In other words, the separation of the model in the reading process and the model in the update process is a result of this separation of responsibilities.

Advantages

Independent scaling: CQRS allows the read and write workloads to scale independently.

Optimized data schemas/models: The read side can use a schema that is optimized for queries, while the write side uses a schema that is optimized for updates.

Security: It’s easier to ensure that only the right domain entities are performing writes on the data.

Separation of concerns: Segregating the command and query sides can result in models that are more maintainable and flexible.

Simpler queries: Simple and smaller queries. The application can avoid complex queries.

Disadvantages

The CQRS is not particularly suitable for small applications that do not require a high degree of scalability and do not have complex domain logic, the CQRS is not suitable or is only suitable to a very limited extent. Besides, having different models for command and query makes it difficult tokeep the models consistent with each other. On the other hand, if scability is not required for the system, instead of simplifying, CQRS introduces complexity in the system.

Implementation Considerations

Complexity: The basic idea of CQRS is simple. Just separate responsibility as Command and Query. But it can lead to a more complex application design, especially if they include the Event Sourcing, Synchronization, Messaging patterns.

Messaging: Despite CQRS does not require messaging, it’s common to use messaging to process commands and publish update events. Please look at Eventual Consistency below.

Eventual consistency: If you separate the command and query storages, the read has to be considered to be updated for each command action to avoid stale data.

Coding

Command: Let’s assume that we need a functionality as Insert card to ATM.

  1. ICommand and ICommandHander
  2. InsertCardCommand
  3. InsertCardCommandHandler
  4. Registration

ICommand and CommandHandler implementation:

InsertCardCommand:

InsertCardCommandHandler:

Registration:

Query: Let’s assume that we need a functionality as querying Balance on ATM machine.

  1. IQuery and IQueryHandler
  2. BalanceQuery
  3. BalanceQueryHandler
  4. Registration

IQuery and IQueryHandler:

BalanceQuery:

BalanceQueryHandler:

Registration:

How we use (dispatch) the Query and the Command:

We should have Command and Query dispatcher for being able to use our Command and Query objects.

By this dispatcher, we can dispatch command or query to related handler.

For more information, please pull and look at the soure code in detail.

Source code: https://github.com/alisuleymantopuz/atmps

References:

Martin Fowler’s blog- https://martinfowler.com/

Microsoft Docs: https://docs.microsoft.com/en-us/azure/architecture

--

--

Ali Süleyman TOPUZ
.Net Programming

Software Engineering and Development Professional. Writes about software development & tech. 📍🇹🇷