DDD:地址作为聚合根?

时间:2010-07-13 20:38:42

标签: oop domain-driven-design aggregate

我正在努力设计这个系统,其中地址是最重要的信息。现在在这种情况下,地址不仅仅是几行字符串。我们将市政当局(代码,姓名),地区(邮政编码,姓名),街道(代码,姓名),门牌号码存放在属于市政的特定区域的街道上。这是一个非常规范化的计划。

因此,我们将实体Municipal,District,Street和HouseNumber各自相互关联,为一个人(或其他人)定义一个完整的地址。

现在我一直在试图找出一个名为Address的聚合根是否有意义?然后,地址实体(聚合根)将引用HouseNumber,Street,District和Municipal。然后一个人将与一个地址相关联。

严格地说,这个聚合根不是必需的,但是如果我没有它,我将不得不遍历许多对象以获得完整的地址。根据该参数创建聚合根是否有意义?

在这种情况下,一个人永远不会引用除聚合根之外的任何东西,但UI可能只显示市政当局(浏览地址时等)。这是否违反了聚合根概念?

我真的很喜欢你的建议并接受这个问题。任何帮助将不胜感激!


关于我的问题的另一个讨论的一点点更新

需要在聚合中管理一些不变量。例如;一世 在一个区/自治市的街道上没有门牌号码 邮政信箱在另一个不同的地区/自治市。所以在分配时 一个地址/人的邮箱,我需要确保它们是相同的 区。

还有一些一致性界限(如果我理解这个概念的话 正确的方法)。如果我有地址,则必须在某个地区设有门牌号码 一条街(在那个区)。一条街可以跨越多个地区,所以它是 确保该街道上的门牌号码正确无误 区。


有关设计聚合的更新:

门牌号实际上是地址的入口点。门牌号码与街道和地区相关联。所以一个人与门牌号码相关联。我还想要定义的是,如果一个人对该门牌号码有“邮政责任”。引入聚合根地址,使该人与该关联而不是门牌号。在数据库中,聚合地址将包含与门牌号的1-1关联,并且地址对人员具有1- *。我应该在哪里存储表明该人有邮政责任的价值?我应该在地址汇总中这样做吗?或者在哪里 你说呢?我的实体也是如此 - 我应该在哪里指明该人是否有邮政责任?

3 个答案:

答案 0 :(得分:8)

要区分地址是价值对象还是实体,请问自己一个问题 - 如果人员地址发生变化且第二人有相同的地址 - 会改变吗?如果它们都改变了 - 地址被提升为实体(因为地址标识很重要而不是价值)。

要区分地址是实体还是聚合根,请问自己一个问题 - 地址是否有任何意义,或者它总是与人相关,通过它修改,与之一起删除?如果它不是与人联系在一起但存在于它自己(在模型中你是建模而不是现实),那么地址就是聚合根。


  

严格地说,这个聚合根不是必需的,但是如果我没有它,我将不得不遍历许多对象以获得完整的地址。根据该参数创建聚合根是否有意义?

不,不。技术问题不应该与您的域名混淆。实体可以作为“子聚合”工作,地址可以包含市政,城市等,并且仍然只是一个实体(因为它对任何人都没有意义)。

  

在这种情况下,一个人永远不会引用除聚合根之外的任何东西,但UI可能只显示市政当局(浏览地址时等)。这是否违反了聚合根概念?

演示文稿也不应该破坏您的域名。据我所知 - 如果您只显示实体列表并隐藏它们所属的聚合,那就完全没问题了。


  

两个人可以关联到同一个地址,如果其中一个人移动,另一个人不会自动移动。

问题是 - 你想如何模拟这个移动过程?

我看到两种方式:

  1. 当#1移动时,地址已修改但是人#2的地址不是同一地址,因此 - 不受影响。在这种情况下 - 地址只是一个实体。
  2. 当#1人移动时,移动过程切换地址到另一个。在这种情况下 - 地址是聚合根。
  3.   

    地址本身存在,如果一个人移动到某个地址,他就会与之关联。

    这意味着您希望坚持第二种方式(当地址是聚合根时)。没关系,但是你应该重新检查地址是否可以降级为实体,这会使你的域模型变得不那么复杂。


    请记住 - 没有“模特”,只有“模特”。你无法模拟现实来完美地模仿它,你只能将其中的某些部分建模为解决特定问题

    这就是回答ddd相关问题很难的原因 没有人知道你正在努力解决的问题。


      

    如果我理解正确(http://msdn.microsoft.com/en-us/magazine/dd419654.aspx - 关于聚合的部分),那么地址是否可以在没有人(或其他收件人)的情况下存在是无关紧要的;问题是地址成分是否可以存在或在没有地址的情况下被访问。如果可以,Address不应该是聚合根。

    这是相关的。如果地址在没有人的情况下不存在(这不是一个案例) - 它不可避免地被降级为一个实体(因为没有人没有意义)或价值对象(如果地址本身没有身份)。否则 - 您只是引入了不必要的聚合根。

    如果聚合根包含对其他聚合根(但不包含其他聚合根的实体)的引用,则可以。因此 - 地址成分也可以是聚合根(PostOffice中引用的市政),如果地址本身是实体或聚合根,则不会改变。

答案 1 :(得分:1)

在我看来,如果

,应该创建聚合
  1. 有一个收容 与其相关的关系 对象
  2. 一个人的对象     聚合存储在数据库中,     只有根应该是     可通过查询获得。该     应该获得其他对象     通过遍历协会。
  3. 并且您有不变的规则,您需要在所包含的对象中统一强制执行
  4. 你的情景似乎并不满足其中任何一个2.所以我的意见不是

    另请阅读此帖并提供答案:DDD: Aggregate Roots

答案 2 :(得分:-1)

地址是否应该是一个单独的实体,不应该受到技术问题的驱使。

您谈论地址的方式告诉我,这是一个由您提到的组成部分组成的独立实体。

即使没有绑定到Person或其他类,Address仍然存在的事实也是一个线索,它应该是它自己的实体。

此外:地址不仅可以用作Person,还可以用于其他东西(类)。你是否真的想给每个可以拥有地址的班级负担如何从其组成部分处理它?<​​/ p>

仅仅是你所说的地址作为一个特定概念的事实足以使它成为一个单独的类。即使在地址只存在于另一个类中的情况下也是存在的,在这种情况下创建一个单独的类(可能是嵌套类)是有意义的,只是为了将处理地址的逻辑与逻辑分开处理其余人的属性。

<强>更新

如果我理解正确(http://msdn.microsoft.com/en-us/magazine/dd419654.aspx - 关于聚合的部分),那么地址是否可以在没有人(或其他收件人)的情况下存在是无关紧要的;问题是地址成分是否可以存在或在没有地址的情况下被访问。如果可以,Address不应该是聚合根。

一方面,地址应该是其组成部分的集合。但是,地址的组成部分似乎与地址无关,并且可以在没有地址的情况下存在。毕竟,在没有“门”存在的情况下,市政府或街道都可以存在。所以,我想说这会使地址成为DDD术语中的聚合根。

<强>更新 正如汤米所提到的那样(见评论):一个更好的问题是“系统是否会直接操纵街道/市政,或者它是否始终是整个地址?”

我认为,当总是在构建地址的上下文中完成时,从列表中选择一个市镇来构建地址不是“直接操纵”。同样地,如果只保留一个地址使用,我不会考虑保留该城市名单“直接操纵”。

<强>更新 正如Arnis所指出的那样,地址是否可以独立于人(或另一个实体)存在是相关的,因为它决定了地址本身是否是一个实体。据我所知,现在只有实体可以是聚合根。