微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

五、聚合根

一、简介

在领域驱动设计中,也许聚合根是最重要最难理解的概念了。甚至于每个人的理解都从不同角度,广度,深度的不同造成理解程序的不一致,而指导实践的时候也是不一致的。

当然,我们可以看到有一些原则是一致的,比如:不变性约束,一致性边界,一个事物只修改一个聚合。

可问题是,这些东西都显得有点抽象,在实践中依然不知道怎么下手。也或者,我们可以从书籍中或者网上很多人发表的文章获取灵感,能够勉力指导一下实践。

不过不管怎么说,理论再难啃也得自己来啃,即使你吃出不同味道也不要紧,这是属于你的理论,当然了,如果你的吃出的味道和大牛吃出的味道是一致的也是好事,只是我们或许不应该把不同味道看得太重。

那,聚合是什么呢?DDD中的聚合和一般我们所说的聚合有什么不同,或者与OOAD中我们谈论的聚合有什么不同?

其实在日常中,我们好像不太使用聚合这么一个词汇来诠释我们的行为,所以有时候一旦它成为了某个术语似乎就变得难易理解。那我们姑且把聚合换一个词汇,就用“聚集”?

比如,某个地方有一个什么活动,这个活动聚集了很多人观看。或者某个集市里,有很多人去采购商品。

如果我们只关注上面两个例子中的“人”这个概念,你会发现,一些平常分散的,独立的个体,也就是“人”,在这个场景下被聚集到了同一个地方,形成一群“人”。

而如果我们放宽我们的关注点,比如把活动里的人、事、物,以及他们为什么参加这个活动因素,包括在聚集这个概念里面就形成了一个“活动”的概念。把集市里的人、事、物,以及他们为什么来赶集的因素,包括在里面就形成了“集市”这个概念。

这样,我们似乎可以粗略地去定义聚合是什么了

聚合:即把一些分散的、独立的人、事、物等个体,在一定关系下形成一个完整的概念。

也或者,我们可以类比编程语言中的集合?是不是容易理解呢

二、DDD中的聚合

上面,我们粗浅地定义了聚合的概念。

在DDD中聚合就是将领域对象依据不变性规则来框定一个一致性边界,统一通过聚合根来访问聚合内的一切东西。这里的聚合根是一个实体,有全局唯一的标识符。

听上去很晦涩难懂,下面我们根据几个实际例子来考虑两个对象是否应该被聚合在一起

领域对象:帖子 ---- 回复 
有帖子可以没有回复 -> 帖子是一个聚合根,但帖子中不聚合回复回复不可以没有帖子 -> 回复一个聚合根,回复需要聚合帖子
由于帖子也是一个聚合根,那么回复只聚合帖子的唯一标识
领域对象:用户 一--对--多 消息
有用户可以没有消息 -> 用户一个聚合根,但用户不聚合消息
有消息不可以没有用户 -> 消息是一个聚合根,消息需要聚合用户,由于用户一个聚合根
那么消息只聚合用户的唯一标识
领域对象:用户 ---- 收获地址
用户可以没有收获地址 -> 用户一个聚合根,不需要聚合收获地址
收获地址不可以没有用户 -> 收获地址是一个聚合根,聚合用户,但用户一个聚合根所以只聚合用户ID
领域对象:商品订单 ---- 收获地址
有收获地址可以没有商品订单 -> 收货地址是一个聚合根,收获地址不需要聚合订单
有商品订单不可以没有收获地址 -> 订单是一个聚合根,订单需要聚合收获地址,地址是聚合根所以只聚合地址的ID
领域对象:商品订单 一--对--多 订单子项
有订单不可以没有订单子项 -> 订单是一个聚合根,订单需要聚合订单子项
有订单子项不可以没有订单 -> 订单作为聚合根聚合了订单子项,订单子项不需要成为聚合根,
依托于订单存在
领域对象:商品 ---- 收货地址
商品可以没有收货地址 -> 商品是聚合根,不需要聚合收货地址
收货地址可以没有商品 -> 收货地址是聚合根,不需要聚合商品

如上的例子中,我们考虑两个对象之间是否可以相互脱离,独立存在来判断是否应该聚合在一起。

而不变性约束自然而然就符合了,比如下面这些约束来验证一下:

1、购买的商品总金额必须大于100元,意味着“订单”和“订单子项”必须聚合,和上面判断结果是一致的。

2、购买商品,必须有收获地址,订单作为聚合根,聚合收获地址的ID(一般上是聚合收货地址的值对象),和上面结果也是一致的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐