CQRS - это...
Просто о NET | создано: 05.11.2020 | опубликовано: 05.11.2020 | обновлено: 13.01.2024 | просмотров: 5481 | всего комментариев: 2
Несколько фактов о CQRS
Что такое CQRS?
Для начала давайте определимся, что же всё-таки такое CQRS. Итак, CQRS - это способ написания программного кода. Аббревиатура расшифровывается как Command and Query Responsibility Segregation (CQRS). То есть это разделение ответственности на команды и запросы. Единственное, для чего он был придуман, так это для того, чтобы разделить операции записи в базу данных от операций чтения данных. И всё потому, что операции записи требуют больше ресурсов и времени чем операции чтения. Всё! И чего только не услышишь про этот CQRS, и "Task Based UIs", и даже "Event Sourcing"... Просто жесть! Давайте покажу на примере.
Пример применения паттерна CQRS на C#
Предположим, что у меня есть интерфейс репозитория для работы с сущностью User:
/// <summary> /// User repository /// </summary> public interface IUserRepository{ /// <summary> /// Returns user by identifer /// </summary> User GetById(Guid id); /// <summary> /// Returns user by identifer /// </summary> IPagedList<User> GetPaged(int pageIndex, int pageSize); /// <summary> /// Creates new user /// </summary> void CreateUser(string firstName, string lastName, DateTime dateOfBirth); /// <summary> /// Updates new user /// </summary> void UpdateUser(Guid id, string firstName, string lastName, DateTime dateOfBirth); /// <summary> /// Deletes user by identifier /// </summary> void DeleteUser(Guid id); /// <summary> /// Sets Salary for user with identity /// </summary> void SetSalary(Guid id, decimal value); }
Обратите внимание, что в моём репозитории есть несколько методов на получение данные (другими словами Query) и несколько методов на запись (можно назвать Command).
После того как я применю паттерн (подход), который уже набил оскомину и назавается CQRS, то мой репозиторий разделится на две части. Первая - это набор запросов (Queries):
/// <summary> /// User repository for read data /// </summary> public interface IUserReadRepository { /// <summary> /// Returns user by identifer /// </summary> User GetById(Guid id); /// <summary> /// Returns user by identifer /// </summary> IPagedList<User> GetPaged(int pageIndex, int pageSize); }
и вторая часть - это набор комманд (Commands):
/// <summary> /// User repository for write /// </summary> public interface IUserWriteRepository { /// <summary> /// Creates new user /// </summary> void CreateUser(string firstName, string lastName, DateTime dateOfBirth); /// <summary> /// Updates new user /// </summary> void UpdateUser(Guid id, string firstName, string lastName, DateTime dateOfBirth); /// <summary> /// Deletes user by identifier /// </summary> void DeleteUser(Guid id); /// <summary> /// Sets Salary for user with identity /// </summary> void SetSalary(Guid id, decimal value); }
Всё. Больше ничего в этом CQRS нет.
Заключение
В качестве заключения позвольте привести список "НЕ..."
- CQRS НЕ потребует на изучение более 2 минут.
- CQRS - это НЕ панацея от всех проблем
- CQRS НЕ является Event Sourcing
- CQRS НЕ требует Message Queue (шины сообщений)
- CQRS внутренне НЕ связан с DDD
- CQRS НЕ является архитектурой верхнего уровня
- CQRS НЕ является основополагающим принципом
- CQRS - это НЕ новый подход.
- CQRS - это НЕ серебряная пуля, и он никак не улучшит ваш код
- CQRS НЕ сделает ваш прижок в высоту выше
Ссылки
- CQRS wiki
- Другой пример: ReadonlyController и WritableController из сборки Calabonga.UnitOfWork.Controllers (nuget)
Комментарии к статье (2)
В начале статьи когда описывали IUserRepository допущена грубая ошибка: надо было сразу сказать, что этот интерфейс УЖЕ написан по шаблону CQRS. Вон, даже по первой же ссылке написано что? "Принцип гласит, что метод должен быть либо командой, выполняющей какое-то действие, либо запросом, возвращающим данные, но не одновременно". Посмотрите на каждый метод и найдите в нём хоть один метод, объединяющий и действие и получение данных. Ответственности УЖЕ разделены. Точка.