Command & Query Responsibility Segregation (CQRS)

В 1985 году Бертран Майер описал концепцию CQS, которая заключалась в том, что команды делают изменения и не возвращают данные (при этом не запрещается возвращать статусы команды или какие-то ошибки), данные возвращаются только с помощью запросов, которые не могут изменять данные.

Спустя некоторое время, аж в 2010 году, Грек Янг описал подход CQRS. Тогда он описывал это как CQS с дополнениями. Тренд был быстро подхвачен.

CQS vs CQRS

CQS – команды и запросы обрабатываются одним объектом.

CQRS – команды и запросы обрабатываются разными объектами.

Какую проблему решаем?

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

Допустим, у нас есть экран, где надо показать название продукта, цену и наличие на конкретном складе. Для этого необходимо, как правило, связать огромное количество объектов и выполнить несколько сложных запросов. Если все это помножить на количество таких товаров, мы получим неслабую нагрузку на домен и БД.

Дополнительной проблемой тут является ORM. При маппинге данных из БД с объектами домена обычно получается так, что нам нужно много оптимизировать и кастомизировать в коде для обеспечения быстрой загрузки (ленивая загрузка), выборки и так далее, что усложняет поддержку и развитие проекта. Если что-то меняется в БД, то обязательно нужно что-то менять в коде, да и, как правило, не в одном месте, затем обновлять тесты. В общем, производить огромное количество работы, которую, казалось бы, можно и не делать.

CQRS призван решать все эти проблемы за счет разделения логики на команды и запросы. Каждая модель для чтения предназначена своему запросу. Фактически это Data Access Layer,  компонент архитектуры программного обеспечения, который переводит запросы в запросы к БД и обратно. Как правило, данные уже лежат заранее подготовленные в готовых подходящих структурах для отображения пользователям. При этом команды работают с доменами записи, которые направлены на конкретные операции. Тут нам не требуются никакие эвенты, мы просто читаем и записываем раздельно.

Если более детально посмотреть на реализацию, то можно описать так:

1⃣ Команда -> Шина команд -> Обработчик команд -> Доменная модель -> Данные 2⃣ Запрос -> Обработчик запроса -> Данные

Применимость

✔️Сервисы, где происходит работа с массивом данных, а не с единичными записями. ✔️Система не обязана использовать DDD или строиться на событиях. ✔️Чтение данных преобладает над записью, тогда можно получить серьезный прирост в производительности. ✔️Для средних и крупных систем, где требуется скорость и гибкость.

Памятка-пример по доменам

Каждый сервис может реализовывать свой архитектурный стиль. Применять CQRS для всей системы часто нецелесообразно.

Домен Заказы = Event Sourcing Домен Клиенты = Transactional + CRUD Домен Товары = DDD + CRUD Домен Склад = CQRS + Event Sourcing

Технические сложности

▪️ Синхронизация данных между базой записи и базой чтения. ▪️ Требуется больше места для хранения данных. ▪️ Поддержка версионности сообщений.

Мой канал – https://t.me/carbonka

Command & Query Responsibility Segregation (CQRS)
В 1985 году Бертран Майер описал концепцию CQS, которая заключалась в том, что команды делают изменения и не возвращают данные (при этом не запрещаетс... | Сетка — социальная сеть от hh.ru