DDD 教我们像真实世界的原型(prototype)一样构建我们的类。
所以不要使用setter
job = new Job
job.person = person
job.since = time.Now()
job.title = title
我们在聚合根中定义了命名良好的方法
job = person.promote(title, /** since=time.Now() **/)
现在棘手的部分
假设我们有一个 HR 的 UI,他/她在其中输入一个新的
title
通过 HTML 表单并输入“prgrammer”之类的错字(当然在实际应用中会有一个选择列表,但这里我们有一个文本输入),或者选择了错误的日期(如今天的默认值)现在我们有一个问题。现实世界中没有错别字。我们的 John Doe 绝对是一个“程序员”,而不是一个“prgrammer”
我们如何在我们的领域模型中修复这个错字?
我们的
Person
刚刚promote
, demote
, fire
等方法,体现了HR领域模型。我们可以稍微作弊并更改
Job
直接记录,但现在我们有一个Job.setTitle
方法,这不反射(reflect)我们的领域模型,而且,setter 是邪恶的,你知道的。这可能看起来有点“学术”,但是当我尝试为复杂的应用程序构建一个好的域模型时,这真的让我很烦恼
最佳答案
DDD 的另一面是不变量——“always valid”实体。当你试图打破这个不变量(某些规则)时,你必须停止执行并“大声”地说出这个(抛出异常)。因此,您需要有一个有效标题列表,并且当您尝试将标题(不管如何)更改为无效状态时,您必须抛出一些有用的异常。
要“修复”错字情况,您必须将域中的操作分开 promote
是一项操作(它可能会检查某些内容,发送通知电子邮件:) 等等)。和edit
操作 - 只是为了编辑一些属性。因此,区别在于操作逻辑。您不能调用promote
没有一些先决条件(例如,要求 worker 的经验),但您可以调用edit
并根据类型修复 worker 的姓名。
而且通常这些操作在不同的用户之间是分开的:只有 HR 可以 promote
但是 worker 可以edit
他的名字,如果它是错误的。
对于此类示例,此解决方案非常复杂,但始终使用 DDD。
主要概念 - 单独操作。每一个都有自己的条件、权限、规则。
一个 question关于不变量(规则)。
关于domain-driven-design - Domen 驱动的架构和用户拼写错误/错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32002962/