abp学习笔记 - 如何判断一个对象是不是聚合

简介

网络上关于DDD的文章很多,但我水平有限,其实很少看懂过。
借着新项目使用abp的春风,带着问题去学习/思考,效率永远是最快的。

对Navigation Properties的滥用

因为公司要求使用外键,所以代码中也自然而然的配置好了导航属性,这在我们日常开发中很爽,dbContext一拿,Include就完事了,想要什么数据就加载什么数据。
image

image

直到有一天数据库开始报警,有个哥们一个查询十几个Include,就差没把整个数据库给捅出来。
其核心原因,就是对Navigation Properties的滥用,导致无节制的Include,从而使得查询的笛卡尔体积指数级膨胀。

那应该怎么处理呢? 谜底就在谜面上,既然是滥用,那我限制它滥用不就好了吗?
那如何限制呢? 答案就是:斩断无限制的Include。
之前查询可以通过一个CustomerId => User => User Order => OrderPurchase = > ....... => UserRole => Role => .....
只要你愿意,你可以把数据库所有表都加载出来。
而现在,我们要根据业务模块来划分彼此的边界, 比如User信息就只有Customer 与User 能关联,Order信息只有Order与OrderPurchase能关联, 以此类推 。
恭喜你,你成功发明了DDD领域驱动的核心概念,领域建模

四条设计规则

既然要根据业务来划分边界,那判断的依据是什么呢?

  1. 有没有自己的不变量
    不变量指必须始终保持一致的业务规则,
    举个例子,C= a + b ,那么a ,b ,c 就必须在同一个事务里一起改,否则这个公式就不成立。
    再举个例子, 我创建Order , 订单基本信息与产品(sku)信息,肯定是要同时创建的,否则就会出现,我下单了,但里面什么都没买的情况。这明显不合理。

判断规则:边界划在哪里,就是看哪些东西必须在同一个事务里,规则:要求A和B逆序在同一次保存里成立,有,就是一个聚合。没有,就是两个聚合

  1. 聚合独立加载,保存,小而美
    DDD领域驱动一书原文说道到Provide repositories only for aggregate roots that actually need direct access
    外部对象只应该持有对聚合根的引用,用同一个聚合边界去管理,所以Reposityory对外只提供聚合根。

理论很美好,但在实际过程中,要考虑性能问题。由于聚合作为一个整体来加载与保存的,所以要设计得小,只放必须的。或者从业务上拆分成多个聚合根(没错,DDD思想是可以反向指导业务的,只要你能说服产品)。
不到万不得已,不要破坏这个规则,除非你是什么报表之类的需求

判断规则:有没有场景需要脱离父对象单独加载或保存?有,它就是独立聚合的候选条件

  1. 别的聚合根只能通过Id引用它
    Reference Other Aggregates By Identity
    引用其他聚合时,只用它的全局唯一标识,不持有整个对象引用(也就是不要在聚合之间直接导航),从而减少加载量(把整个数据库都脱库的例子),也便于拆分拓展。

判断规则:如果你发现A里面带着B的导航属性,而且你需要通过A去改B,那其实B是A的内部成员,它们应该是同一个聚合。反过来,如果B只是被A记录Id,那么B是独立聚合,那么它们就不应该在Repository相遇,而是在Application层相遇

  1. 跨边界怎么办?最终一致
    边界之外最终一致,跨聚合的规则不要求时刻最新,可以用事件、批处理等方式最终一致,一个请求里如果涉及到多个聚合,也不要在同一个事务里修改多个,跨聚合的更新应该用异步方式处理,只有边界内部才使用同步方式
    举个例子:在一个请求里,我要修改UserInfo 与UserRole,它们是两个聚合。所以理论上它们应该是先保存UserInfo,然后把修改UserRole作为事件发出去。
    判断规则:如果在Application层,你需要引用多个Repository来更新,就可以考虑使用CQRS来解耦,实现最终一致性

几条最佳实践

  1. DDD里的实体永远只属于一个聚合,既然A的内部成员,又是一个独立聚合是不成立的,必须二选一。
    Microsoft的文档说法是,如果绕过根单独修改子实体,根就没办法保证聚合处于有效状态,就好比”桌子有一条松腿“。

  2. 聚合根与充血模式相辅相成
    不变量由聚合根负责执行,规则不要散落在Application layer,应该使用充血模型。

未完待续,日后有新的感悟继续补充

posted @ 2026-11-11 09:39  叫我安不理  阅读(0)  评论(0)    收藏  举报