知识卡片

值对象记录业务数据快照,实现聚合间解耦和故障隔离

普通读书笔记卡

内容

由于值对象常以数据冗余的方式承接来自其他聚合的数据,这个特性还带来一个重要的使用场景:记录业务发生那一刻的数据快照。以订单聚合下单为例,订单聚合会在生成订单的那一刻,把当时的商品信息和收货地址等基础数据记录下来(这类数据俗称”跟单数据”),此时商品和收货地址是以包含多个属性的属性集值对象形式存在的,被订单聚合根整体引用。这种”属性集值对象”的快照方式和”通过商品ID或地址ID关联”的单一属性值对象方式有本质区别:快照方式下,即使源头聚合(商品聚合、客户聚合)里的商品或地址数据后续发生了变更,也完全不会影响订单聚合里已经记录下来的快照数据——因为订单聚合保存的是数据发生那一刻的完整副本,而不是一个随时会指向最新值的引用。这带来两个直接好处:一是业务上能准确还原”下单那一刻”的真实场景(哪怕商品价格后来变了、地址后来改了,订单里记录的还是当时的数据);二是技术上实现了故障隔离,即使商品或地址所在的源端聚合服务此刻不可用,也完全不会影响订单聚合内部读取商品、地址快照数据的业务逻辑。反过来,如果业务需要的是”实时最新数据”而非某一时刻的快照,则应该改用关联ID的方式,但代价是会引入频繁的跨聚合、甚至跨微服务查询,增加服务间的耦合度。

参考来源

- 位置:第7章《实体和值对象:领域模型的基础单元》"7.3 实体和值对象的关系"(源文件:_epub-src/OEBPS/Text/chapter3-3-3.xhtml) - 结论依据:原文说明"值对象以数据冗余的方式记录业务发生那一刻前后序聚合之间的业务数据,还原业务发生那一时刻的数据场景……当商品或地址的源端聚合的商品实体或地址实体数据变更后,不会影响订单聚合中商品和收货地址值对象的快照数据……即使源端商品或地址所在聚合出现服务不可用的情况,也不会影响订单聚合中商品或地址相关的业务逻辑,很好地实现了应用的解耦和故障隔离",直接支撑本卡片结论。 - 原始内容:值对象以数据冗余的方式记录业务发生那一刻前后序聚合之间的业务数据,还原业务发生那一时刻的数据场景……即使源端商品或地址所在聚合出现服务不可用的情况,也不会影响订单聚合中商品或地址相关的业务逻辑,很好地实现了应用的解耦和故障隔离。