知识卡片

实体与值对象的角色转换:同一份数据在不同聚合里的不同身份

普通读书笔记卡

内容

很多值对象的数据其实来源于其他聚合,以数据冗余的方式实现不同领域之间的数据流转和共享——在数据的源头聚合里,它以实体或聚合根的形式存在,承担数据的集中维护和生命周期管理;而在别的聚合里引用这份数据时,它就变成了一个值对象,被这个聚合内的某个实体整体引用。书中的例子是:地址数据的源头是客户聚合,在客户聚合里地址是一个实体,可以被独立维护修改;但订单聚合需要收货地址时,会从客户聚合获取地址数据、组合成订单聚合自己的地址值对象——订单实体只能整体引用和替换这个地址值对象,不能单独修改它的某个属性(比如street),所有地址数据的新增修改操作,都只能在客户聚合这个唯一的源头完成。这个设计保证了业务职责的高内聚:要修改地址相关的业务逻辑,永远只需要改客户聚合这一处,其他聚合里的地址值对象只是这份权威数据的一份只读快照式引用,不会出现多处都能修改同一份数据、导致数据不一致或职责分散的问题。

参考来源

- 位置:第7章《实体和值对象:领域模型的基础单元》"7.3 实体和值对象的关系"(源文件:_epub-src/OEBPS/Text/chapter3-3-3.xhtml) - 结论依据:原文说明"在值对象的数据源头聚合,以实体或聚合根的形式存在,完成实体和数据的集中维护和生命周期管理。而在自己的聚合中它则以值对象的形式存在……订单实体可以整体引用和修改地址值对象的数据,但不允许单独修改地址值对象的某一个属性数据……所有地址数据的新增和修改等维护操作,都只能在客户聚合中完成,这样就可以实现业务职责的高内聚",直接支撑本卡片结论。 - 原始内容:在订单聚合中,订单实体有收货地址这个值对象。在生成订单实体时,会从个人中心的客户聚合中,获取地址实体数据组合成订单聚合的地址值对象。订单实体可以整体引用和修改地址值对象的数据,但不允许单独修改地址值对象的某一个属性数据,如street。