DDD领域模型设计:何时用ID引用实体/何时嵌套实体?
领域实体关系建模问题
实体属性
| Company(公司) | Product(产品) |
|---|---|
| Id(ID) | Id(ID) |
| Name(名称) | Name(名称) |
| MarketCap(市值) | Category(品类) |
| Geography(地域) | Price(价格) |
补充信息
- 一家公司拥有数百万个产品
- 产品不能脱离公司独立存在
需要支持的核心接口
- 获取特定品类的所有产品(无需公司信息)
- 获取所有公司(无需产品信息)
- 获取某公司的所有产品
- 获取经营某品类产品的所有公司
两种建模方案
方案1:ID关联建模
// Company type Company struct { Id int Name string MarketCap int Geography string ProductIds []int } // Product type Product struct { Id int Name string Category string Price int CompanyId int }
方案2:嵌套实体建模
// Company type Company struct { Id int Name string MarketCap int Geography string Products []Product } // Product type Product struct { Id int Name string Category string Price int Company Company }
方案分析
方案2更符合DDD设计理念,领域模型无需关心存储实现细节,但在部分接口场景下效率极低。比如实现“获取所有公司列表”接口时,若用方案2,构建Company实体必须关联产品表,加载数百万个产品数据——即便最终API响应不需要返回产品,也得先获取所有产品才能构建合法的Company对象。而方案1无需关联操作,ProductIds可通过单独的关联表(companyID, productID)高效获取。
技术问题
在领域层设计一对多或多对多关系时,何时应仅用ID建模,何时应采用嵌套层级建模?
回答
判断用ID还是嵌套实体建模,核心要围绕领域规则、性能需求、数据访问场景三个维度:
1. 优先用嵌套实体建模的场景
- 领域逻辑强依赖关联实体的完整状态:如果业务规则必须直接操作关联实体的属性(比如公司需要统计旗下产品的平均价格、判断是否有某个品类的产品),嵌套实体能让领域模型更内聚,避免频繁跨实体查询,符合DDD“富领域模型”的设计思路。
- 关联实体数据量小且访问频繁:比如公司的部门、核心员工小组这类数据量不大的关联,嵌套后不会带来性能负担,还能简化业务逻辑的实现。
2. 优先用ID建模的场景
- 关联实体数据量极大:像案例中公司有数百万个产品,嵌套加载会导致内存占用过高、数据库查询效率暴跌,此时用ID关联能避免不必要的数据加载。
- 多数访问场景不需要关联实体数据:如果大部分接口(比如获取公司列表)不需要返回或操作产品数据,仅用ID就能满足领域模型的标识需求,同时大幅提升性能。
- 存在多方向的复杂查询需求:比如需要按产品品类反向查询公司,用ID+关联表的方式能更灵活地构建数据库查询,避免嵌套模型带来的JOIN性能问题。
3. 折中方案:按需加载
实际项目中也可以采用领域模型保留嵌套结构,但在数据访问层实现按需加载——比如默认不加载关联实体,只有当业务逻辑需要时才通过ID去查询。这种方式既符合DDD的设计原则,又能兼顾性能需求,但需要ORM框架或数据访问层支持延迟加载,或者在领域服务中显式控制数据加载逻辑。
内容的提问来源于stack exchange,提问作者siva
相关产品推荐
相关产品推荐

