Command and Query Responsibility Segregation

Command and Query Responsibility Segregation (сокращенно — CQRS) — паттерн разделения ответственности в коде (обрабатывающем обращения к серверу) на команды и запросы получения данных. Основан на принципе программирования Command-query Separation (CQS) , который сформулирован Бертандом Майером, создателем языка Eiffel.

Такое разделение вносит свои особенности.

  • Команды (Command) ориентированы на задачи. Например «добавить товар в корзину», «оформить заказ» и т.п. Они изменяют данные прикладной области в БД. Команды могут быть как синхронными (в ответ возвращая успех операции или идентификатор добавленной сущности) так и асинхронными (помещаться в очередь для последующей обработки).
  • Запросы (Query) служат только для получения данных. Они не меняют данные прикладной области в БД. В ответ на запрос обычно отдается Data Transfer Object инкапсулирующий нужную информацию.

При реализации CQRS часто разделяют данные для чтения и записи по разным БД или таблицам. Подходы здесь могут применяться разнообразные. Например, использование Materialezed Views в качестве источника для чтения данных. Или использования реляционной БД для записи и NoSQL БД для чтения. Такие решения позволяют избавиться у операций чтения от сложных объединений таблиц, подзапросов и группировок.

Схема подхода CQRS представлена на рисунке ниже

Потоки данных при использовании CQRS
Потоки данных при использовании CQRS

Здесь трудное место — синхронизация БД чтения с данными БД записи. Обычно синхронизация достигается посредством событий в момент изменения БД записи. Тоесть в одной операции происходит как изменение данных основной БД так и отправка события на обновление данных в БД чтения. Процесс синхронизации БД чтения и записи называют проекцией.

Перечислим различные стороны паттерна CQRS.

Плюсы:

  • Возможность выдерживать большие нагрузки при операциях чтения из-за ухода от ресурсоёмких запросов к БД
  • Независимое масштабирование операций чтения и записи
  • Более простые запросы чтения за счет плоской (без ссылок на другие таблицы) БД чтения
  • Более простые классы за счет разделения ответственности, а значит проще обслуживать такой код
  • Большая гибкость описания прав доступа, так как можно отдельно прописывать права для обращений на чтение и запись

Минусы:

  • Не смотря на простоту формулировки CQRS сложность может крыться в деталях. Например, в организации механизма синхронизации БД чтения с БД записи
  • Нужно организовывать подсистему обработки событий
  • Проблема загрузки пользователем устаревших данных, если БД чтения отстает от БД записи

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

Leave a Reply

Ваш адрес email не будет опубликован.