我应该从抽象领域层验证框架? [英] Should I abstract the validation framework from Domain layer?

查看:128
本文介绍了我应该从抽象领域层验证框架?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用FluentValidation来验证我的服务操作。我的code如下:

I am using FluentValidation to validate my service operations. My code looks like:

using FluentValidation;

IUserService
{
    void Add(User user);
}

UserService : IUserService
{
    public void Add(User user)
    {
       new UserValidator().ValidateAndThrow(user);
       userRepository.Save(user);
    }
} 

UserValidator实现FluentValidation.AbstractValidator。

UserValidator implements FluentValidation.AbstractValidator.

DDD说,领域层必须是技术自主。

DDD says that domain layer have to be technology independent.

我在做什么是使用验证框架,而不是自定义异常的。

What I am doing is using a validation framework instead of custom exceptions.

这是一个糟糕的主意,把验证框架领域层?

It's a bad idea to put validation framework in the domain layer?

推荐答案

好吧,我看到你的设计的几个问题,即使你通过声明 IUserValidator 接口从框架保护您的域名。

Just like the repository abstraction?

Well, I see a few problems with your design even if you shield your domain from the framework by declaring an IUserValidator interface.

起初,好像如果这将导致相同的抽象战略作为存储库等基础设施的担忧,但有一个在我看来是个巨大的差异。

At first, it seems like if that would lead to the same abstraction strategy as for the Repository and other infrastructure concerns, but there's a huge difference in my opinion.

在使用 repository.save(...),你其实根本不从域中的角度实施的关心,因为怎么坚持的东西是不是域的关注。

When using repository.save(...), you actually do not care at all of the implementation from the domain perspective, because how to persist things is not a domain concern.

然而,不变的执法域的关注和你不应该有钻研基础设施的详细信息(即 UserValidtor 现在可以看到这样),看看它们是由什么和这基本上你到底是什么了做,如果你做了这条道路,因为这些规则将在框架方面pssed前$ p $和生活会外域。

However, invariant enforcement is a domain concern and you shouldn't have to dig into infrastructure details (the UserValidtor can now be seen as such) to see what they consist of and that's basically what you will end up doing if you do down that path since the rules would be expressed in the framework terms and would live outside the domain.

为什么会住在外面?

domain -> IUserRepository
infrastructure -> HibernateUserRepository

domain -> IUserValidator
infrastructure -> FluentUserValidator

始终处于有效的实体

或许有你的设计更根本的问题,那你甚至不能问这个问题,如果你坚持的,虽然那所学校:始终保持有效的实体

Always-valid entities

Perhaps there's a more fundamental issue with your design and that you wouldn't even be asking that question if you adhered to that school of though: always-valid entities.

从这个角度看,不变执法域实体本身的责任,因此甚至不应该能够不被有效存在。因此,不变的规则是,这些受到侵犯时pssed合同和异常只是前$ P $抛出。

From that point of view, invariant enforcement is the responsibility of the domain entity itself and therefore shouldn't even be able to exist without being valid. Therefore, invariant rules are simply expressed as contracts and exceptions are thrown when these are violated.

这背后的原因是,很多错误都来自一个事实,即对象是他们应该永远都没有的状态。要公开我从Greg Young的读取一个例子:

The reasoning behind this is that a lot of bugs comes from the fact that objects are in a state they should never have been. To expose an example I've read from Greg Young:

让我们提出,我们现在有一个 SendUserCreationEmailService ,需要一个
  用户配置 ...我们如何能够在服务,名称理顺
  没有?难道我们再检查吗?或者更可能的......你就是不
  不屑于为最好的希望检查,你希望有人打扰
  它发送给你之​​前验证它。当然,使用的TDD 1
  我们应该写的第一个测试是,如果我送与客户
  它应该引发错误名称。但是,一旦我们开始写
  这些类型的测试一遍又一遍,我们认识......等,如果我们
  决不允许的名字变成空,我们不会有所有这些测试的 - Greg Young的关于<一个评论href=\"http://jeffreypalermo.com/blog/the-fallacy-of-the-always-valid-entity/\">http://jeffreypalermo.com/blog/the-fallacy-of-the-always-valid-entity/

Let's propose we now have a SendUserCreationEmailService that takes a UserProfile ... how can we rationalize in that service that Name is not null? Do we check it again? Or more likely ... you just don't bother to check and "hope for the best" you hope that someone bothered to validate it before sending it to you. Of course using TDD one of the first tests we should be writing is that if I send a customer with a null name that it should raise an error. But once we start writing these kinds of tests over and over again we realize ... "wait if we never allowed name to become null we wouldn't have all of these tests" - Greg Young commenting on http://jeffreypalermo.com/blog/the-fallacy-of-the-always-valid-entity/

现在不要误会我的意思,显然你不能强制执行的所有验证规则一样,因为有些规则是特定于某些业务操作禁止这种做法(例如,保存一个实体的副本草案),但这些规则并不是要查看的方式一样不变的执法,这是规则适用于每一个场景(例如,一个客户必须有一个名称)。

Now don't get me wrong, obviously you cannot enforce all validation rules that way, since some rules are specific to certain business operations which prohibits that approach (e.g. saving draft copies of an entity), but these rules aren't to be viewed the same way as invariant enforcement, which are rules that applies in every scenarios (e.g. a customer must have a name).

如果我们现在看看你的code和尝试应用始终有效的方法,我们清楚地看到 UserValidator 对象没有它的位置。

If we now look at your code and try to apply the always-valid approach, we clearly see that the UserValidator object doesn't have it's place.

UserService : IUserService
{
    public void Add(User user)
    {
       //We couldn't even make it that far with an invalid User
       new UserValidator().ValidateAndThrow(user);
       userRepository.Save(user);
    }
}

因此​​,有一个为FluentValidation在此时域没有地方。如果仍然不服气,问自己你将如何整合的值对象?你将有一个 UsernameValidator 来验证用户名值对象每次它的实例化?很显然,这并没有任何意义和使用价值的对象将是相当困难与非始终有效的方法结合起来。

Therefore, there's no place for FluentValidation in the domain at this point. If you still aren't convinced, ask yourself how you would integrate value objects? Will you have a UsernameValidator to validate a Username value object everytime it's instanciated? Clearly, that doesn't make any sense and the use of value objects would be quite hard to integrate with the non always-valid approach.

这实际上是东西我挣扎,我一直在问我自己一段时间(我还没有完全相信什么,我会说)。

That's actually something I struggled with and I've been asking that myself for a while (and I'm still not entirely convinced about what I'll be saying).

基本上,我终于明白的是,它不是域的职责是收集和返回错误,这是一个用户界面问题。如果无效的数据使得它的方式到域,它只是抛出你。

Basically, what I've come to understand is that it isn't the job of the domain to collect and return errors, that's a UI concern. If invalid data make it's way up to the domain, it just throws on you.

因此​​,像FluentValidation框架会发现他们在UI自然家园,将验证视图模型,而不是领域实体。

Therefore, frameworks like FluentValidation will find their natural home in the UI and will be validating view models rather than domain entities.

我知道,这似乎很难接受会有一些重复的水平,但是这主要是因为你可能是一个全栈的开发像我这样的UI和域的时候,其实那些可以而且应该涉及可能会被看作是完全不同的项目。此外,就像视图模型和领域模型,视图模型验证和域验证可能是类似的,但服务于不同的目的。

I know, that seems hard to accept that there will be some level of duplication, but this is mainly because you are probably a full-stack developer like me that deals with the UI and the domain when in fact those can and should probably be viewed as entirely different projects. Also, just like the view model and the domain model, view model validation and domain validation might be similar but serves a different purpose.

另外,如果你还是担心是干的,有人曾经告诉我,code再利用也是耦合,我认为这其实是特别重要的位置。

Also, if you're still concerned about being DRY, someone once told me that code reuse is also "coupling" and I think that fact is particularly important here.

我不会在这里再解释这些,但也有不同的方法来处理域中递延验证,如规范模式和的递延由Ward Cunningham在他的检查模式语言描述的验证方法。如果您有由沃恩弗农的实施领域驱动设计的书,你也可以从208-215页读取。

I will not re-explain those here, but there are various approaches to deal with deferred validations in the domain such as the Specification pattern and the Deferred Validation approach described by Ward Cunningham in his Checks pattern language. If you have the Implementing Domain-Driven Design book by Vaughn Vernon, you can also read from pages 208-215.

验证是一个极其困难主体和证明的是,今天的人们仍然不应该怎么做达成一致。有这么多的因素,但在年底,你想要的是一个解决方案,即实用,易于维护和前pressive。你不能永远是一个纯粹的,而且必须接受这样的事实,有些规则将被打破(例如你可能有泄漏,以使用您选择的ORM在实体的一些不显眼的持久性细节)。

Validation is an extremely hard subject and the proof is that as of today people still don't agree on how it should be done. There are so many factors, but at the end what you want is a solution that is practical, maintainable and expressive. You cannot always be a purist and must accept the fact that some rules will be broken (e.g you might have to leak some unobtrusive persistence details in an entity in order to use your ORM of choice).

因此​​,如果你认为你可以用一个事实,即有些FluentValidation细节使它成为您的域名,它是更实际的这样的生活,以及我真的不能告诉它是否会做更多的伤害比长好运行,但我不会。

Therefore, if you think that you can live with the fact that some FluentValidation details makes it to your domain and that it's more practical like that, well I can't really tell if it will do more harm than good in the long run but I wouldn't.

这篇关于我应该从抽象领域层验证框架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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