CQRS: well known techniques facelift.
by Milan Kratochvíl, Senior modelling and architecture consultant, Kiseldalen.com, Sweden.
Quite many expert notes and articles here imply Command Query Responsibility Segregation (CQRS) as an aside, while addressing a multitude of other important data-architecture issues. In this note, the relationship is reversed, focusing explicitly on CQRS.
CQRS extends Command–Query Separation (CQS) to handling commands (write requests) and queries (read requests) by separate Query objects and Command objects, whereas CQS made them separate operations within one interface.
CQRS is an architectural sibling, although not a synonym, of separated read and write data stores or subsystems. If you’ve been involved in data warehousing and data marts in your past, you probably argue, rightly, that the separation is nothing new. It has been tested and leveraged for decades. In fact, the more analytics and management data, the more sense CQRS makes; its typical niche are not simple “get” operations where plain CQS within one interface would do, for example “get_updated_balance” when producing an updated customer receipt (at the end of a withdrawal transaction on an account).
On the benefit side of CQRS, we find many favorites of data architects, as well as of other roles. CQRS results in more components, but they become simpler and less dependent on each other. This makes CQRS systems more resilient to change. At the same time, they facilitate performance optimisation especially on the “Q” side (side-effect free read operations) which can be partitioned into several data stores, each optimised for different categories of queries. This makes CQRS quite special, compared to a multitude of other patterns and tactics where modifiability and performance (or availability) are a difficult architectural tradeoff.
In an agile, iterative transition to a Software Product Line architecture, the underlying pre-programmed variability, i.e. the mechanisms for “reshaping without reprogramming”, starts typically on the read/“Q” side, which often becomes only 2-tier (interaction, data) plus security. Parameterised multidimensional expressions (in MDX, mdXML, etc.) in the data tier match smoothly a parameterised interaction tier (parameterized Use Cases, user stories, dialogs, GUI layouts). For example, natural-language localisation (often including currency symbol, date formatting, decimal separator etc.) follows a similar “parameterised” rationale, using config files, start-up time parameters, language files for captions, etc. This is simpler than on the write/“C” side where even a simple localisation has to tackle rules (internal, external regulatory, or both) that tend to vary from country to country.
CQRS makes the transition from CRUD to semantic (“rich”) operations and task-based GUI more natural. On the “C” side, they speed up the transfer of business logic (from Post-Its, texts, and end users’ minds) into the system, and they can also enable security improvements.
The “S” in CQRS (segregation) paves the road to non-procedural programming paradigms, recently dealt with in the article by professor Reichenbach here on big data query languages (January 20th). These make things simpler for the programmer (although rarely for the vendor of compilers, optimisers, or test tools), especially in a multicore and multithread environment where non-procedural approaches and automation are less prone to human error than procedural ones.
Summing up, CQRS is a widely used practice, rather than a law of nature. Its plus points cluster around modifiability: low coupling, high cohesion, scalability, variability (deferred binding time), notably without compromising performance.