🔥 CQRS - это 3-й всадник архитектурного апокалипсиса, которым обычно дополняют DDD и Event Sourcing. Если вы тоже сорвали джекпот, давайте разберём как вообще с этим работать.

🔀 В основе идея, что нужно разделить приложения на части - одна для изменения данных (Write model) и другая для их чтения (Read model). Потому что назначение и требования к ним разные. И все клиенты (frontend, mobile) начинают работать именно с моделью чтения. Модель чтения состоит из так называемых view - наборов атрибутов одного или нескольких агрегатов. По сути денормализованных таблиц в базе данных, оптимизированных для быстрой выборки.

Многие элементы логики в моделях чтения и записи совпадают. Обе модели имеют снапшоты агрегатов и применяют события. Но есть критичные отличия: 💡 Модель чтения не проверяет инварианты. 💡 Вместо набора событий в ней хранится состояние агрегата, набор значений только тех его атрибутов, которые нужны клиентам. 💡 view может хранить данные нескольких агрегатов в одной таблице, чтобы обойтись без лишних join’ов.

⚖️ Проблемы и особенности подхода начинаются сильнее проявляться при масштабировании. В лучшем случае у вас один сервис на чтение и один на запись. В худшем - по сервису на каждый тип агрегатов и каждый view. Это оправдано, когда отличается нагрузка на каждый сервис, и их нужно масштабировать независимо.

🔄 Каждая view реагирует только на определенные события. Если модель чтения - единый сервис, то он инкапсулирует эту логику, получает все события и обновляет view внутри себя. Но если каждая view - это отдельный сервис, то начинается невероятно сложная хореография событий в системе.

📡 Также важно учитывать сетевые задержки. View обновляются не мгновенно и могут содержать информацию неактуальную по сравнению с моделью записи. Также View могут быть рассогласованы между собой.

⚙️ Один из подходов - полностью скрыть сложность внутри серверной части. Слои Middleware могут взять на себя маршрутизацию запросов, решать, в какой агрегат отправить command и кому адресовать query. Внешние клиенты видят простой и привычный RESTful API. Это удобный, но далеко не единственный вариант.

💻 На практике я столкнулся с другим подходом. Вместо того чтобы скрывать сложность, клиент может ее принять. Толстый клиент (thick client), который читает из read модели и параллельно получает события и применяет их к внутренней модели агрегата, чтобы сделать ее актуальной. Бизнес-логика дублируется на backend и frontend, это сложно реализовать и поддерживать. Но именно этот подход обеспечивает максимальную отзывчивость интерфейса.

🧩 Очередной архитектурный tradeoff. Один из той сотни, которые неочевидны до начала реализации. Внедрение CQRS облегчит масштабирование, но серьезно усложнит достижение консистентности системы. Надеюсь, в вашей команде есть люди c опытом применения этого подхода, которые смогут принимать грамотные решения, подходящие именно вашей системе.

🔥 CQRS - это 3-й всадник архитектурного апокалипсиса, которым обычно дополняют DDD и Event Sourcing. Если вы тоже сорвали джекпот, давайте разберём как вообще с этим работать | Сетка — социальная сеть от hh.ru