在哪一层应该主要在DDD的上下文中进行验证



这个问题可能会被问一千次,但答案中有很多困惑和矛盾。

我询问了领域驱动设计中的验证

  1. 验证应该主要在哪一层进行
  2. 对象处于无效状态可以接受吗?因为很多答案都说可以,主要是因为历史数据和业务规则可能会随着时间的推移而变化,加载历史数据可能会导致问题
  3. 许多实现都考虑在域层中抛出异常并将消息映射到UI,尽管Martin Fowler建议在Validations中用Notification替换抛出异常!何时返回消息,何时在验证上下文中抛出异常
  4. 许多文章在文章中解释了一些技巧或路径,比如Vladimir Khorikov和jbogard,但在评论中,他们承认自己现在的做法有点不同。这些模式仍然有效吗?

  5. 我应该使用FluentValidation这样的框架吗?如果我使用它,这个框架是否只在应用层中用作MVC annotations的替代方案?

  6. 何时应该使用Business Rule Framework (BRF)

我知道这里有很多问题,但它们针对的是同一点(DDD中的验证)。

注意:我不使用CQRS模式,因为它使应用程序非常复杂。所以我有(domain layer,data layer, application layer(MVC), and shared kernel)

验证应该主要在哪一层进行?

主要在域中,除了与基础结构相关的验证,例如xsd验证或json模式。

对象处于无效状态可以接受吗?因为很多答案是可以的,主要是因为历史数据和业务规则可能会随着时间和加载历史数据而变化可能会引起问题?

这是可以接受的,因为验证是在域中完成的,所以不应该是这样。从业务的角度来看,对象不可能处于无效的业务状态,但是,有时,就像在现实生活中一样,流程可能处于无效/临时状态。我们称之为最终一致性(https://en.wikipedia.org/wiki/Eventual_consistency),我建议你看看这个。最终,系统将处于有效状态,这就是一切,如果它暂时无效,那么维护这样的系统可能会付出更大的努力,但有时你别无选择。

许多实现都考虑在域层中抛出异常并将消息映射到UI,尽管Martin Fowler建议到在验证中用通知替换引发异常!何时返回消息以及何时在验证中引发异常上下文

我不太喜欢域层的异常,除非这显然是一个先决条件。例如,一个字段的输入太大,或者一个项目的价格为负。如果您不能构建一个有效的业务对象,那么在我看来,这是一个非常有效的异常情况。如果这是一个商业案例,那么消息是最合适的。

许多文章解释了一些技巧或路径,如VladimirKhorikov和jbogard在他们的文章中,但在评论中承认他们现在做事有点不一样。这些图案吗仍然有效?

我应该使用FluentValidation这样的框架吗?如果我使用它,这是仅在应用程序层中使用的框架,作为MVC注释?

DDD中的最佳建议是永远不要使用框架,不过Spring或JDBC可能会有所帮助,但一般来说,您应该手动完成。我们甚至手工编写了存储、应用程序服务、Oracle预测和事件总线。它更快速,更易于维护,而且您可以学到更多。Vaughn Vernon在他的书(实现领域驱动设计)中给出了非常好的例子和一个项目,你可以看看:https://github.com/VaughnVernon/IDDD_Samples(用Java编写)

何时应该使用业务规则框架(BRF)?

同样,不要使用框架

实际上有几种不同的活动可能被称为"验证",它们的处理方式都有所不同。

消息验证通常发生在我们所能管理的边界附近。当我收到HTTP请求时,我将验证请求本身是否格式正确,元数据中是否指定了正确的媒体类型,请求主体是否可以干净地处理,生成的DOM是否具有所有必需的字段,已知的数据节点是否都是适当的类型,存在的值是否在允许的范围内,在我担心域模型的当前状态之前。

通常,这种验证的形式是将消息中的数据转换为域中的值对象图;这通常看起来像工厂或构建者,他们知道如何采用与域无关的值类型并将其转换为特定于域的值。域模型通常不知道消息格式,也不知道序列化(JSON通常不是域问题)。

从持久存储读取值时也有类似的关注点分离——值工厂知道如何从基元创建值,但不一定知道JSON或结果集等

"业务逻辑"通常存在于域模型中,它验证给定消息在给定域的当前状态下是否有意义。

对象处于无效状态可以接受吗?

对象处于无效状态是不可接受的。

但也有一些有效的状态是不可访问的。负账户余额正成为公司的一项重大负债,因此引入了一项新的业务规则,防止导致负余额的提款。这并不能改变鲍勃账户余额为负的事实。它仍然是一个有效的状态,只是新规则无法访问的状态。

何时返回消息,何时在验证上下文中抛出异常?

不要使用异常来实施应急管理。

您的问题有直接的答案。所以我在没有背景的情况下给出了答案。

验证应该主要在哪一层进行?

服务器端和客户端都提供更准确、更安全的应用程序。无论设计背景如何。对于服务器端,您可以采用不同的方式,如fluent验证或数据注释(模型),或者使用集成库(如jquery unsobstruct ajax)将它们带到客户端服务器端验证更为重要,因为需要验证CRUD操作以避免异常等。。。。就您的问题而言,图层是视图和模型(数据访问)。

对象处于无效状态可以接受吗?因为很多答案是可以的,主要是因为历史数据和业务规则可能会随着时间和加载历史数据而变化可能会引起问题?

当您在数据库中显示或处理数据存储时,所需依赖项的可接受、必填字段或空值会引发错误。在这里,没有谈论可能随着时间的推移而发生的变化。我们现在才考虑。我们使用模式和编程规则来创建灵活性/可维护性。验证和条目依赖关系可以随着时间的推移而更改。

许多实现都考虑在域层中抛出异常并将消息映射到UI,尽管Martin Fowler建议到在验证中用通知替换引发异常!何时返回消息以及何时在验证中引发异常上下文

在客户端显示异常对于开发日或向相应用户通知阻止更改/存储数据的错误是一种很好的技术考虑到:有些系统确实没有向最终用户显示额外信息的策略。一些报告可能会使应用程序更容易受到入侵。这完全基于您正在开发的软件类型。一个好的做法是在客户端显示一个简单的错误,并将错误日志存储在服务器中(包含全面的详细信息)。

许多文章解释了一些技巧或路径,如VladimirKhorikov和jbogard在他们的文章中,但在评论中承认他们现在做事有点不一样。这些图案吗仍然有效?

有些人可能有自己命名的个人架构。但其中一些是官方的并被广泛使用,如工作单元存储库模式,它们为著名的模式(MVC)添加了一些层,以实现更准确、干净和可维护的代码/应用程序。遵循任何模式背后的主要目的。

我应该使用FluentValidation这样的框架吗?如果我使用它,这是仅在应用程序层中使用的框架,作为MVC注释?我应该何时使用业务规则框架(BRF)相反

FluentValidationDataAnnotations的替代方案,类似于FLUEtAPI。请注意,两者都用于为属于已定义类(数据库表)的属性定义规则。有一个名为ViewModel的概念,它包含主模型类(表)的转换(有一些更改),主要针对前端的验证。您可以在一个项目中同时使用这两种方法,将每个模型映射到其ViewModel,反之亦然。如果您使用的是存储库模式,比如说,有一个数据访问层,那么一些验证就在这个层中。如果您使用的是ViewModel,那么它位于应用程序层内部。但是,作为一个建议,这些都毫无价值。关键的成功在于理解任何技术/架构/模式背后的主要目的。你可以找到大量关于它们的文章,并专注于目的,然后你可以决定做什么来拥有一个更干净/标准/可维护/灵活的/等等。。。密码

最后提示:增加模块性会增加集成成本(软件成本),尽管会降低每个模块的成本。为你的项目使用适度的设计。组合体系结构有时不仅不是一个好主意,还会增加成本和开发难度。软件设计基础中的更多细节

最新更新