在DDD中,是验证应用程序逻辑还是域逻辑?


26

假设我们正在使用DDD对表单进行建模;表格可能具有某种与之相关的业务规则-如果您不是学生,可能需要指定收入,如果您表示已婚,则需要列出孩子。如果您指定了一个国家,那么它应该有一个有效的国家。

这种验证是否存在于域或应用程序层中?我正在考虑的其他一些问题:

  • 某些框架(例如Laravel)提供了验证规则,可以在请求到达控制器之前验证输入。如果在该级别进行验证,是否会破坏DDD?

  • 对于确定国家/地区是否有效的情况,通常我只会查询世界上所有国家/地区的数据库表。但是,在DDD中,这可能(根据我的理解)是在域层上完成的。是否允许域层访问数据库,还是必须使用非SQL搜索来确定有效的国家/地区?

  • 是否有必要在应用程序和域层都验证输入?


6
您的问题是假设总是有一个正确的地方放置所有东西。没有。
罗伯特·哈维

1
@RobertHarvey说什么。验证应始终在模型上,而不管“应用程序”进行任何验证(不是应用程序的模型部分吗?)。“应用程序”中的任何验证应仅是模型验证的重复-以增强UI的响应性,或者应仅与“应用程序”逻辑相关(例如:“在此表单上,您只能输入”。 ..”,但我假设是实体验证)。永远不要信任用于域验证的“应用程序”层,它可能不是您的客户端发送信息……
Marjan Venema

Answers:


29

这种验证是否存在于域或应用程序层中?

应用。您想要的魔术搜索词是反腐败层

通常,您的应用程序收到的消息将具有某种DTO的风格。您的反腐败层通常会创建域将识别的值类型。分派给域模型的实际命令将以经过验证的值类型表示。

示例:DepositMoney命令可能会包括金额和货币类型。DTO表示可能会将金额表示为整数,将货币代码表示为字符串。反腐败层会将DTO转换为“存款”值类型,该类型将包括“已验证的金额”(必须为非负数)和“已验证的CurrencyCode”(必须是域中受支持的代码之一)。

成功将命令解析为域模型可以理解的类型后,该命令会在域中执行,但该命令仍会以违反业务不变性为理由(该帐户尚不存在,该帐户已被阻止,不允许该特定帐户使用该货币?等)。

换句话说,在反腐败层验证输入之后,业务验证将在域模型中进行。

验证规则的实现通常将存在于值类型的构造函数中,或存在于用于构造值类型的工厂方法中。基本上,您限制对象的构造,以确保它们是有效的,将逻辑隔离在一个位置,然后在过程边界处调用它。


为什么申请是答案?根据您的文字,形式验证可以在域或应用程序中进行,并且只能在域中进行业务验证。
inf3rno

@ inf3rno,因为专门询问有关验证与域无关的表单的问题
timetofly

1
这个答案没有道理。DDD的反腐败层是您编写的额外代码,用于与(另一个系统的)外部域模型和基于DDD的应用程序的域模型之间进行转换。如果没有这样的外部系统,则没有反腐败层。同样,验证业务规则属于域模型(和域层),而不是应用程序层。对于DTO,这是DDD应用程序中可能存在或不存在的技术组件(在应用程序层中)。在DTO与实体/值对象之间进行转换与反腐败层无关。
罗杰里奥

5

您的问题域模型包括域业务规则。业务规则是对模型元素的约束。他们的意思是,电梯不会在门打开的情况下移动,不会将易腐烂的货物装载到非冷藏集装箱中,并且不会发送已取消的订单。

这并不意味着当您的域与人互动(通过屏幕,表格等)时,就不需要验证或帮助。只是意识到它是可选的。

考虑到有两种类型的业务规则:-约束对象属性的属性规则,和约束对象之间协作的添加和删除的协作规则。

业务规则不同于逻辑规则,逻辑规则与您的编程语言相关,并检查是否提供了值并且不为null等。

注意:DDD中没有“建模”表单的概念。


0

特定状态会使模型实体无效吗?如果是,则该模型必须阻止实体进入该状态。这意味着模型必须知道如何进行自我验证。

但是有一个小问题:模型验证通常为时已晚。通常,我们希望尽早进行验证,因此用户不必等待太久。这就是为什么通常将验证放入应用程序逻辑中的原因。

至于验证的上下文:实体能够查询其他数据没有问题。但它不在乎这些数据从何而来。它不在乎它来自SQL,File还是仅是硬编码的。这就是为什么存在存储库。域定义了它需要哪种查询,并让其他人来维护实现。


-2

域层应包含所有验证逻辑。表示层,反腐败层或其他从属层应反映出这一点。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.