Валидаторы бизнес-правил и обработчик команд в CQRS - PullRequest
32 голосов
/ 23 марта 2011

Я новичок в CQRS, и я пытаюсь понять смысл проверки бизнес-правил на стороне записи (домен).Я знаю, что проверка на стороне клиента должна выполняться с точки зрения действительной даты (обязательное поле, длина строки, действительный адрес электронной почты и т. Д.), А проверка, связанная с бизнес-правилом / бизнес-доменом, должна выполняться на стороне домена.На самом деле, те же правила проверки на стороне клиента также должны применяться к команде в домене, поскольку мы не доверяем пользователям.

Итак, у нас есть действительная команда (AddEmailToCustomer), и для команды вызывается обработчик команды,Вот мой подход к валидации.

  1. Создание экземпляров двух валидаторов команд в обработчике команд.
  2. Первый проверяет данные команды так же, как и проверка на стороне клиента (обязательное поле, действительный адрес электронной почты)и т. д.)
  3. Второй валидатор проверяет данные на основе логики во втором валидаторе.Что-то вроде "активен ли этот клиент" или что-то ещеЯ знаю, что меняющаяся электронная почта здесь не подходит, но это не важно.Важно то, что здесь есть проверка бизнеса.
  4. Мы смотрим на ValidationResult, возвращаемый Validator.Validate (ICommand cmd), и обнаруживаем, что есть ошибки
  5. Мы не получим клиентаиз хранилища для вызова метода UpdateEmail на AR.Так что же нам делать на этом этапе?

Я выбрасываю исключение в обработчике команд и добавляю туда эти ошибки?Отправить команду в очередь ошибок или куда-то еще?Я отвечаю что-то вроде Bus.Reply и возвращаю код ошибки?Если да, что мне делать с сообщениями об ошибках?Как мне сообщить об этих ошибках пользователю?Я знаю, что могу отправить их по электронной почте позже, но в веб-сценарии я могу отправить идентификатор запроса в команде (или использовать идентификатор сообщения), опросить ответ с идентификатором запроса и отобразить сообщения об ошибках для пользователя.

Ваше руководство приветствуется.

Спасибо

1 Ответ

42 голосов
/ 23 марта 2011

Важно знать, что команды могут быть отклонены после того, как они отправлены обработчику.

По крайней мере, вы можете столкнуться с нарушением параллелизма, которое не может быть обнаружено, пока не будет затронут совокупный корень.

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

Проверка того, что не может произойти вне сущности, является проверкой вашей бизнес-логики.Эта проверка зависит от контекста, в котором она выполняется ( см. Уточненный CQRS Уди Даана ).

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

Кроме того, я считаю, что проверка, которая происходит в пользовательском интерфейсе, должна быть перепроверена не в обработчике команд, а в домене.Эта проверка существует для предотвращения повреждения домена - если она не выполняется за пределами домена, то домен по-прежнему имеет недопустимые параметры.

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

Наконец, вам нужно будет всплытьКоманды отклонены из обработчика.Я делаю это с максимально возможными исключениями.

...