Введение
Архитектура ИТ, разделяющая операции и чтение данных, является принципом императивного программирования. Он был разработан Бертраном Мейером в рамках его новаторской работы над языком программирования Эйфель. Принцип заключается в том, что каждый метод должен либо выполнять действие (команда), либо возвращать данные вызывающей стороне (запрос), но не делать и того, и другого одновременно. Иными словами, запрос информации не должен изменять состояние системы. Более формально, методы должны возвращать значение только если они референтно прозрачны и, следовательно, не имеют побочных эффектов.
Command query separation (CQS) is a principle of imperative computer programming. It was devised by Bertrand Meyer as part of his pioneering work on the Eiffel programming language. It states that every method should either be a command that performs an action, or a query that returns data to the caller, but not both. In other words, asking a question should not change the answer. More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.
Связь с проектом по договору
Отделение команд от запросов особенно хорошо подходит для методологии проектирования по контракту (DbC), в которой дизайн программы выражается в виде утверждений, встроенных в исходный код, описывающих состояние программы в определенные критические моменты времени. В DbC утверждения рассматриваются как проектные аннотации, а не как программная логика, и, следовательно, их выполнение не должно влиять на состояние программы. CQS полезен для DbC, поскольку любой метод, возвращающий значение (любой запрос), может быть вызван любым утверждением без опасения изменить состояние программы. С теоретической точки зрения, это обеспечивает определенную логичность, позволяющую рассуждать о состоянии программы, не изменяя его одновременно. На практике CQS позволяет отключать все проверки утверждений в рабочей системе для повышения ее производительности, не изменяя при этом ее поведение непреднамеренно. CQS также может предотвратить возникновение определенных видов гейзенбагов.
Более широкое влияние на разработку программного обеспечения
Даже помимо связи с проектированием по контракту, сторонники CQS считают, что она упрощает программу, делая её состояния (через запросы) и изменения состояний (через команды) более понятными. CQS хорошо сочетается с объектно-ориентированной методологией, но также может применяться и вне объектно-ориентированного программирования. Поскольку разделение побочных эффектов и возвращаемых значений не является неотъемлемой частью объектно-ориентированного подхода, CQS может быть полезно применена к любой парадигме программирования, требующей анализа побочных эффектов.
Разделение ответственности командной запроса
Сегрегация ответственности за командные запросы (CQRS) обобщает CQS для сервисов на уровне архитектуры: она применяет принцип CQS, используя отдельные интерфейсы запросов и команд, а также, как правило, различные модели данных для получения и изменения данных соответственно.
Другие архитектурные узоры
По мере того, как мы отказываемся от единого представления, с которым взаимодействуем посредством CRUD, мы можем легко перейти к пользовательскому интерфейсу, ориентированному на задачи. CQRS хорошо сочетается с моделями программирования, основанными на событиях. Обычно в системе CQRS наблюдается разделение на отдельные сервисы, взаимодействующие посредством совместной работы на основе событий (Event Collaboration). Это позволяет этим сервисам легко использовать преимущества архитектуры, управляемой событиями. Использование отдельных моделей ставит вопрос о сложности обеспечения их согласованности, что повышает вероятность применения eventual consistency (конечной согласованности). Для многих предметных областей значительная часть необходимой логики требуется при обновлении данных, поэтому может быть целесообразно использовать Eager Read Derivation (жадное получение производных данных для чтения) для упрощения моделей, используемых на стороне запросов. Если модель записи генерирует события для всех обновлений, модели чтения можно структурировать как подписчики событий (Event Posters), позволяя им быть представлениями в памяти (Memory Images) и, таким образом, избегая большого количества обращений к базе данных. CQRS подходит для сложных предметных областей, которые также выигрывают от применения Domain-Driven Design.