【问题标题】:DDD - Entity's repository dependent validationsDDD - 实体的存储库相关验证
【发布时间】:2014-08-29 16:19:34
【问题描述】:

我很难找出实现依赖于数据库中存储的数据的业务规则验证的最佳方法。在下面的简化示例中,我想确保 Username 属性是唯一的。

public class User() {
    public int Id { get; set; }
    public string Name { get; set; }
    public string Username { get; set; }
    public string Password { get; set; }
    public string GenerateRandomPassword() {

    }
}

public interface IUserRepository : IRepository<User>
{
    bool UsernameTaken(string username);
}

public interface IUnitOfWork : IDisposable
{
    void Commit();
    IUserRepository Users { get; }
}

我已经阅读了很多关于实现该目标的不同方法的资料,包括将存储库注入实体(并防止它进入无效状态)、创建扩展方法等。

但我认为这些都不是最好的方法。

所以我决定使用应用程序服务来编排使用规范的实体验证。

public class CreateUserService : ICreateUserService
{
    private readonly IUnitOfWork _uow;

    public CreateUserService(IUnitOfWork uow)
    {
        _uow = uow;
    }

    public User Create(User user)
    {
        var usernameAvailableSpecification = new UsernameAvailableSpecification(_uow.Users);

        if (!usernameAvailableSpecification.IsSatisfiedBy(user))
        {
            throw new ValidationException("Username already taken");
        }

        user.GenerateRandomPassword();

        _uow.Users.Store(user);
        _uow.Commit();

        return user;
    }
}

起初,它看起来不错。但是单元测试有点困难,因为服务与规范实现紧密耦合,并且必须手动处理规范的依赖关系。我也想过抽象规范,但我不确定我是否是正确的路径。

也有可能我开始错了,因为实际上我正在学习 DDD,但我仍然不清楚应该由哪一层来负责这种验证。

任何帮助将不胜感激。

【问题讨论】:

    标签: validation domain-driven-design ddd-repositories ddd-service


    【解决方案1】:

    这几乎就是我建模它的方式,除了我会将CreateUserService 设为域服务(并在单独的应用程序服务中处理工作单元)。使用这种方法,我不会太害怕域服务和规范之间的紧密耦合,因为用户名唯一性似乎是源自实际业务域的业务规则(这里是“用户和身份验证”有界上下文) .

    如果你仍然害怕CreateUserService和规范之间的紧密耦合,你确实可以进一步抽象规范。似乎是合法的,但请记住 YAGNI 原则。

    【讨论】:

    • 感谢您的回答。我已经尝试过您建议的方法并取得了成功。另外,我接受它作为答案。再次感谢您。
    猜你喜欢
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    • 2010-11-24
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 2012-03-10
    • 1970-01-01
    相关资源
    最近更新 更多