День 1363. #ЗаметкиНаПолях
CQRS. Факты и Мифы. Начало
Технические паттерны полны мифов и неверных толкований. Довольно часто это происходит с CQS и CQRS. Часто про CQ(R)S можно услышать, что:
- нужны две базы данных,
- нужно использовать очередь сообщений (например, RabbitMQ или Kafka),
- это сложно применить и усложняет архитектуру,
- возникнут проблемы окончательной согласованности (Eventual Consistency),
- нужно реализовывать паттерн Источников Событий (Event Sourcing).
CQS означает Разделение Команд и Запросов (Command Query Separation).
CQRS — Разделение Ответственности Команд и Запросов (Command Query Responsibility Segregation).
Ничто в названии не говорит о двух базах данных, разных таблицах или вообще о том, как информация хранится. Зато и в CQS, и в CQRS в названии есть Команды и Запросы:
Команда (Command) — это запрос на изменение.
Запрос (Query) — это запрос на возврат данных.
Команда для добавления события может выглядеть так:
public class CreateEvent
{
public string Name { get; }
public string Where { get; }
public DateTime When { get; }
}
Запрос на получение данных события может выглядеть так:
public class GetEvent
{
public Guid Id { get; }
}
Как видите, это простые DTO.
Шаблон CQS был создан Бертраном Мейером во время его работы над языком Eiffel. Он утверждал, что: «Задавание вопроса не должно менять ответ» и определил, что: «Команда (процедура) что-то делает, но не возвращает результат. Запрос (функция) возвращает результат, но не изменяет состояние». Благодаря такому различию обработку можно сделать более простой и предсказуемой. Запрос не создаст никаких побочных эффектов. Команда не будет использоваться для получения данных.
CQRS является расширением CQS. Грег Янг определил его так: «Разделение ответственности команд и запросов использует то же определение команд и запросов, что и у Мейера, и придерживается точки зрения, что они должны быть чистыми. Принципиальное отличие состоит в том, что в CQRS объекты делятся на два типа, один из которых содержит команды, а другой — запросы». Таким образом, CQS определяет общий принцип поведения. CQRS более конкретно говорит о реализации.
При использовании CQRS должно быть строгое разделение между моделью записи и моделью чтения. Они должны обрабатываться отдельными объектами (обработчиками) и не быть концептуально связанными друг с другом. Обработчики же не являются структурами хранения информации и не связаны с тем, где и как будут храниться данные. Обработчики команд исполняют команды, которые изменяют состояние или выполняют другие операции с побочными эффектами. Обработчики запросов отвечают за возврат результата запроса.
Ничто не мешает модели записи и модели чтения иметь одинаковую структуру или использовать одни и те же таблицы БД. Более того, в CQRS не обязательно использовать базу данных. Под капотом может быть Excel, текстовый файл или внешний API. Самое главное — концептуально разделять модели записи и чтения данных.
Ничто не мешает вам использовать реляционную базу данных, даже одну и ту же таблицу для чтения и записи, также можно использовать ORM. При этом вы можете извлечь выгоду из CQRS, например, отключив отслеживание изменений в обработчиках запросов, зная, что запрос не изменит состояния.
Окончание следует…
Источник: https://event-driven.io/en/cqrs_facts_and_myths_explained/