DDD领域模型复杂的验证 [英] DDD Domain Model Complex Validation

查看:209
本文介绍了DDD领域模型复杂的验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的工作使用领域驱动设计坚持的原则重写我的ASP.NET MVC应用程序。我想验证我的用户实体。到目前为止,我能够验证基本规则(如用户名和密码是一个非空/空白字符串)。但是规则之一,我需要确保用户名是独一无二的。不过,我需要访问数据库序要做到这一点,这意味着我将不得不注入我IUserRepository到我的用户的实体像这样。

 公共类用户
{
    私人只读IUserRepository _userRepository;
    公共用户(IUserRepository回购)
    {
        _userRepository =回购;
    }    公共覆盖无效的validate()
    {
        //基本验证code
        如果(string.IsNullOrEmpty(用户名))
            抛出新ValidationException(用户名不能为空或空格字符);
        如果(string.IsNullOrEmpty(密码))
            抛出新ValidationException(密码不能为空或空格字符);        //复杂的验证code
        VAR用户= _userRepository.GetUserByUsername(用户名);
        如果(用户= NULL和放大器;!&安培;!USER.ID = ID)
            抛出新ValidationException(用户名必须是唯一的)
    }
}

不过,这似乎......好错了。让我的实体依赖于我的仓库似乎是一个坏主意(纠正我,如果我错了)。但其在实体验证code是有道理的。哪里是把复杂的验证code的最佳地点?


解决方案

  

不过,这似乎......好错了。让我的实体依赖于我的仓库似乎是一个坏主意(纠正我,如果我错了)。


在一般情况下,在存储库依赖性不是'错误',有时不可避免的。不过,我认为它应该是一个例外,应该避免尽可能。在你的情况,你可能会重新考虑有这种依赖性。如果你想想看,'独特性'不是实体本身的责任,因为实体不知道其他实体。那么,为什么有实体强制执行这个规则?


  

但其在实体验证code是有道理的。哪里是把复杂的验证code的最佳地点?


我觉得你可能会overgeneralizing'验证'。我想摆脱'验证'方法,并会确保该对象不进入无效状态摆在首位。我几个月前回答类似的问题。

现在回到了独特的规则。我认为这是的例子,DDD泄漏了一下,从某种意义上说,此业务规则的执行不能在域code纯粹pssed前$ P $之一。我想接近它是这样的:

  //库
接口用户{
  //实施关系DB的情况下,执行SQL COUNT
  布尔IsNameUnique(字符串名称);  //实现将调用IsNameUnique如果失败抛
  无效添加(用户用户);
}

客户端code会知道添加新用户之前,应明确检查的唯一性,否则会崩溃。这种组合强制域中code业务规则,但它通常是不够的。作为一个附加的执行层,你可能需要添加UNIQUE约束在数据库或使用显式锁定。

I am working on rewriting my ASP.NET MVC app using the domain driven design priciples. I am trying to validate my User entity. So far I am able to validate basic rules (like the username and password being a non null/whitespace string). However one of the rules, I need to make sure that the username is unique. However I need access to the database inorder to do this, which means I would have to inject my IUserRepository into my User entity like so.

public class User
{
    private readonly IUserRepository _userRepository;
    public User(IUserRepository repo)
    {
        _userRepository = repo;
    }

    public override void Validate()
    {
        //Basic validation code
        if (string.IsNullOrEmpty(Username))
            throw new ValidationException("Username can not be a null or whitespace characters");
        if (string.IsNullOrEmpty(Password))
            throw new ValidationException("Password can not be a null or whitespace characters");

        //Complex validation code
        var user = _userRepository.GetUserByUsername(Username);
        if (user != null && user.id != id)
            throw new ValidationException("Username must be unique")
    }
}

However this seems ... well wrong. Making my entity depend on my repository seems like a bad idea (correct me if I am wrong). But having the validation code in the entity makes sense. Where is the best place to put complex validation code?

解决方案

However this seems ... well wrong. Making my entity depend on my repository seems like a bad idea (correct me if I am wrong).

In general, dependency on repository is not 'wrong', it is sometimes unavoidable. However I think it should be an exception and should be avoided as much as possible. In your scenario you may reconsider having this dependency. If you think about it, 'uniqueness' is not a responsibility of the entity itself because entity does not know about other entities. So why having entity enforce this rule?

But having the validation code in the entity makes sense. Where is the best place to put complex validation code?

I think that you may be overgeneralizing 'validation'. I would get rid of the 'Validate' method and will make sure that the object does not get into 'invalid' state in the first place. I answered similar question few months ago.

Now back to the uniqueness rule. I think that this is one of the examples where DDD 'leaks' a bit, in a sense that the enforcement of this business rule can not be expressed purely in domain code. I would approach it like this:

// repository
interface Users {
  // implementation executes SQL COUNT in case of relation DB
  bool IsNameUnique(String name);

  // implementation will call IsNameUnique and throw if it fails
  void Add(User user);
}

The client code would know that before adding a new user, it should explicitly check for uniqueness, otherwise it will crash. This combination enforces business rule in the domain code, but it is usually not enough. As an additional enforcement layer you may want to add UNIQUE constraint in the database or employ explicit locking.

这篇关于DDD领域模型复杂的验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆