这个问题可能被问过一千遍,但是答案中却有很多困惑和矛盾。
我询问有关域驱动设计的验证。
许多文章在其文章中解释了一些提示或路径,例如Vladimir Khorikov和jbogard,但在评论中他们承认,现在的做法有所不同。这些模式仍然有效吗?
我应该使用FluentValidation之类的框架吗?如果使用它,此框架是否仅在应用程序层中用作MVC annotations
的替代品?
Business Rule Framework (BRF)
?我在这里知道很多问题,但它们针对的是同一地点(DDD中的验证)。
注意:我不使用CQRS
模式,因为它使应用程序变得如此复杂。
所以我有(domain layer,data layer, application layer(MVC), and shared kernel)
答案 0 :(得分:3)
主要应在哪一层进行验证?
主要在域中,但与基础架构相关的验证除外,例如例如xsd验证或json模式。
对象处于无效状态是否可以接受?因为很多 回答说还可以,主要是因为历史数据和 业务规则可能会随时间变化并加载历史数据 可能会引起问题?
这是可以接受的,因为验证不是在域中完成的。从业务的角度来看,对象不能处于无效的业务状态,但是有时,就像在现实生活中一样,流程可能处于无效/临时的状态。我们称其为最终一致性(https://en.wikipedia.org/wiki/Eventual_consistency),建议您对此进行一下了解。最后,系统将处于有效状态,这很重要,如果它暂时无效,那么维护此类系统的工作可能会更大,但有时您别无选择。
许多实现都考虑在域层中引发异常 并将消息映射到UI,尽管Martin Fowler建议 用验证中的通知替换抛出异常! 何时返回消息以及何时在验证中引发异常 上下文?
我不是领域层异常的忠实拥护者,除非这显然是先决条件。例如,对于字段而言输入太大,或者某项商品的价格为负数。如果您不能构建有效的业务对象,那么我认为这是一个非常有效的例外情况。如果这是业务案例,则最适合发送消息。
许多文章都解释了一些提示或方法,例如弗拉基米尔(Vladimir) Khorikov和jbogard在他们的文章中但在评论中, 坦白说,他们现在做事不一样了。这些模式是 仍然有效吗?
我应该使用FluentValidation这样的框架吗?如果使用它,这是 框架仅在应用程序层中用作替代 MVC批注?
DDD中的最佳建议是永远不要使用框架,但是Spring或JDBC可能会有所帮助,但是总的来说,您应该手工完成。我们甚至手工编写了商店,应用程序服务以及Oracle预测和事件总线。它更快,更易维护,您会学到更多。沃恩·弗农(Vaughn Vernon)在他的《实现域驱动的设计》一书中提供了很好的示例和一个项目,您可以查看:https://github.com/VaughnVernon/IDDD_Samples(用Java编写)
何时应改为使用业务规则框架(BRF)?
再次,不要使用框架
答案 1 :(得分:2)
实际上有几种不同的活动可以称为“验证”,它们的处理方式有所不同。
消息验证通常发生在我们可以管理的边界附近。当我收到HTTP请求时,我将验证请求本身的格式是否正确,是否在元数据中指定了正确的媒体类型,是否可以对请求主体进行干净处理,所产生的DOM是否具有所有在我担心域模型的当前状态之前,所有必填字段,即已知数据节点都是适当的类型,存在的值在允许的范围内。
通常,这种验证采取将消息中的数据转换为域中的值对象图的形式;通常看起来像工厂或构建者,他们知道如何获取域不可知的值类型并将其转换为特定于域的值。域模型通常对消息格式一无所知,并且对序列化一无所知(JSON通常不是域关注的问题)。
从持久性存储中读取值时,存在类似的关注点分离-值工厂将知道如何从基元创建值,但不一定了解有关JSON或结果集的任何信息。
“业务逻辑”通常用于域模型中,该逻辑用于验证给定消息鉴于域的当前状态是否有意义。
对象处于无效状态是否可以接受?
对象处于无效状态永远是不可接受的。
但是存在不能可达的有效状态。负帐户余额正成为公司的重要负债,因此引入了新的业务规则,该规则可防止可能导致负余额的取款。但这并没有改变鲍勃的帐户余额为负的事实。它仍然是有效状态,只是新规则无法达到的状态。
何时返回消息以及何时在验证上下文中引发异常?
请勿使用异常来实施应急管理。
答案 2 :(得分:2)
对于您的问题有直接的答案。所以我没有背景就回答了。
主要应在哪一层进行验证?
服务器端和客户端都可以提供更准确和安全的应用程序。不论设计环境如何。对于服务器端,您可以采用不同的方法,例如流畅的验证或数据注释(模型),或通过集成库(如jquery-unobtrusive-ajax)将其带到客户端。 服务器端验证更为重要,因为需要对CRUD操作进行验证以避免异常等。 就您的问题而言,层是视图和模型(数据访问)。
对象处于无效状态是否可以接受?因为很多 回答说还可以,主要是因为历史数据和 业务规则可能会随时间变化并加载历史数据 可能会引起问题?
当您显示或处理数据库中的数据存储时,可接受的必需字段或必需依赖项的空值会引发错误。在这里,没有谈论随着时间的推移而发生的变化。我们现在才考虑。我们采用模式和编程规则来创建灵活性/可维护性。验证和条目依赖关系可以随时间更改。
许多实现都考虑在域层中引发异常 并将消息映射到UI,尽管Martin Fowler建议 用验证中的通知替换抛出异常! 何时返回消息以及何时在验证中引发异常 上下文?
在开发日中,在客户端显示异常是一种不错的技术,也可以通知相应的用户有关错误的信息,该错误会导致数据无法更改/存储。 考虑:某些系统确实没有策略向最终用户显示其他信息。一些报告会使该应用更容易受到入侵。这完全基于您正在开发的软件类型。一个好的做法是在客户端显示一个简单的错误,并将错误日志存储在服务器内部(具有全面的详细信息)。
许多文章都解释了一些提示或方法,例如弗拉基米尔(Vladimir) Khorikov和jbogard在他们的文章中但在评论中, 坦白说,他们现在做事不一样了。这些模式是 仍然有效吗?
某些人可能拥有带有自己命名的个人架构。但是其中有些是官方的,并且被广泛使用,例如工作单元或存储库模式,它们为著名的模式(MVC)添加了一些层,以实现更准确,清洁和可维护的代码/应用。遵循任何模式背后的主要目的。
我应该使用FluentValidation这样的框架吗?如果使用它,这是 框架仅在应用程序层中用作替代 MVC注释?什么时候应该使用业务规则框架(BRF) 代替?
FluentValidation 是 DataAnnotations 的替代方法,其作用类似于 FluentAPI 。请注意,两者都用于定义属于已定义类(数据库表)的属性的规则。有一个名为 ViewModel 的概念,其中包含对Main Model类(表)的转换(有些更改),主要针对前端的验证。您可以将两者同时用于一个项目,将每个模型映射到其ViewModel,反之亦然。如果您使用的是存储库模式,比如说有一个数据访问层,那么一些验证就在该层内部。如果您使用的是ViewModel,则它位于应用程序层内。但是,作为建议,这些都是毫无价值的。成功的关键在于了解任何技术/体系结构/模式背后的主要目的。您可以在它们周围找到大量文章,并专注于目标,然后可以决定要做什么以拥有更干净/标准/可维护/灵活/等...的代码。
和最终提示:增加模块化会增加集成成本(软件成本),尽管会降低每个模块的成本。为您的项目使用适度的设计。有时,将架构进行组合不仅不是一个好主意,而且还会增加成本和开发难度。在software design basics
中有更多详细信息