Domain driven design Domen驱动的体系结构和用户输入错误

Domain driven design Domen驱动的体系结构和用户输入错误,domain-driven-design,encapsulation,setter,Domain Driven Design,Encapsulation,Setter,DDD教我们像真实世界的原型一样构建我们的类 所以不要使用setter job = new Job job.person = person job.since = time.Now() job.title = title 我们在聚合根中定义了命名良好的方法 job = person.promote(title, /** since=time.Now() **/) 现在是棘手的部分 假设我们有一个人力资源用户界面,他/她通过HTML表单输入一个新的标题,并做出类似“prgrammer”的打字错

DDD教我们像真实世界的原型一样构建我们的类

所以不要使用setter

job = new Job
job.person = person
job.since = time.Now()
job.title = title
我们在聚合根中定义了命名良好的方法

job = person.promote(title, /** since=time.Now() **/)
现在是棘手的部分

假设我们有一个人力资源用户界面,他/她通过HTML表单输入一个新的
标题
,并做出类似“prgrammer”的打字错误(当然在实际应用中会有一个选择列表,但这里有一个文本输入),或者选择了一个错误的日期(比如今天的默认值)

现在我们有一个问题。现实世界中没有打字错误。我们的无名氏绝对是一个“程序员”,而不是一个“程序员”

我们如何在我们的域模型中修复这个输入错误

我们的
人员
提升
降级
解雇
等方法,它们反映了人力资源领域模型

我们可以作弊一点,直接更改
作业
记录,但现在我们有了
作业。setTitle
方法,它不反映我们的域模型,而且,setter是邪恶的,你知道


这看起来有点“学术性”,但当我试图为一个复杂的应用程序构建一个好的领域模型时,这真的让我很烦。当你试图打破这个不变量(某些规则)时,你必须停止执行,并大声说出这个(抛出异常)。所以,您需要有一个有效标题的列表,当您试图将标题(无论如何)更改为无效状态时,您必须抛出一些有用的异常

要“修复”打字错误,您必须将域中的操作分开
promote
是一个操作(它可能会检查某些内容,发送反对电子邮件:)等等)。和
edit
操作-仅编辑某些属性。所以,不同之处在于操作逻辑。如果没有一些先决条件(例如,工人的必要经验),您不能调用
promote
,但您可以调用
edit
并修复工人的姓名,因为类型不同。 通常,这些操作在不同的用户之间是分开的:只有人力资源部可以
提升
,但是员工可以
编辑
他的名字,如果名字不对的话。 对于这样的例子,这个解决方案非常复杂,但它总是使用DDD。 主要概念-单独操作。每个人都有自己的条件、权限和规则


关于不变量(规则)。

如果客户机纯粹是在输入数据,那么此(有界)上下文中的基础域不是很深。在这些情况下,可以使用CRUD样式的应用程序并允许更改标题(
setTitle()


只要确保不存在“无效数据”这类情况的依赖BCs(例如,账单、假期计划等)能够对CRUD上下文中的更改做出适当的反应。

应用程序应在到达域层之前强制执行输入正确性,无垃圾输入。如果这意味着使用下拉菜单的职位名称,那么就这样吧。您可以根据现有标题验证标题

我的公司有1.8万名员工,打字错误时有发生。对此,您必须实事求是,并接受代码中会有setter(以某种方式)

实用主义思维是领域驱动设计的核心,也是保持事物简单化的关键

“纯度在理论上是好的,但在实践中很难实现,有时你必须选择务实的方法”-《领域驱动设计的模式、原则和实践》(2015)

“现实世界中没有拼写错误”,我明白你的意思,但那不是真的,现实世界中存在人为错误,如果这些错误经常发生,则应在您的领域中加以说明

如果数据输入错误不频繁,那么额外的建模工作可能就不值得了,这些错误可能直接在数据库中得到修复。这还取决于企业是否希望了解这些错误

但是,如果数据输入错误频繁出现,这可能表明系统可能没有提供足够的指导,业务部门可能希望了解更多关于这些错误的信息,以便使流程更高效、更不容易出错

您可能希望在专用于数据更正的BC中实现一个操作,例如
job.correctTitle(…)
?而且,很可能很少见的是,每一条信息都是错误的,因此可以将纠正操作分离开来。这意味着您可能不需要
作业。更正信息(…)
类操作


这整个场景都是虚构的,因为职务头衔通常会在一个单独的BC中管理,而不是在使用它们的地方,并且它们可能会从列表中选择,因此拼写错误的频率会降低,但您必须始终处理数据输入错误。选择合适的解决方案并不总是容易的,而且会因情况而异,但要尽量保持务实,不要在你的领域的每个领域都追求完美的模式。

这是一个非常好的问题,并延伸到其他打字错误/错误,比如无意中输入了错误的日期等等,但当人力资源人员从有效标题列表中选择了错误的标题时会发生什么?@AlexanderLanger HTML只是一个视图,它可以有另一个模型(ViewModel),理论上用户(或违反安全性)可以选择错误的值,但是当您尝试将此值设置为您的实体时,您必须抛出异常。最好的方法-不允许选择错误的值(尤其是您有正确的列表标题来验证实体)是的,这适用于预定义的标题列表。但是人们的名字呢?您不能有完整的姓名列表,或者Sam和Pam都是有效姓名,但其中一个可能是typo@dmzkrskddd不能保护您免受打字错误。因为,只有用户知道什么是正确的Sam或Pam。这是一个关于质量控制的问题,不是ddd,我认为这个问题不是关于防止打字错误,而是关于在ddd中修复打字错误