Почему принцип CQS требует, чтобы команда не возвращала никакого значения?
Принцип CQS гласит, что каждый метод должен быть либо командой, выполняющей действие, либо запросом, который возвращает данные вызывающей стороне, но не обоими. Для Query имеет смысл не делать ничего другого, потому что вы не ожидаете, что запрос изменит состояние. Но это выглядит безвредным, если команда возвращает какую-то дополнительную информацию. Вы можете использовать возвращаемое значение или игнорировать его. Почему принцип CQS требует, чтобы команда не возвращала никаких значений?
2 ответа
Но выглядит ли это безопасным, если команда возвращает какую-то дополнительную информацию?
Это часто так. Иногда это не так.
Люди могут начать путать запросы для команд или вызывать команды больше для информации, которую она возвращает, чем для ее эффекта (наряду с "умными" способами предотвращения того, чтобы этот эффект был реальным эффектом, который может быть хрупким).
Это может привести к пробелам в интерфейсе. Если единственным примером использования, который люди могут представить для конкретного запроса, является совместная работа с конкретной командой, может показаться бессмысленным добавлять чистую форму запроса (например, писать стек с Pop()
но нет Peek()
) который может ограничить гибкость компонента перед лицом будущих изменений.
В некотором смысле "выглядит безобидным" - это именно то, о чем вас предупреждает CQS, запрещая такие конструкции.
Это не означает, что вы все еще не можете решить, что конкретная комбинация команд-запросов не так полезна, чтобы ее стоить, но, взвесив все за и против такого решения, CQS всегда голосовой спор против этого.
Насколько я понимаю, одним из преимуществ CQS является то, насколько хорошо он работает в распределенных средах. Команды становятся их собственным изолированным модулем, который может быть немедленно выполнен, помещен в очередь для последующего выполнения, удаленным обработчиком событий и т. Д.
Если в интерфейсе commander указывается тип возвращаемого значения, то вы сильно влияете на силу шаблона CQS в его способности хорошо вписываться в распределенную модель.
Общий подход к решению этой проблемы ( см. Эту статью, например, Mark Seemann) заключается в создании уникального идентификатора, такого как guid, который уникален для события, выполняемого обработчиком команды. Затем это сохраняется, чтобы позволить идентифицировать данные на более позднем этапе.