我有一个如何更好地组织以下功能的实现的问题。 假设用户需要通过唯一电子邮件和密码(第一步)注册到系统中,然后他应该确认注册(第二步)。我有几种选择来构建应用程序服务/域服务/ 用户实体之间的第一步(注册)实现,我不确定哪一个更好。
第一个选项:
AppService服务:
var existingUser = UserRepository.GetUserByEmail(email);
if (existingUser != null)
{
throw new ValidationException(...);
}
var newUser = UserFactory.CreateUser();
newUser.Register(email, password);
UserRepository.Save(newUser);
// commit
所以在这里,我们不使用任何域名服务。我个人觉得不舒服的事情是在应用服务中检查电子邮件唯一性业务规则,这是一个商业规则。
第二个选项:
AppService服务:
var user = UserRegistrationDomainService.RegisterUser(email, password);
UserRepository.Save(user);
// commit
UserRegistrationDomainService:
User RegisterUser(email, password)
{
var existingUser = UserRepository.GetUserByEmail(email);
if (existingUser != null)
{
throw new ValidationException(...);
}
var newUser = UserFactory.CreateUser();
newUser.Register(email, password);
return newUser;
}
我不喜欢这里,这个解决方案与第二步的实现并不完全对称,我们只是从存储库中获取用户并调用User.ConfirmRegistration()。因此,对于注册确认,我们不需要任何域名服务,而对于注册,在第二个选项中,我们使用此类服务。
哪个选项更好?第一个选项的应用程序服务是否可以包含电子邮件唯一性验证?
答案 0 :(得分:3)
就我个人而言,我认为其验证存在于域中(服务的实体)。毕竟,由于业务规则,该规则是必需的。
在选项2中,最好是应用程序服务不负责保存用户,这会模糊责任,如果域服务处理它会更好。应用程序服务只需调用UserRegistrationDomainService.RegisterUser(email, password)
答案 1 :(得分:1)
选项1表示唯一的电子邮件规则是特定于应用程序的。换句话说,如果你使用域dll(或jar,模块等)在另一个应用程序中重用它,规则将不再存在。
由于我们可以合理地认为该规则与应用程序无关,因此我选择选项2.
另一种解决方案可能是在工厂中实现它。毕竟,您通常会在创建用户时使用验证逻辑(空/空名称检查,电子邮件格式验证等),那么为什么不将所有创建规则集中在同一个地方呢?