Красовская, Анастасия Олеговна
- 1 year ago
- 0
- 0
The Command and Query Responsibility Segregation (CQRS) — принцип, или парадигма, CQRS разделяет назначение запросов (например, при чтении данных) и команд на обработку данных. Внедрение CQRS в приложение может максимизировать его производительность, масштабируемость и безопасность. Гибкость, создаваемая переходом на CQRS, позволяет системе лучше развиваться с течением времени и не позволяет командам обновления вызывать конфликты слияния на уровне домена.
Шаблон CQRS применяет принцип императивного программирования разделения команд и запросов — сommand-query separation ( CQS ), используя отдельные объекты запросов и команд для извлечения и изменения данных соответственно . CQS введён Бертраном Мейером во время работы над языком программирования Eiffel . Принцип гласит, что метод должен быть либо командой , выполняющей какое-то действие, либо запросом , возвращающим данные, но не одновременно. Другими словами, задавание вопроса не должно менять ответ . Более формально, возвращать значение можно только чистым (т. е. детерминированным и не имеющим побочных эффектов ) методом. Строгое соблюдение этого принципа делает невозможным отслеживание количества вызовов запросов.
CQRS особенно хорошо вписывается в методологию контрактного программирования , в которой используются утверждения , встроенные в исходный код, описывающие состояние программы в определённые важные моменты. В контрактном программировании утверждения относятся к проектированию, а не к логике выполнения, поэтому их выполнение не должно оказывать влияния на состояние программы. CQRS выгоден для контрактного программирования, так как любой возвращающий значение метод (любой запрос) можно вызывать в утверждениях, не беспокоясь о возможном изменении состояния программы.
Теоретически, это даёт возможность узнавать состояние программы, не меняя его. На практике, CQRS даёт возможность пропустить все проверки утверждений в действующей системе, чтобы повысить её производительность, не боясь того, что это изменит её поведение. CQRS также предотвращает возникновение некоторых гейзенбагов .
Даже за пределами контрактного программирования, применение CQRS рассматривается его приверженцами как оказывающее эффект упрощения на программу, делая доступ к её состоянию (через запросы) и изменение её состояния (через команды) более понятными, аналогично тому как избежание использования goto упрощает понимание потока выполнения программы.
CQRS хорошо подходит для методологии объектно-ориентированного программирования, но может быть применён и вне ООП, так как разделение побочных эффектов и возвращения значений не требует ООП, поэтому CQRS может быть с пользой применён в любой парадигме программирования , требующей заботы о побочных эффектах.
CQRS может осложнить создание реентерабельного и многопоточного ПО. Эта проблема обычно возникает при использовании непотокобезопасного шаблона для реализации CQRS.
Простой пример шаблона, нарушающего CQRS, но полезного в многопоточном ПО:
private int x;
public int increment_and_return_x()
{
lock x; // какой-либо механизм блокировки
x = x + 1;
int x_copy = x;
unlock x; // какой-либо механизм блокировки
return x_copy;
}
Распространённый CQRS шаблон, применимый только в однопоточных приложениях:
private int x;
public int value()
{
return x;
}
void increment_x()
{
x = x + 1;
}
Даже в случае однопоточных программ иногда можно утверждать, что значительно более удобно иметь метод, объединяющий запрос и команду.
Мартин Фаулер
приводит метод
стека
pop()
в качестве примера.