Мне нравится идея использования CQRS без источника событий. Но я не уверен, как решить тот факт, что мне нужно дать пользователю мгновенную обратную связь.Валидация и синхронные команды в CQRS
Это моя текущая регистрация (упрощенная для понимания) Я использую Dapper для чтения и nHibernate для записи.
signupcontroller.cs
public ActionResult signup(UserCreateModel model)
{
// model validation (email, password strength etc)
if (!ModelState.IsValid)
{
// get back to form and show errors
}
// use service layer to validate against database and create user
var registermodel = _userService.create_user_account(model.username, model.email, model.password);
// service returns and object with several states
if (registermodel.Status == UserRegistrationStatus.Ok)
{
// user registered ok, display thank you or whatever
}
if (registermodel.Status == UserRegistrationStatus.DuplicatedUsername)
{
// duplicated username found, back to form and show errors
}
if (registermodel.Status == UserRegistrationStatus.DuplicatedEmail)
{
// duplicated email found, back to form and show errors
}
// get back to form and show errors
}
Какой из appraoches будет наиболее CQRS дружелюбные?
Метод 1
signupcontroller.cs
public ActionResult signup(UserCreateModel model)
{
// model validation (email, password strength etc)
if (!ModelState.IsValid)
{
// get back to form and show errors
}
// validate duplicated email
bool is_email_duplicated = _read.user_email_exists(model.email);
// duplicated email found, back to form and show errors
// validate duplicated username
bool is_username_duplicated = _read.user_username_exists(model.username);
// duplicated username found, back to form and show errors
// assume all is perfect and dispatch
_commandDispatcher.Dispatch(new CreateUserCommand(model.username, model.email, model.password));
}
Что делать, если мне нужно сделать то же проверку где-то в системе (я бы дублируется код)?
Я думал о создании ValidationService.
Что делать, если команда «взрывается» по какой-то причине, и пользователь получит ложную обратную связь?
Метод 2
signupcontroller.cs
public ActionResult signup(UserCreateModel model)
{
// model validation (email, password strength etc)
if (!ModelState.IsValid)
{
// get back to form and show errors
}
// dispatch and validate inside the handler, abort execution if validation failed
var command = new CreateUserCommand(model.username, model.email, model.password)
// attached common feedback object to the command and deal with errors
if(command.status == UserRegistrationStatus.DuplicatedUsername)
{
// get back to form and show errors
}
}
В основном внутри обработчика я обмануть и проверки (добавление дополнительных методов NHibernate репо).
Метод 3
Подобно первому подходу, но герметизирующего проверки и отправки в UserService
signupcontroller.cs
public ActionResult signup(UserCreateModel model)
{
// model validation (email, password strength etc)
if (!ModelState.IsValid)
{
// get back to form and show errors
}
var feedback = _userService.create_user(model.username, model.email, model.password);
// check for status and return feedback to the user
}
userservice.cs
public Feedback create_user(string username, string email, string password)
{
// validate duplicated email
bool is_email_duplicated = _read.user_email_exists(email);
// duplicated email found, back to form and show errors
// validate duplicated username
bool is_username_duplicated = _read.user_username_exists(username);
// duplicated username found, back to form and show errors
// dispatch command
_commandDispatcher.Dispatch(new CreateUserCommand(username, email, password));
}
Мне нравится этот подход, но я чувствую, что он станет кодом Баклавы.
Вы можете отлично добавьте свои «чтения» в CommandHandler. В конце концов, ничего не происходит в CommandHandler, пока вы не решите создать новое AR или не модифицируете что-либо. Вы можете отлично отбросить исключение из своего CommandHandler и позволить управлению справиться с этим. –