Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding the Command pattern in a DDD context

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)
like image 681
w0051977 Avatar asked Dec 23 '22 11:12

w0051977


1 Answers

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 its 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.

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.

In chapter 10 of my book I go into a lot more detail than I can provide here. I discuss how these patterns relate to SOLID and AOP and go through a step-by-step refactoring as an example, and demonstrate the power of decorators.

like image 98
Steven Avatar answered Jan 05 '23 15:01

Steven