Разделение запросов команд: команды должны возвращать void?

Если CQS не позволяет командам возвращать переменные состояния, как можно написать код для команд, которые могут быть неудачными? Допустим, вы не можете полагаться на исключения.

Кажется, что все, что запрос / ответ является нарушением CQS.

Таким образом, может показаться, что у вас есть набор методов "мама, может я", задающих статусы, которые были бы возвращены командой. Что происходит в многопоточном / мультикомпьютерном приложении?

Если у меня есть три клиента, которые хотят запросить увеличение объекта сервера на один (и объект имеет пределы 0-100). Все проверяют, чтобы увидеть, могут ли они, но один получает это - и два других не могут, потому что это просто достигло предела. Казалось бы, возвращенный статус решит проблему здесь.

2 ответа

Решение

Кажется, что все, что запрос / ответ является нарушением CQS.

В значительной степени да, отсюда и Command-Query-Separation. Как хорошо говорит Мартин Фаулер:

Основная идея состоит в том, что мы должны разделить методы объекта на две резко разделенные категории:

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

Команды: Изменить состояние системы, но не возвращать значение [мой акцент].

Запрос на увеличение объекта сервера на единицу - это команда, поэтому он не должен возвращать значение - обработка ответа на этот запрос означает, что вы одновременно выполняете действие команды и запроса, что нарушает фундаментальный принцип CQS.

Поэтому, если вы хотите узнать значение сервера, вы создаете отдельный запрос.

Если вам действительно нужен шаблон запрос-ответ, вам нужно иметь что-то вроде запутанного процесса обратного вызова для выдачи запросов на статус определенного запроса, или чистый CQS не подходит для этой части вашей системы - обратите внимание на слово чистый.


Многопоточность является основным недостатком CQS и может затруднить его выполнение. В Википедии есть базовый пример и обсуждение этого, а также ссылки на ту же статью Мартина Фаулера, где он предлагает, что можно сломать шаблон, чтобы что-то сделать, не сводя себя с ума:

[Бертран] Мейер [изобретатель CQS] любит использовать разделение команд и запросов абсолютно, но есть исключения. Popping стек является хорошим примером запроса, который изменяет состояние. Мейер правильно говорит, что вы можете избежать использования этого метода, но это полезная идиома. Поэтому я предпочитаю следовать этому принципу, когда смогу, но я готов нарушить его, чтобы получить популярность.


TL; DR - Я бы, наверное, просто посмотрел, как вернуть ответ, даже если он не правильный CQS.

Статья "Условия гонки не существуют" может помочь вам разобраться в проблеме с мышлением CQS/CQRS.

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

Подход заключается в том, чтобы сервер мог принять такое решение. Пусть все клиенты отправляют команды (некоторые из них будут успешными, а некоторые - неудачными). В конечном итоге клиенты получат согласованное представление о состоянии объекта сервера (где достигнут предел) и могут, наконец, прекратить отправку таких команд.

Это временное окно несогласованности приводит к неправильным решениям клиентов, но оно никогда не нарушает согласованность объекта (или модели домена) на стороне сервера, если команды обрабатываются надлежащим образом.

Другие вопросы по тегам