13

我正在从事我的第一个 DDD 项目,我想我了解实体、数据访问对象及其关系的基本角色。我有一个基本的验证实现,它将每个验证规则与其关联的实体一起存储。这适用于仅适用于当前实体的规则,但在需要其他数据时会崩溃。例如,如果我有用户名必须唯一的限制,我希望 IsValid() 调用在存在具有当前名称的现有用户时返回 false。

但是,我没有找到任何干净的方法来将此验证规则保留在实体本身上。我想在实体上有一个 IsNameUnique 函数,但大多数解决方案都需要我注入一个用户数据访问对象。这个逻辑应该在外部服务中吗?如果是这样,我如何仍然与实体本身保持逻辑?还是这应该在用户实体之外?

谢谢!

4

3 回答 3

4

我喜欢 Samuel 的回答,但为了简单起见,我建议实施Specification。您创建一个返回布尔值的规范,以查看对象是否满足特定条件。将 IUserRepository 注入规范中,检查是否已经存在具有该名称的用户,并返回布尔结果。

public interface ISpecification<T>
{
  bool IsSatisfiedBy(TEntity entity);
}

public class UniqueUsernameSpecification : ISpecification<User>
{
  private readonly IUserRepository _userRepository;

  public UniqueUsernameSpecification(IUserRepository userRepository)
  {
    _userRepository = userRepository;
  }

  public bool IsSatisfiedBy(User user)
  {
    User foundUser = _userRepository.FindUserByUsername(user.Username);
    return foundUser == null;
  }
}

//App code    
User newUser;

// ... registration stuff...

var userRepository = new UserRepository();
var uniqueUserSpec = new UniqueUsernameSpecification(userRepository);
if (uniqueUserSpec.IsSatisfiedBy(newUser))
{
  // proceed
}
于 2009-06-21T05:41:40.840 回答
2

In DDD, there ia a concept called aggregate. It is basically responsible for consistency within the application.

IMHO, in this case specifically, I guess the CustomerRepository would be inside something like the "Customer aggregate", being the Customer class the aggregate root.

The root would then be responsible for doing all this stuff, and no one else could access the CustomerRepository options. And there are some possibilities:

  • The CustomerRepository could throw an exception if the name is not unique (and the Customer would catch and return the error, or something like that)
  • The CustomerRepository could have an IsValidUserName(), that the Customer would call before doing anything else
  • Any other option you can think of
于 2009-06-15T21:15:05.217 回答
2

我要说的是,这完全超出了 DDD 的范围。

DDD 所拥有的是产生有用模型的事件聚合。然而,这些模型之间的数据关系不一定是可能的。

您使用的是什么一致性模型?

如果您可以在 ACID 事务中提交多个事件,则可以确保对一组聚合的更改以原子方式发生。

如果您使用最终一致性模型,您可能要等到以后才能真正验证这些东西。当你这样做时,你可能需要补偿那些本应发生但不再有效的事情。

必须在上下文中回答唯一性。如果您的模型很小(以千计),您可以有一个聚合表示您希望唯一的一组值。假设组聚合事务是可能的。

如果不是,那么您只需将模型投影到支持唯一性约束的数据库。如果此预测失败,您必须返回聚合并以某种方式将其标记为无效。一直以来,您都需要考虑失败。这是分布式长时间运行的过程(如 saga 模式)可能有用的地方,但也需要您考虑其他事情。

总而言之,如果您不能使用具有强一致性保证的存储模型,那么一切都会变得更加复杂。就是说,在分布式环境中管理故障有很好的彻底的模式,但它使问题变得有点头绪,因为现在您需要在沿途的每一点考虑故障,这是一件好事,但它将需要更大的时间投入。

于 2017-12-12T10:30:53.330 回答