一、简介
在领域驱动设计中,也许聚合根是最重要最难理解的概念了。甚至于每个人的理解都从不同角度,广度,深度的不同造成理解程序的不一致,而指导实践的时候也是不一致的。
当然,我们可以看到有一些原则是一致的,比如:不变性约束,一致性边界,一个事物只修改一个聚合。
可问题是,这些东西都显得有点抽象,在实践中依然不知道怎么下手。也或者,我们可以从书籍中或者网上很多人发表的文章获取灵感,能够勉力指导一下实践。
不过不管怎么说,理论再难啃也得自己来啃,即使你吃出不同味道也不要紧,这是属于你的理论,当然了,如果你的吃出的味道和大牛吃出的味道是一致的也是好事,只是我们或许不应该把不同味道看得太重。
那,聚合是什么呢?DDD中的聚合和一般我们所说的聚合有什么不同,或者与OOAD中我们谈论的聚合有什么不同?
其实在日常中,我们好像不太使用聚合这么一个词汇来诠释我们的行为,所以有时候一旦它成为了某个术语似乎就变得难易理解。那我们姑且把聚合换一个词汇,就用“聚集”?
比如,某个地方有一个什么活动,这个活动聚集了很多人观看。或者某个集市里,有很多人去采购商品。
如果我们只关注上面两个例子中的“人”这个概念,你会发现,一些平常分散的,独立的个体,也就是“人”,在这个场景下被聚集到了同一个地方,形成一群“人”。
而如果我们放宽我们的关注点,比如把活动里的人、事、物,以及他们为什么参加这个活动因素,包括在聚集这个概念里面就形成了一个“活动”的概念。把集市里的人、事、物,以及他们为什么来赶集的因素,包括在里面就形成了“集市”这个概念。
这样,我们似乎可以粗略地去定义聚合是什么了
聚合:即把一些分散的、独立的人、事、物等个体,在一定关系下形成一个完整的概念。
也或者,我们可以类比编程语言中的集合?是不是容易理解呢
二、DDD中的聚合
上面,我们粗浅地定义了聚合的概念。
在DDD中聚合就是将领域对象依据不变性规则来框定一个一致性边界,统一通过聚合根来访问聚合内的一切东西。这里的聚合根是一个实体,有全局唯一的标识符。
听上去很晦涩难懂,下面我们根据几个实际例子来考虑两个对象是否应该被聚合在一起
领域对象:帖子 ---- 回复 有帖子可以没有回复 -> 帖子是一个聚合根,但帖子中不聚合回复 有回复不可以没有帖子 -> 回复是一个聚合根,回复需要聚合帖子 由于帖子也是一个聚合根,那么回复只聚合帖子的唯一标识
领域对象:用户 一--对--多 消息 有用户可以没有消息 -> 用户是一个聚合根,但用户不聚合消息 有消息不可以没有用户 -> 消息是一个聚合根,消息需要聚合用户,由于用户是一个聚合根 那么消息只聚合用户的唯一标识
领域对象:用户 ---- 收获地址 用户可以没有收获地址 -> 用户是一个聚合根,不需要聚合收获地址 收获地址不可以没有用户 -> 收获地址是一个聚合根,聚合用户,但用户是一个聚合根所以只聚合用户ID
领域对象:商品订单 ---- 收获地址 有收获地址可以没有商品订单 -> 收货地址是一个聚合根,收获地址不需要聚合订单 有商品订单不可以没有收获地址 -> 订单是一个聚合根,订单需要聚合收获地址,地址是聚合根所以只聚合地址的ID
领域对象:商品订单 一--对--多 订单子项 有订单不可以没有订单子项 -> 订单是一个聚合根,订单需要聚合订单子项 有订单子项不可以没有订单 -> 订单作为聚合根聚合了订单子项,订单子项不需要成为聚合根, 依托于订单存在
领域对象:商品 ---- 收货地址 商品可以没有收货地址 -> 商品是聚合根,不需要聚合收货地址 收货地址可以没有商品 -> 收货地址是聚合根,不需要聚合商品
如上的例子中,我们考虑两个对象之间是否可以相互脱离,独立存在来判断是否应该聚合在一起。
而不变性约束自然而然就符合了,比如下面这些约束来验证一下:
1、购买的商品总金额必须大于100元,意味着“订单”和“订单子项”必须聚合,和上面判断结果是一致的。
2、购买商品,必须有收获地址,订单作为聚合根,聚合收获地址的ID(一般上是聚合收货地址的值对象),和上面结果也是一致的。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。