Command & Query: Domain - Abstract Model
Tags: csharp, dotnet, oop, cqs
Published: 2020-08-18 06:15:01

*The story is part of the series about software architecture powered by command-query separation principle and aspect-oriented programming.*

***

## Abstract model in software — where, when and why?

Software problems which share common characteristics could be represented and associated with an abstract model, as a backbone for building generic, reusable solutions. It definitely is challenging to discover such [abstractions](https://en.wikipedia.org/wiki/Abstraction_(computer_science)) as a basis to build a usable software model — it requires a lot of effort, time and experience.

> *Abstraction is the amplification of the essential and the elimination of the irrelevant.* — Robert C. Martin, Agile Principles, Patterns, and Practices in C#

There are many fields in mathematics which are typically a good foundation to form an abstract model and finally build a generic solution for a particular or more general problem space. As an example, [graph theory](https://en.wikipedia.org/wiki/Graph_theory) is usually the basis for any valid *graph* representation, structure or model in software. Validity comes from the fact that theoretical definitions are embedded in abstract software models to guard a defined set of laws and provide a predictable interface to a consumer. Ultimately, a well-implemented model can serve as a generic solution for the same problems in the technical domains belonging to different business domains, such as data storage, social networking or communication networks.

Another, more advanced example is the influence of the [category theory](https://en.wikipedia.org/wiki/Category_theory) in functional programming. The theory itself focuses on identification and formalization of a *category* as a mathematical structure. A *category* is a graph which represents abstractions of other mathematical concepts and consists of *objects (nodes)* and their *morphisms (arrows)*. Even though the theoretical concept is quite broad and abstract, some functional programming languages, like [Haskell](https://en.wikibooks.org/wiki/Haskell/Category_theory), took advantage of such high-level abstractions, embedded their rules into core language features, and adopted terminology.

How will individual abstraction be truly accomplished in the context of programming language or particular framework is solely up to abstract models’ implementation characteristics. Since source code implementation is opinionated, it’s not surprising that theoretical model realization could vary a lot. It is influenced by many things — to give a brief idea, some are:

* Language paradigm — object-oriented, functional, event-driven …

* Language features — type system, generics, pattern matching …

* Framework features — concurrency, collections, garbage collection …

Determining the right implementation direction is quite challenging, but most importantly it’s rewarding since it’ll make a certain theoretical concept easy to apply and intuitive to use in every-day development.

To support the statement, a good example would be the *async/await* feature’s advancement in C#. [Asynchrony](https://en.wikipedia.org/wiki/Asynchrony_(computer_programming)), as a theoretical concept is a well known and hot topic in computer programming. However, every language or framework which supports *async* programming has own way of achieving it. In other words, each has a different way to implement and expose a meaningful and intuitive [API](https://en.wikipedia.org/wiki/Application_programming_interface) for the developer. In fact, C#/.NET supports 3 different [approaches](https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/).

It is known that asynchronous programming in .NET gained tremendous popularity once *async/await* was incorporated into C#, powered by the already existing [TPL](https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl). The reason is that *developers* eventually managed to form a software model based on the complex theoretical concept, with intuitive API — to use seamlessly within the context of language and framework.

Just remember how adventurous, hard to maintain and error-prone was asynchronous programming in C# without first-class compiler support, or even before, without first-class library support. Pursuing “asynchronous all the way” principle using earlier patterns (models) was much more complex and rare due to the lack of intuitive API.

It’s fair to mention that such a powerful generalization comes with the [cost](https://devblogs.microsoft.com/premier-developer/dissecting-the-async-methods-in-c/), and definitely, in [essentially](https://en.wikipedia.org/wiki/No_Silver_Bullet) complex domains it might be needed to “fallback” to the lower-level models which usually expose a certain degree of implementation details to expose necessary extensibility and configurability (e.g. `TaskFactory.StartNew`, `Task.Run` methods, `BeginX/EndX` pattern).

In conclusion, it was quite challenging to accomplish the current state of the first-class `async` support in .NET, since it was gradually developed over the years. At the same time, it was rewarding because of the widespread acceptance of the “new/old” *async* feature in the .NET realm. Besides, it became a *de facto* standard when dealing with asynchronous domains like HTTP servers.

## Command and Query — definition and model

Unlike the complexity of *async* domain space, CQS principle can be quite simply, yet powerfully modeled to provide a succinct, meaningful and intuitive API to work with.

To begin with the [definition](https://en.wikipedia.org/wiki/Command%E2%80%93query_separation), *Command* is a method that performs an action which **mutates** the domain’s state or has any kind of side-effect. In addition to that, it doesn’t return anything. On the other hand, *Query* is a method that performs an action which **queries** the domain’s state, doesn’t produce side-effects and returns data.

In both cases, there is a given set of rules (characteristics) which any method should adhere to, in order to be classified as one or the other. Moreover, there is a possibility to define the base abstract model which would guard the rules and embed characteristics into the source code, providing a necessary tool in hands to start taking the real advantage of a theoretical principle.

Fair to say, it’s not mandatory to build a software library which supports the concept to start applying it daily. In many cases, even following the rules would be beneficial.

But, having a reusable library built to support a certain principle gives additional room for improvements and a natural *upgrade* of the whole concept. As described in the [introductory](https://dev.to/darjanbogdan/command-query-domain-introduction-5eo2) article, *commands*, *queries*, and their *handlers* could be represented using only a few generic interfaces, but they can serve as a base ground for the architecture which effortlessly supports building the software components following SOLID principles and AOP paradigm.

Contrary to the mentioned abstract model which includes separate interface pairs for commands and queries, I find it more useful to unify them into a single pair. One interface to represent both (*command* and *query*), commonly called *request*, and another to represent the corresponding request handler.

![Umm...I have a question?...Meme](https://dev-to-uploads.s3.amazonaws.com/i/pl85i4fz9s9sth5tkstm.jpeg)

I’m not the greatest fan of the term either. Firstly, it deviates from the terminology coined by CQS principle. Secondly, due to the possible association with the completely different concepts in other domains (e.g. HTTP *request*). Nevertheless, I finally came to terms with it by simply moving the name distinction to the classes which implement before-mentioned interfaces (e.g. `CreateUserCommand : IRequest<TResult>` and `CreateUserCommandHandler : IRequestHandler<CreateUserCommand, TResult>`). After all, the whole abstraction is about commands, queries and their distinction — it’s worth to incorporate it somewhere.

So, the main goal is to have only two base interfaces on top of which other elements will be built, something like:

```csharp
interface IRequest<TResult> 
{
}

interface IRequestHandler<TRequest, TResult> 
    where TRequest : IRequest<TResult>
{
    Task<TResult> HandleAsync(TRequest request, CancellationToken ct);
}
```

One could immediately say that this abstract model violates, not only the terminology but also the rules (*command* has a return value!) defined by the abstract principle — and one would be right. However, I’m completely fine with that deviation, I’m seeing it as a reasonable theoretical model approximation caused by several (technical) limitations:

* `async/await` feature requires a method to return `Task/Task<T>` objects to be *awaitable* — *`async void Handle(){}` isn’t awaitable and exceptions can’t be [handled](https://jaylee.org/archive/2012/07/08/c-sharp-async-tips-and-tricks-part-2-async-void.html) in the same execution context.*

* `void` ([`System.Void`](https://docs.microsoft.com/en-us/dotnet/api/system.void?view=netcore-2.2)) can’t be used as a generic type parameter nor can be passed to a method — *`Task<void>` isn’t allowed.*

* [Variance](https://docs.microsoft.com/en-us/dotnet/standard/generics/covariance-and-contravariance) is supported by generic interface and generic delegate types only — *`class HandlerDecorator<in TRequest, out TResult>` isn’t valid.*

Despite some limitations, it’s still quite important to support asynchronous programming using widely adopted [TAP](https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap) pattern. That effectively means that interface methods must return `Task` and/or `Task<T>`.

Although, it seems that `Task HandleAsync(T command)` method would be appropriate to use for *commands* in asynchronous domains, it still involves violation of the principle rules. The method returns an instance of a `Task` type, which holds the information about the method’s execution (status, exception, identifier…) and doesn’t make it truly fire-and-forget anymore. Furthermore, it would hurt reusability because it’d still be needed to have two separate interfaces for command and query handlers.

To keep the possibility to represent a method which doesn’t “return” anything when having `Task<T>` as a return type, the special `Unit` structure must be implemented. That type indicates the absence of a specific value and often is a built-in type in functional languages, like [F#](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/unit-type).

Having that in place, it’s straightforward to implement any handler which represents command or query, using the same `IRequestHandler<TRequest, TResult>` interface:

The main benefit of the singular approach lies in the possibility to reuse the same (cross-cutting) components in both cases, considering that commands and queries could share the same characteristics. Like the way of validating or authorizing them before execution, or maybe the way of preserving audit trails, or rate-limiting, and so on.

Consider the following example, to implement a generic validation component for handlers, it is just necessary to build a decorator around a single `IRequestHandler<TRequest, TResult>` interface. Otherwise, it requires practically two of them, one for `ICommandHandler<TCommand>` and another for `IQueryHandler<TQuery, TResult>`.

Similarly, any other [aspect](https://en.wikipedia.org/wiki/Aspect_(computer_programming)) could be implemented (e.g. authorization, caching, …) as a single place in the code which handles the particular cross-cutting matter.

It’s not only possible to chain or compose multiple decorators to technically form a *request* pipeline, but also to conditionally apply them (generic type constraints, attributes), and automatically resolve them using *inversion of control* techniques.

## Result — definition and model

The last thing which I find important to address and (optionally) incorporate into a base model is exception handling or plainly error data propagation.

While it’s not mandatory to have it in place, I think it is important, especially in cases when structured error data (e.g. validation failure reasons) need to be communicated back to an API consumer.

Due to the fact that it’s not possible to have more than one return type in method signatures in C#, and because there is no first-class support for [discriminated unions](https://en.wikipedia.org/wiki/Tagged_union), the easiest and the most straightforward way is to use and extend built-in exception types. So, if there is a need to return some heterogeneous data from a method, one part can be simply propagated within (custom) exception types and just thrown from a method.

Still, structured error data should be treated as part of a domain, and as such should not be included inside a regular exception handling process. Besides, it’s not recommended to throw exceptions in non-exceptional scenarios (e.g. wrong input, token expiry), it makes error handling [vexing](https://blogs.msdn.microsoft.com/ericlippert/2008/09/10/vexing-exceptions/) since exceptions must be handled all the time.

It’s possible to avoid using custom `Exception` as a carrier of the domain-related data, by “borrowing” and implementing generic [Result](https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/results) structure, usually found in functional-first languages.

There are many different ways to implement structure alike in C#, as it is usually based on [Church-encoded](https://blog.ploeh.dk/2018/06/11/church-encoded-either/) *Either* abstraction, which is represented with a single interface method:

```csharp
interface IEither<TLeft, TRight>
{
    T Match<T>(Func<TLeft, T> left, Func<TRight, T> right);
}
```

For the sake of clarity and intuitiveness, instead of using highly abstract *Either* term, *Result* will be used. The name more closely describes the intent and is more fitting in every-day conversation.

If incorporated as-is into the request handler interface, three generic type parameters must be exposed (i.e. `IRequestHandler<TRequest, TResponse, TError>`) which adds additional complexity to the model. Also, the whole interface looks quite tedious to work with.

Most of the times, such a degree of model extensibility isn’t required at all and unification of all *errors* under common type is recommended — there is rarely a need to work with different *error* types. In that case `TError` generic type parameter can be omitted and suitable non-generic `Error` type used instead — making the generic `Result` class simpler and final version of handler interface cleaner:

```csharp
interface IRequestHandler<TRequest, TResponse> 
    where TRequest : IRequest<TResponse>
{    
    Task<Result<TResponse>> HandleAsync(
        TRequest request, 
        CancellationToken cancellationToken
    );
}
```

There are many *quality-of-life* details which could be added to the abstract model to furtherly enhance every-day usage, such as implicit conversion into `Result<T>`, set of various helper methods, more derived interfaces, etc.

All these details can be seen in the more comprehensive and complete model shown in *Pype* [repository](https://github.com/darjanbogdan/pype/tree/master/src/Pype). The repository will be gradually expanded with the components which will be covered throughout the article series.

Besides that, it’s worth mentioning [MediatR](https://github.com/jbogard/MediatR) and [Microbus](https://github.com/daniellittledev/Enexure.MicroBus) libraries which are modeling the same principle, both providing similar generic interfaces, but each has some specifics and additional features.

In the [next](https://dev.to/darjanbogdan/command-query-domain-mediator-kn7) chapter, request handler mediator and request pipeline composition will be covered!

***

*All the gists, examples or solutions will be done in C# using the latest .Net Core/Standard versions and hosted on [Github](https://github.com/darjanbogdan?utf8=%E2%9C%93&tab=repositories&q=pype&type=public&language=c%23).*