CQRS

Материал из Википедии — свободной энциклопедии
Перейти к навигации Перейти к поиску

The Command and Query Responsibility Segregation (CQRS) - принцип или парадигма CQRS разделяет назначение запросов(напр. при чтении данных) и команд на обработку данных. Внедрение CQRS в приложение может максимизировать его производительность, масштабируемость и безопасность. Гибкость, создаваемая переходом на CQRS, позволяет системе лучше развиваться с течением времени и не позволяет командам обновления вызывать конфликты слияния на уровне домена.[1]

Шаблон CQRS применяет принцип императивного программирования разделения команд и запросов - сommand-query separation (CQS), используя отдельные объекты запросов и команд для извлечения и изменения данных соответственно[2][3]. CQS введён Бертраном Мейером во время работы над языком программирования Eiffel. Принцип гласит, что метод должен быть либо командой, выполняющей какое-то действие, либо запросом, возвращающим данные, но не одновременно. Другими словами, задавание вопроса не должно менять ответ. Более формально, возвращать значение можно только чистым (т.е. детерминированным и не имеющим побочных эффектов) методом. Следует отметить, что строгое соблюдение этого принципа делает невозможным отслеживание количества вызовов запросов.

Применение в контрактном программировании[править | править код]

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

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

Другие применения[править | править код]

Даже за пределами контрактного программирования, применение CQRS рассматривается его приверженцами как оказывающее эффект упрощения на программу, делая доступ к её состоянию (через запросы) и изменение её состояния (через команды) более понятными, аналогично тому как избежание использования goto упрощает понимание потока выполнения программы.

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

Недостатки[править | править код]

CQS может осложнить создание реентерабельного и многопоточного ПО. Эта проблема обычно возникает при использовании непотокобезопасного шаблона для реализации CQS.

Простой пример шаблона, нарушающего CQS, но полезного в многопоточном ПО:

private int x;
public int increment_and_return_x()
{
  lock x;   // какой-либо механизм блокировки
  x = x + 1;
  int x_copy = x;
  unlock x; // какой-либо механизм блокировки
  return x_copy;
}

Распространённый CQS шаблон, применимый только в однопоточных приложениях:

private int x;
public int value()
{
  return x;
}
void increment_x()
{
  x = x + 1;
}

Даже в случае однопоточных программ иногда можно утверждать, что значительно более удобно иметь метод, объединяющий запрос и команду. Мартин Фаулер приводит метод стека pop() в качестве примера.[4]

См. также[править | править код]

Примечания[править | править код]

  1. dragon119. CQRS pattern - Azure Architecture Center (англ.). docs.microsoft.com. Дата обращения: 1 апреля 2021.
  2. Young, Greg CQRS Documents. Дата обращения: 28 декабря 2012.
  3. Fowler, Martin CQRS. Дата обращения: 14 июля 2011.
  4. CommandQuerySeparation

Литература[править | править код]

Ссылки[править | править код]