4
votes

I was recently reading this article here: https://cuttingedge.it/blogs/steven/pivot/entry.php?id=100. It appears to talk about using commands (http://www.dofactory.com/net/command-design-pattern) instead of application services.

Please see the code below:

public sealed class ShipmentController
{
    private readonly ICommandDispatcher dispatcher;

    public void ShipOrder(ShipOrder cmd) => dispatcher.Dispatch(cmd);
}

sealed class CommandDispatcher : ICommandDispatcher
{
    private readonly Container container;

    public void Dispatch(dynamic cmd) => GetHandler(cmd.GetType()).Handle(cmd);

    private dynamic GetHandler(Type type) =>
        container.GetInstance(typeof(ICommandHandler<>).MakeGenericType(type));
}

which replaces code like this: http://www.zankavtaskin.com/2013/11/applied-domain-driven-design-ddd-part-6.html

I have three questions:

1) Is this saying that you should have one command per command request in the Application Service Layer? Wouldn't this result in class explosion e.g. if you have 100 commands?

2) What do you do with CQRS queries? Do you create regular application services for these?

3) What do you do with scenarios where you extract from the database (say an order); perform a command on the Order e.g. CalculateTax and then persist to the database? I assume the flow would be (is this right):

MVC 
Application Service (to extract order from database)
Command (Application Service calls CalculateTaxCommand)
1
1) No. Http request and command request are two completely different things. And yes, for command request you would have at least 3 classes: command, handler and response. 2) No. You have the same principle as commands, except queries are idempotent (they can't modify anything). This means you might need to encapsulate your db access so that nobody can write a query that modifies something 3) You would: a) send a query b) execute a command to calculatetax c) execute a command to update the dbzaitsman
@zaitsman, can you confirm that each query/command is encapsulated in its own class?w0051977
This is a theory :) So yes, it should be as that is the only thing that guarantees the separation level. The whole point of DDD and CQRS is that it allows to decompose your application down to a few lines of isolated code, which is a lot easier to refactor in a team of 20+ devs and across thousands of operations. Normally all commands, queries and handlers inherit some interface or a base class. Also check out MediatR (github.com/jbogard/MediatR)zaitsman
Is this a c# question only?Constantin Galbenu
@zaitsman Idempotent doesn't mean they can't modify anything, it means that a function can be executed multiple times but the result won't change after the first execution.DavidG

1 Answers

9
votes

It appears to talk about using commands instead of application services.

No, it does not talk about the command design pattern. There is a very clear, and crucial distinction between the Command design pattern, and the CQRS-like patterns that are described on my blog and elsewhere.

The 'command' in the Command design pattern combines both data and behavior within the same class. With CQRS, on the other hand, the command is simply a message, a data container, with no behavior. Behavior is moved to a 'handler' class. The handler is identical to your old 'application services' with the distinction that a handler has a very narrowly defined scope. This separation is the driver that enables the maintainability and flexibility of this design.

  1. Is this saying that you should have one command per command request in the Application Service Layer? Wouldn't this result in class explosion e.g. if you have 100 commands?

It is a very common misconception with developers to think there is a direct reverse relationship between the number of types in a system and it maintainability; an increase in classes would means a decrease of maintainability.

The SOLID design patterns, however, favor small and focused classes over big classes, because making classes smaller, can actually increase the maintainability of a system tremendously.q

This is exactly what's going on here. This design should be viewed from the point of SOLID. My experience that, within the systems I refactored to that model, we saw a massive increase in maintainability of an order of a magnitude, even though the amount of classes could as well increase with an order of a magnitude.

TIP: Do not worry about the number of classes in your system. Just worry about maintainability.

This doesn't mean that project structure is irrelevant, though—it certainly is relevant. You should find a good project structure for your commands, their handlers, and their decorators. In the comments of this blog post there are some ideas of how to structure your project.

  1. What do you do with CQRS queries? Do you create regular application services for these?

You do exactly the same to queries as you do to commands. Each query should have its own query message and a handler, and optionally a result message class. This blog post describes how to design you queries.

  1. What do you do with scenarios where you extract from the database (say an order); perform a command on the Order e.g. CalculateTax and then persist to the database? I assume the flow would be (is this right):

This is an atomic operation and should all be part of the command. When the command is executed, the order is loaded from the database, based on its ID captured in the command. The tax is calculated and the order is persisted as part of that (business) transaction.