CQRS advanced course

disclamer: the article dwells on some special aspects of the CQRS implementation within the Incoding Framework, which allow solving the tasks in a more flexible and universal way. For a deeper insight one has to know the basic CQRS terms.

In the center

Dispatcher – this is a key element in the CQRS functioning, which renders the Command and Query within one transaction, implementing the pattern Unit Of Work, and also allows to take advantage of AOP  without extra plug-ins or third-party libraries. Let us consider in sequence each point.

1.Unit Of Work – if considering the CommandBase implementation, one may see that the main code is contained in the overloaded Execute method which can be applied to without Dispatcher being involved, but in this case connection to base won’t be open and transaction won’t be created.

  • строка 1 – Command implementation without Dispatcher
  • строка 2 – Command implementation with  Dispatcher

Note: if implementing the Unit Of Work in each Command or Query the code duplication in the Execute method will be very high.

2. AOP – aspect-oriented programmingin C# is mainly implemented within Reflection and Attributes but for this purpose extra methods marking is necessary with the attributes, as well as implementing the system of attributes reading during the code execution. There are tools, such as PostSharp which allow implementing it at a higher level, but they are paid, and also require additional abstractions. All Message which are executed through Dispatcher at certain stages of execution become publish of events which signal about this or that status.

  • OnBeforeExecuteEvent – the event happens before Message execution. Application scenarios: auditing, profilings, restrictions check
  • OnAfterExecuteEvent – the event happens after Message successful execution. Application scenarios: auditing, profilings, restrictions check
  • OnAfterErrorExecuteEvent –  the event happens if in case of Message execution Exception was displayed. Application scenarios: audit, error handling, annunciation
  • OnCompleteExecuteEvent – an event happens after Message execution even if there was an error, that is this event groups the behavior of After Execute and After Error Execute. Application scenarios is the same, as for OnAfterExecuteEvent and OnCompleteExecuteEvent

Sample

  • line 12 – получив доступ к текущему выполняемому  Message, пробуем привести его к интерфейсу IRoleMessage
  • line 13 – если roleMessage null, то ограничений нет
  • строка 16 – получаем User на основе имеющегося UserId
  • строка 17 – получаем через рефлексию instance атрибута Role
  • строка 18 – проверяем права
  • строка 19 – “выбрасываем” exception если проверка прав не прошла

 

Extra decomposition

CQRS helps to divide responsibility between the classes thus covering a set of tasks, but there are also scenarios which are difficult to support or test even after division into Command and Query because of large volume of business logic and conditions. To solve this problem in Incoding Framework there are two methods:

1.Composite – allows to perform Nth number of Command or Query within a songle transaction, thus enabling the decomposition of the complex scenario into smaller bits.

Let us consider the sample basing on the example.

    Assumption: step-by-step announcement registration

  • Step 1 – filling in the spaces
  • Step 2 – enabling additional options
  • Step 3 – payment

Restriction: all three steps must be performed within one transaction.

Problem: If the code necessary for execution of the scenario is written in one Command, the solutrion will be complicated and difficult to support, therefore Composite or can be used for these purposes.

note: push method has got a number of overloads which allow to perform one Command  or packet.

  • line 5 – refer to step 1
  • line 6 – refer to step 2
  • line 7 – refer to step 3
  • line 8 – on filling in the  Composite every command is executed in the sequence of listing when it meets all the requirements of the task and all the Commands  will be executed within a single transaction, thus providing the rollback of all actions if step 2 or step 3 “will throw out” the exception.

Apart from grouping Command in one packet Composite allows to manipulate results of execution. We will complicate the task and we will set a condition that Step1 after execution transferred the Id of a new element to Step 2 and 3.

  •  line 5 – after successful completion of Step1, action OnAfter which will put down Result from Step1 in the field of the Id for Step 2 and 3 will be executed.

2.Event Broker – is the broker of events which is primarily used for aggregation of the same actions from different Command иQuery, it may also be applied as responsibility division in Message.

Let us consider this method basing on the example.

       Assumption:sending email after successful user registration.

    Problem: the matter is that the main target of Command in this context is to preserve a new user, whereas all the other actions are considered as “after assumption”. “After assumption ” can be complex in implementation and will add “noise” to the main implementation, for example sending email by pattern or operation with IMAP which will eventually lead to complication of the code and support and testing problems.

The listing presents a code Command, where in the last line the publication of an event is made, which is responsible for sending email thus allowing to share responsibility..

Which is better ?

 Event Broker

+ variables, which exist within the Execute method, are available
+ can be executed outside the Message context
+ can be used repeatedly in different Message
– does not support transaction by itself

Composite

+ can solve complicated atomic tasks
+ can be used repeatedly outside the Composite context (for example payment for advertisement, which can be called for not only at the moment of registration, but also in other situations).
 – can’t be used in the framework of other messages.

conclusion: Composite and Event Broker can solve the tasks which are similar at first glance, but they have differences, basing on which one may analyze the task set and having decided in which context the execution is necessary, it is easy to choose the convenient method for Your scenario.

What to do if…

A lot of developers faced a problem when apart from operating with the base, the project implementation also requires being connected to an already existing customer base or the system requirement, so that there was a possibility of change of connection string in runtime.

1. 1. Legacy system – 1. this occurs most often when an oldewr project written in WinForm has no API. In such a case the best solution will be to write the wrapper atop “old ″ bases. Within Incoding Framework there are means which allow you to avoid creating additional infrastructure for operating with different configurations and to develop Command and Query disregarding this detail.

Sample

листинг кода демонстрирует регистрацию двух разных конфигураций баз данных, которые имеют разную схему и могу также иметь разные провайдеры ( mssql,mysql, oracle )

Для того, чтобы выполнить Query или Command в рамках определенной конфигурации, надо указать имя Instance в параметрах Dispatcher.Push или Dispatcher.Query

2.2. “Hot” connection string change – 2. if an application receives a string of connection not in case of start, but in the course of operation, for example after login third-party service gives out the address on the current session, it is necessary to have an opportunity to change the predetermined path.

 

Conclusion: CQRS implementation within the Incoding Framework takes into consideration a multiplicity of scenarios which a .net developer might come across, and has a set of tools to solve the tasks and improve the code (refactor)

 

Vlad Kopachinsky

I am a Senior developer at Incoding Software in Russian Federation. I created the Incoding Framework for rapid development

More Posts - Website - Twitter - Facebook - LinkedIn

Leave a Reply