18 авг. 2010 г.

Что такое CQRS?

Command and Query Responsibility Segregation - это шаблон проектирования, описывающий принцип разделения приложения на две составные части, отвечающие, один - за обработку команд, второй - за обработку запросов к данным.
Автор шаблона, Григорий Юнг (Gregory Young)[1], пишет в своем блоге[2] о названии, данном шаблону, следующее:
"Я отказался от короткого имени шаблона и назвал его Command and Query Responsibility Segregation или CQRS так как это название в точности соответствует тому, что мы делаем - мы фактически разбиваем один объект на два и разделяем его обязанности между этими двумя объектами."
Шаблон очень похож на принцип разделения команд и запросов к данным Command-Query Segregation[3], предложенный Бертраном Майером,  в котором говорится о том, что каждый метод должен обеспечивать либо изменение состояния объекта, либо получение данных, но не оба действия одновременно.

В шаблоне CQRS принцип CQR применяется ко всему приложению в целом. В приложение четко выделяют две части - одну, отвечающую за изменение состояния объектов предметной области и одну, отвечающую за представление данных клиенту.

Трансформация архитектуры приложения при использовании шаблона CQRS.

    Что мы получаем от такого разделения? В чем проблема стандартного подхода?
  • Проблема в лишних преобразованиях?

      В стандартном приложении данные передаются всегда по одному и тому же маршруту:
    • Пользователь нажимает кнопку;
    • Клиент трансформирует модель представления в DTO и передает его серверу;
    • Сервер трансформирует объект DTO в объект предметной области;
    • К объекту предметной области применяются бизнес-правила;
    • Объект предметной области трансформируется в реляционную модель и сохраняется в базе данных.

      Запросы к данным происходят в обратном порядке:
    • Из базы данных извлекаются реляционные данные и трансформируются в объект предметной области;
    • объект предметной области трансформируется в DTO и передается клиенту;
    • Клиент трансформирует DTO в модель представления и отображает данные пользователю;

    Задайте себе простой вопрос - В чем объективная необходимость преобразования данных в модель предметной области и DTO? Клиенту они не нужны! Клиенту нужна модель представления, которую он отобразит пользователю.
  • Данные дают ответ на вопрос "как?".

    Как изменились данные контракта? Как изменился баланс клиента? Если вы хотя бы раз участвовали в "разборе полетов", то наверняка знаете, что это не тот вопрос, который интересует бизнес. Бизнес интересует вопрос "почему?" - Почему изменились данные контакта? Почему сумма на счете больше, чем прибыль?
  • Проблема в расширяемости?

    Что мы делаем, когда нам требуется расширить наше оборудование для увеличения производительности? Мы покупаем новое оборудование и настраиваем репликацию. Репликацию двухстороннюю. Тяжелую. И в плане настройки и в плане потребления ресурсов.

    Что дает нам разделение команд и запросов?
  • Отсутствие лишних преобразований данных.

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

    Информация о событиях, происходящих в системе, хранится в виде одной "плоской" таблицы. Это может быть не обязательно таблица базы данных - это может быть файл или какой-нибудь движок, позволяющий выбирать данные по ключу. Данные хранятся в виде набора событий. Это позволяет в любой момент времени "вернуться в прошлое" и проиграть тот или иной набор событий в порядке их изменения.
  • События дают ответ на вопрос "почему?"

    События хранятся в виде... событий. Перед сохранением события десериализуются, что дает возможность восстановить событие в точности в том же виде, каким оно было создано. Это позволяет создать набор событий, отвечающих на вопросы бизнеса "почему?". Например, базовую команду клиента ChangeCustomerAddressCommand можно расширить до ChangeCustomerAddressWhileCustomerDeparturedCommand и в ответ на нее создать событие CustomerAddressWasChangedWhileCustomerIsDeparturedEvent, которое даст точный ответ на вопрос "почему?".
  • Event-Driven подход позволяет легко наращивать мощность оборудования.

    По статистике 90% запросов к серверу - запросы к данным. Даже если опустить тот факт, что при использовании CQRS мы избавляемся от ненужных преобразований, остается еще один очень важный момент: для расширения системы нам нужен просто еще один сервер. Вся настройка сводится к установке на него еще одной копии кэша и подписке на события. Это позволяет очень быстро нарастить пропускную способность оборудования, простым добавлением серверов, обслуживающих запросы на получение данных.

На сегодня пока все. Если Вас заинтересовала данная тема - этот сайт для Вас. Если у Вас есть свои мысли или переводные материалы по теме программирования с использованием DDD/CQRS, обращайтесь ко мне лично в почту grominc@cqrs.net.ru, я постараюсь по возможности более полно ответить на все ваши вопросы или предоставить возможность самостоятельно размещать статьи в этом блоге.

-----------------------------
Ссылки на материалы, использованные в тексте

1. Greg Young blog блог Грега Юнга;
2. Gerg Young about CQRS Грег Юнг о шаблоне проектирования CQRS;
3. Command-Query segregation principle принцип CQS Бертрана Майера;
4. Майер, Бертрант (wikipedia);
5. Пол Фосмо о CQRS

Комментариев нет:

Отправить комментарий