[Перевод] CQRS, UI, основаный на заданиях, Источники событий… ах

Ремарка от меня. Подобрать терминологию было непросто, поэтому готов в процессе редактировать перевод, чтобы улучшить понимание текста.

Многие люди путаются, чем является CQRS. Они смотрят на CQRS как на архитектуру — но это не так. CQRS очень простой шаблон, который позволяет много возможностей для архитектуры, которой иначе может и не быть. CQRS это не конечная согласованность, не событийность, это не обмен сообщениями, а также не разные модели для чтения и записи, а также не использование источников событий. Я хочу несколькими абзацами описать точно, чем CQRS является, а потом рассказать, как он относится к другим шаблонам.
CQRS Разделение ответственности команд и запросов (Command and Query Responsibility Segregation)

Чтобы начать с CQRS, просто создайте два объекта, которые ранее были одним. Разделение основано на том что методы это команды или запросы (то же определение что использовано в Meyer в Command and Query Separation, команда это любой метод, который изменяет состояние, и запрос это любой метод, который возвращает значение).

Когда большинство людей обсуждают CQRS, они действительно говорят о применении подхода к объекту, который представляет собой сервисную службу приложения. Рассмотрим следующий псевдо-код сервиса.

CustomerService

void MakeCustomerPreferred(CustomerId)
Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

Применение CQRS на этом приведет к двум сервисам

CustomerWriteService

void MakeCustomerPreferred(CustomerId)
void ChangeCustomerLocale(CustomerId, NewLocale)
void CreateCustomer(Customer)
void EditCustomerDetails(CustomerDetails)

CustomerReadService

Customer GetCustomer(CustomerId)
CustomerSet GetCustomersWithName(Name)
CustomerSet GetPreferredCustomers()

Вот и все. Это вся картина CQRS шаблона. Нет ничего более, чем это… Не кажется уже столь интересным когда мы объясняем это так, не так ли? Это разделение, позволяет сделать нам много интересного в архитектурном отношении. Самое большое, что оно разрывает процесс умственной деградации, потому что два используют те же данные, они также должны использовать ту же модель данных.

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

UI, основанный на заданиях (Task based UI)

Пользовательский интерфейс, основанный на заданиях, довольно сильно отличается от основанного на CRUD. В нем вы следите, что делает пользователь и продвигаете команды, которые представляют его намерения. Я хотел бы заявить, раз и навсегда что CQRS не требует интерфейса основанного на заданиях. Можно применить CQRS в CRUD приложении (хотя такие вещи как создание отдельных моделей будет гораздо сложнее).

Существует однако одна вещь, которая действительно требует такой интерфейс — это доменная модель.

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

В нашем вездесущем языке не было бы глаголов кроме «Создать», «Удалить» и «Изменить». Пока у вас много таких моделей, в которых вездесущий язык только такой, вам, наверное, не стоит использовать принцип доменных моделей для построения системы.

Понятие о таком интерфейсе не предполагает быть частью CQRS, но это не так. Домен может иметь глаголы, но также он должен следить за намерениями пользователя, в целом это важно. Было ли это принудительным или нормальным обновлением? Какая разница? Зависит от того, какой вопрос вы хотели спросить…

Двигаемся к следующему шаблону, который вводит в заблуждение в CQRS

Источники событий

Хочу чтобы было ясно, когда я использую этот термин, я не охватываю все что написано в bliki. Я ссылаюсь к хранению текущего состояния, как серии событий и возобновляю состояние системы повторяя эти серии событий…

На командной стороне уравнения, с тех пор как «чтения» больше не часть домена, сохранение событий может быть отличным способом поддержания текущего состояния. Значение возрастет больше если вы решите иметь две отдельные модели (модель для чтения и модель для записи) и у вас есть необходимость в их интеграции, так что вы вероятнее всего будете это делать через события. Так как вы все равно сохраняете событийность, почему бы просто не использовать одну модель для управления состоянием?

Шаблон обмена сообщениями

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

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

Конечная согласованность

Принцип конечной согласованности также довольно часто вводится между сервисами. Это делается из многих архитектурных побуждений. Но самый большой выигрыш — это то, что он позволяет увеличить масштабируемость и доступность. Если вы помните CAP теорему, там сказано, что если согласованности нету — это увеличивает другие два свойства. Она очень полезна между моделями, если они у вас разделены, но это ни в коем случае не есть свойство самой CQRS.

Пройдя через все из них мы видим, что CQRS на самом деле довольно простой шаблон. Все, что крутится около CQRS, это не CQRS сам собой, а архитектурные свойства интеграции двух сервисов. Другими словами, самое интересное это не шаблон CQRS, а те решения, которые принимаются около него. Поймите меня правильно, есть много интересных решений, которые были задействованы в системе, в которой решили использовать CQRS… но это не есть сам по себе CQRS.

© Habrahabr.ru