Domain driven design 域驱动设计:应用程序服务中允许的逻辑

Domain driven design 域驱动设计:应用程序服务中允许的逻辑,domain-driven-design,Domain Driven Design,我有一个问题,就是如何更好地组织以下功能的实现。 假设一个用户需要通过唯一的电子邮件和密码注册到系统中(第一步),然后他应该确认注册(第二步)。在应用程序服务/域服务/用户实体之间,我有几种构建第一步(注册)实现的选择,我不确定哪一个更好 第一个选项: 应用程序服务: var existingUser = UserRepository.GetUserByEmail(email); if (existingUser != null) { throw new ValidationExcep

我有一个问题,就是如何更好地组织以下功能的实现。 假设一个用户需要通过唯一的电子邮件和密码注册到系统中(第一步),然后他应该确认注册(第二步)。在应用程序服务/域服务/用户实体之间,我有几种构建第一步(注册)实现的选择,我不确定哪一个更好

第一个选项:

应用程序服务:

var existingUser = UserRepository.GetUserByEmail(email);

if (existingUser != null)
{
    throw new ValidationException(...);
}

var newUser = UserFactory.CreateUser();

newUser.Register(email, password);

UserRepository.Save(newUser);

// commit
var user = UserRegistrationDomainService.RegisterUser(email, password);

UserRepository.Save(user);

// commit
所以在这里,我们不使用任何域服务。我个人感到不舒服的是,电子邮件唯一性业务规则是在应用程序服务中检查的,这是一个业务规则

第二选项:

应用程序服务:

var existingUser = UserRepository.GetUserByEmail(email);

if (existingUser != null)
{
    throw new ValidationException(...);
}

var newUser = UserFactory.CreateUser();

newUser.Register(email, password);

UserRepository.Save(newUser);

// commit
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()。所以对于注册确认,我们不需要任何域服务,而对于注册,在第二个选项中,我们使用这样的服务


哪种选择更好?第一个选项中的应用程序服务是否可以包含电子邮件唯一性验证?

我个人认为验证存在于域中(服务的实体)。毕竟,由于业务规则,该规则是必需的


在选项2中,应用程序服务最好不负责保存用户,这会模糊责任线,如果域服务处理它会更好。应用程序服务只需调用
UserRegistrationDomainService.RegisterUser(电子邮件、密码)
选项1意味着唯一的电子邮件规则是特定于应用程序的。换句话说,如果您使用域dll(或jar、模块等)在另一个应用程序中重用它,那么规则将不再存在

既然我们可以合理地认为这个规则是不可知的,我会选择选项2。


另一个解决方案可能是在工厂实施。毕竟,在创建用户时,您通常会将验证逻辑放在这里(空/空名称检查、电子邮件格式验证等),因此为什么不将所有创建规则集中在同一个位置?

这属于“成员资格”系统的外观,无论是服务还是其他。我读过这本书并练习了这些单词,但我逐渐意识到,如果不很好地理解DDD,它会造成伤害。它促使程序员应用“配方”,因为他们愿意设计模式,而不是为手头的问题创建解决方案。