DDD战术设计-聚合

摘自
https://www.zhihu.com/column/p/381540329

设计业务实例

办公用品采购系统。

  1. 企业的员工可以通过该系统提交一个采购请求,一个请求包含了若干数量、若干类型的办公用品(称为采购项)。
  2. 主管负责对采购申请进行审批。
  3. 审批通过后,系统会根据提供商不同,生成若干订单。

如果

  1. 采用以数据库为中心的建模方式
    第一,对于模型的讨论过早地进入了实现领域,和业务概念脱开了联系,不便于持续地和业务人员协作;
    第二,技术细节和业务规则的细节纠缠在一起,很容易顾此失彼

  2. 面向对象
    业务规则如何保证,在传统的面向对象方法中并没有严格的实现约束

针对类似“修改采购项也是修改采购请求”的需求,DDD的做法

image.png

采购请求采购项组织到一起,看做一个更大的整体,称为“聚合”。
这个聚合内部的业务逻辑[例如“采购申请审核通过后,不得对采购申请条目进行更改”]应內建于聚合内部。
为了实现这一目标,我们约定:对采购项(实体)的一切操作(增加、删除、修改等),都是对采购请求(聚合根)的操作。

聚合定义

将实体和值对象划分为聚合并围绕着聚合定义边界。选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制。
https://www.domainlanguage.com/wp-content/uploads/2016/05/DDD_Reference_2015-03.pdf

聚合本质

  • 建立一个比对象粒度更大的边界
  • 聚集紧密关联的对象 ---> 形成了一个业务上的对象整体。
  • 使用聚合根作为对外的交互入口 --> 保证多个互相关联的对象的一致性。

合理使用聚合,可以更容易地保证业务规则的一致性,减少了对象之间可能的耦合,提升设计的可理解性,降低出问题的可能性。


聚合划分的几个启发式规则

  • 生命周期一致性
  • 问题域一致性
  • 场景频率一致性
  • 尽量小的聚合

生命周期一致性

如果聚合根消失,聚合内的其他元素都应该同时消失。


如果采购请求(聚合根)不存在了,那么采购项当然也就失去了存在的意义。而商品、作为申请人的用户等对象,和采购请求之间则不存在此关系。

商品、作为申请人的用户等对象不纳入采购请求

问题域一致性

聚合表示的模型一定会位于同一个限界上下文之内


一个在线论坛,用户可以对论坛上用户的文章发表评论文章显然应该是一个聚合根。如果文章被删除,那么,用户的评论看起来也要同时消失。那么评论是否可以属于文章这个聚合?
一个图书网站,用户可以对图书发表评论,那么评论是否可以属于图书这个聚合?

评论这一个概念,在本质上和文章/图书这个概念相去甚远,因此不属于同一个问题域的对象
则不应该出现在同一个聚合中

image.png

需要依赖”最终一致性“来实现聚合之间的一致性。例如,在文章删除的时候,发送一个文章删除的消息。评论系统接收到文章删除消息之后,删除文章对应的评论。

场景频率一致性

场景(scenario)

  • 是业务用例的具体化描述
  • 反映了用户使用系统达成业务目标的方式。

经常被同时操作的对象,它们往往属于同一个聚合。而那些极少被同时关注的对象,一般不应该划为一个聚合。


考虑软件开发中的产品版本以及功能的关系。产品版本算不算是同一个问题域?

更合理的聚合

操作场景不一致的对象,或者说如果一个对象在不同场景下都会被使用,应该考虑把它们分到不同的聚合中。

尽量小的聚合

凡是不破坏以上三个一致性的情况,都没有必要把它们放到同一个聚合中

聚合之间如何关联?

采购申请及其属性(如状态、提交时间等)以及采购项属于一个聚合。但是,商品用户(提交人,审批人...)这些不能属于采购申请这个聚合。聚合之间如何关联?

引入ID对象来解决这个问题


image.png

引入ID对象带来的问题

  1. 某些场景下需要对信息进行第二次查询,而且无法利用 ORM 的 EagerFetch/LazyFetch 加载机制的遍历
    这不是损失,这类问题应该由外部服务,例如应用层服务来完成。
    好处,断开聚合,加快查询速度
  2. 为了断开聚合而额外引入的 Id 值对象,还能算是领域模型或者是 “统一语言” 的一部分吗?
    这是 DDD 的实现机制的一部分,它属于领域模型,但是请把其可见性控制在开发团队。没有必要和业务人员沟通这些概念
  3. 注意
    这个 Id 对象引用的只能是其他聚合根的 Id
    聚合根的 ID 应该做到全局唯一
    聚合内部的实体对象/值对象,保证内部的 ID 唯一即可。

代码实现方面的考虑

资源库(Repository)、工厂(Factory)面向聚合定义

  • 使用工厂来构造聚合对象是一种更好的对复杂性的封装
    在聚合以外,只应该有一个工厂对外可见,那就是聚合的工厂
  • 资源库是聚合的仓储机制
    一个聚合只能有一个资源库对象,那就是以聚合根命名的资源库。除此之外的其他对象,都不应该提供资源库对象。

代码结构与聚合保持一致

限界上下文,模块
└━聚合
       └━实体(包含聚合根)对象、值对象、资源库、工厂

聚合不可跨越部署的边界

  1. 如果系统采用了微服务架构,应该保持部署边界和限界上下文边界的一致
    不要让部署的粒度大于限界上下文的粒度,这样可以带来更好的业务灵活性和可伸缩性
  2. 从服务的最小边界上,不可让最小边界小于聚合的粒度,否则会带来大量的数据的一致性问题
    因为微服务之间的一致性一般需要通过最终一致性来保证,如果聚合跨越了部署边界将会是一致性的灾难

聚合改进了系统性能和可伸缩性

使用小的聚合
每个涉及访问的对象(事实上就是聚合)不可能很大,而所需的数据又恰如其分的都在,数据完整性和业务完整性就有了保障,还可以方便地进行水平扩展,性能和可伸缩性也就同时得到了满足。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,928评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,192评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,468评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,186评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,295评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,374评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,403评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,186评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,610评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,906评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,075评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,755评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,393评论 3 320
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,079评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,313评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,934评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,963评论 2 351

推荐阅读更多精彩内容