聚合 - 正确使用(DDD)

时间:2015-04-05 19:20:55

标签: oop domain-driven-design

我一直在尝试开始使用域驱动设计(DDD),因此我已经研究了一段时间了。我有一个问题,我寻求帮助,如何以DDD方式解决它。

我有一个 Client 类,其中包含很多属性 - 其中一些是简单的属性,例如 string contactName ,而其他属性是复杂的,例如列出地址,列出网站等

DDD主张客户端应该是一个实体,它也应该是一个聚合根 - 也就是说,客户端代码应该只操纵 Client 对象本身及它;直到 Client 对象,对其内部对象(地址,网站,名称等)执行操作。

这就是我感到困惑的地方:

应用程序中有大量依赖于 Client 的内部对象的业务规则 - 例如:

  1. 根据客户的出生国或居民身份及其地址,可能会适用某些FATCA(美国法规)限制。
  2. 我需要使用来自其他系统的数据来丰富一些内部对象,这些数据既包括我的组织内部也包括外部系统。
  3. 应用程序必须决定是否允许 Client 执行操作,为此,应用程序需要仔细检查大量客户端详细信息并做出决定 - 同时,应用程序会仔细检查客户端它需要更新其许多属性,以跟踪导致应用程序做出决定的原因。
  4. 我可以在这里列出数百条规则 - 但你明白了。我的观点是,我需要更新许多 Client 的内部属性。从域的角度来看,根是客户端 - 它是用户在GUI中搜索的客户端。用户只关心客户端作为一个整体。比如说,孤立的地址毫无意义 - 只有当它是客户端的一部分时才存在。
  5. 说了这么多,我的问题是:

    Eric Evans说根本可以返回对内部对象的瞬态引用,最好是VO(这里是关键字:VO) - 但内部对象的任何操作都应该由root本身执行。

    我需要在我的客户端执行数百次操作 - 如果我将它们全部移动到根目录,根将变得很大 - 它将至少有10K行代码!

    根据Eric的说法,VO应该是不可变的 - 所以如果我的root返回VO,客户端代码就不会被允许更改它们。所以做这样的事情在服务中是不可接受的: client.getExternalInfo()。update(getDataFromExternalSystem())

    所以我的问题归结为地球上我应该如何更新内部对象而不破坏DDD规则?

    我没有看到任何简单的方法。


    更新I:

    我刚遇到规格,这似乎是我的问题的理想DDD概念。

    我还在读它,但我决定发布这个更新。

2 个答案:

答案 0 :(得分:0)

我自己一直在研究DDD,并且很难掌握它。

首先,您是对的:规范是一般用于验证或业务规则的精细模式,假设您应用的规则与谓词树很好地匹配。

当然,我不知道你设计的具体细节,但我对这个模型本身感到好奇。你提到你的客户端类有“很多属性”。你确定你的模型不是anemic吗?你的设计可以从更多的分析中受益,或许可以将其分解为其他聚合体吗?这是一个有限的上下文吗? 应该吗?

答案 1 :(得分:0)

规范绝对是复杂业务逻辑的方法。

但有一个问题 - 您是否将内部实体(如地址和名称)建模为ValueObjects?我能想到的最好的经验法则是,如果你能说他们是平等的,没有身份证,他们很可能会重视对象。您的域名是否认为名称具有州?

如果您正在查看几乎没有实体参与多种类型的更改且需要审计跟踪的问题,您可能还想探索EventSourcing。理想情况下,实体声明它对事件的反应,但您也可以在事件中保留变异代码以便于扩展。当然,这种方法有利有弊。