CQRS: Is it okay to return the result to the ICommandExecutor.Execute () method?

I have some thoughts on team design at CQRS. I want to hear your opinion on my thoughts. Thank you in advance!:)

CQRS has Teams and Team Executors. Sometimes we want the command executors to return some result after execution is complete. One possible solution is (C #):

public interface ICommandExecutor<TCommand>
{
    void Execute(TCommand cmd);
}

public interface ICommandExecutor<TCommand, TResult>
{
    TResult Execute(TCommand cmd);
}

      

Good. We use two command execution interfaces. Now let's see the client code:

var cmd = new MyCommand();
commandBus.Execute(cmd);  // execute no result
commandBus.Execute<MyResult>(cmd); // execute result

      

Yes, now we can return the exeuctor result. But the programmer can be confusing when writing the above code: can this command be executed or not? To get the answer, the programmer needs to examine the source code of the framework to see if there is a MyCommandExecutor or a MyCommandExecutor. This is bad! Very confusing!

So, in my opinion we should DELETE ICommandExecutor<TCommand, TResult>

. That is, I believe that command executors should always return void. The design is ICommandExecutor<TCommand, TResult>

bad!

If we need to see what has changed after executing the command. We have to make a new query to the database after calling commandBus.Execute (cmd).

What do you think about this?

+3


source to share


3 answers


No need to add a second interface. I'm not sure if the return values ​​are appropriate for commands in CQRS, but I sometimes do it with my commands (but I don't follow CQRS). But instead of having a second interface, add the output property to the command.

public class CreateCustomerCommand
{
    // customer properties here

    // output property
    public Guid CustomerId { get; internal set; }
}

      

But keep in mind that commands with output properties can never run asynchronously.



If you really want to have an executor interface with a return value (which I don't recommend), check out this article , This article is about implementing queries in a SOLID way, but it addresses the problem of defining a type-safe interface that allows you to return data.

BTW, in the previous example, the command can easily be made asynchronous if the property CustomerId

has an input property. You allow the client to supply a new random Guid. This way, the client already has an available identifier and does not have to wait for the results to be available.

+7


source


In CQRS, the command side should not return anything as it violates the anatomy of the drawing. Your own thoughts on this are correct.

However, Greg Young often mentions the result of the Ack / Nack command operation (or is used anyway). Most messaging systems support such responses. The downside to the expected result is that you cannot be completely asynchronous. I never felt the need for Ack / Nack, as one of the foundations of CQRS is that the team must always be successful, so there is no point in returning Ack / Nack.



Ask yourself what you need to return. What operation should return information that you don't already have on the send / command side? Take the time to understand this before letting your teams become queries.

+6


source


Strictly speaking, if you use the patter command, it shouldn't return anything, but it should always be void

. You should use another command (query) to get any data

http://www.dofactory.com/Patterns/PatternCommand.aspx#_self1

+4


source







All Articles