Недавно я прочитал статью CQRS à la Greg Young, и я все еще пытаюсь склонить голову CQRS.
Я не уверен, где должна выполняться проверка ввода, и, если это возможно, должно произойти в двух разных местах (тем самым нарушая правило "Не повторять себя" и, возможно, также разделение проблем).
Учитывая следующую архитектуру приложения:
# +--------------------+ ||
# | event store | ||
# +--------------------+ ||
# ^ | ||
# | events | ||
# | v
# +--------------------+ events +--------------------+
# | domain/ | ---------------------> | (denormalized) |
# | business objects | | query repository |
# +--------------------+ || +--------------------+
# ^ ^ ^ ^ ^ || |
# | | | | | || |
# +--------------------+ || |
# | command bus | || |
# +--------------------+ || |
# ^ |
# | +------------------+ |
# +------------ | user interface | <-----------+
# commands +------------------+ UI form data
-
Домен скрыт от пользовательского интерфейса за командной шиной. То есть пользовательский интерфейс может отправлять команды только домену, но никогда не попадает непосредственно в объекты домена.
-
Валидация не должна происходить, когда агрегирующий корень реагирует на событие, но раньше.
-
Команды превращаются в события в домене (по совокупным корням). Это одно место, где может произойти проверка: если команда не может быть выполнена, она не превращается в соответствующее событие; вместо этого (например) генерируется исключение, которое пузырится через командную шину, обратно в пользовательский интерфейс, где он попадает.
Проблема:
Если команда не сможет выполнить, я хотел бы отключить соответствующую кнопку или пункт меню в пользовательском интерфейсе. Но как я могу узнать, может ли команда выполнить ее перед отправкой? Сторона запроса не поможет мне здесь, поскольку она не содержит никакой бизнес-логики; и все, что я могу сделать на стороне команды, - это команды отправки.
Возможные решения:
-
Для любой команды DoX введите соответствующую фиктивную команду CanDoX, которая на самом деле ничего не сделает, но позволяет домену дать отзыв, может ли команда X выполнить без ошибок.
-
Дублируйте в UI некоторую логику проверки (которая действительно принадлежит домену).
Очевидно, что второе решение не является благоприятным (из-за отсутствия разделения ). Но первый действительно лучше?