CQRS: хорошо ли возвращать результат в методе ICommandExecutor.Execute ()? - PullRequest
3 голосов
/ 15 марта 2012

У меня есть некоторые мысли по поводу дизайна командирской части в CQRS.Я хочу услышать ваше мнение о моих мыслях.Заранее спасибо!:)

В CQRS есть команды и исполнители команд.Иногда мы хотим, чтобы исполнители команд возвращали некоторый результат после завершения выполнения.Одним из возможных решений является (C #):

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

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

Хорошо до сих пор.Мы используем два интерфейса для выполнения команд.Теперь давайте посмотрим код клиента:

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

Да, мы можем позволить exeuctor возвращать результат сейчас.Но программист может сбить с толку при написании приведенного выше кода: может ли эта команда выполнить результат или нет ??Чтобы получить ответ, программист должен изучить исходный код фреймворка, чтобы узнать, есть ли MyCommandExecutor или MyCommandExecutor.Это плохо!Очень запутанно!

Так что, на мой взгляд, мы должны DELETE ICommandExecutor<TCommand, TResult>.То есть Я думаю, что исполнители команд всегда должны возвращать void.Дизайн ICommandExecutor<TCommand, TResult> плохой!

Если нам нужно посмотреть, что изменилось после выполнения команды.Мы должны сделать новый запрос к базе данных после вызова commandBus.Execute (cmd).

Что вы думаете об этом?

Ответы [ 3 ]

7 голосов
/ 15 марта 2012

Не следует добавлять второй интерфейс.Я не уверен, подходит ли возвращаемое значение для команд в CQRS, но я иногда делаю это с моими командами (но я не следую CQRS).Но вместо того, чтобы иметь второй интерфейс, добавьте свойство вывода в команду.

public class CreateCustomerCommand
{
    // customer properties here

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

Но имейте в виду, что команды со свойствами вывода никогда не смогут выполняться асинхронно.

Если выдействительно хотите иметь интерфейс executor с возвращаемым значением (что я бы не советовал), посмотрите эту статью .Эта статья посвящена реализации запросов СОЛИДНЫМ способом, но она касается проблемы определения безопасного типа интерфейса, который позволяет вам возвращать данные.

Кстати, в предыдущем примере команду легко выполнитьасинхронный, делая свойство CustomerId свойством ввода.Вы позволяете клиенту предоставить новый случайный Guid.Таким образом, у клиента уже есть идентификатор, и ему не нужно ждать, пока результаты станут доступны.

6 голосов
/ 15 марта 2012

В CQRS командная сторона не должна ничего возвращать, поскольку это нарушает анатомию шаблона. Ваши собственные мысли по этому поводу верны.

Тем не менее, Грег Янг часто упоминает результат Ack / Nack командной операции (или используется в любом случае). Большинство систем обмена сообщениями поддерживают такие ответы. Недостаток ожидания результата в том, что вы не можете быть полностью асинхронным. Я никогда не чувствовал потребности в Ack / Nack, так как одна из основ CQRS заключается в том, что команда всегда должна быть успешной, поэтому нет смысла возвращать Ack / Nack.

Спросите себя, что вам нужно вернуть. Какая операция нужна для возврата информации, которой у вас еще нет на отправляющей / командной стороне? Потратьте время, чтобы понять это, прежде чем ваши команды станут запросами.

4 голосов
/ 15 марта 2012

Строго говоря, если вы используете команду patter, она не должна ничего возвращать, но всегда должна быть void.Вы должны использовать другую команду (запрос), чтобы получить любые данные

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

...