领域驱动设计——值对象的更新

Domain Driven Design - update of value objects

我对 DDD 还很陌生,我还在阅读它。在阅读时,我对聚合与其他聚合共享一些数据有一些疑问。 例如,假设我正在开发一个在线商店,我将对一个帐户聚合和一个订单聚合进行建模。现在,假设订单聚合确实需要帐户聚合的某些数据来完成所有业务案例。严格遵循 DDD,我应该对 Order 聚合进行建模,使其具有一个值对象来保存 Account 聚合的标识,并始终请求所需的 Account 数据。我是否仍应将其建模为持有身份的值对象并始终请求所需的数据,或者我是否可以创建值对象以便它始终持有所需的数据?

这样数据就一直存在,但是,这个数据也需要和真实账户的聚合数据同步。

谢谢

您可以将订单中的客户表示为不可变值对象,将您需要的所有属性保存为原始数据类型。 或者,您将使用订单聚合中的标识值对象引用此帐户聚合。这将假设这两个聚合存在于同一个限界上下文中,但我怀疑情况是否如此。因为显然您在聚合(帐户和客户)中描述具有不同含义的同一事物,所以通用语言是不同的。在一个聚合中,它是一个帐户,在订单中它是一个客户。所以这是第一个迹象,它应该位于两个不同的限界上下文中。您可以在谈论帐户的地方有一个身份访问上下文,在谈论客户的地方可以有一个订单上下文。然后在您的订单上下文中,您可以通过反腐败层从会计上下文中获取客户信息,这会将帐户转换为客户价值对象。

Should I still model it as a value object holding the identity and always ask for the needed data or can I create the value object so that it holds the needed data all the time?

“视情况而定”。

(如果您正在学习 DDD,请习惯这个答案 - 它经常出现。)

聚合的一个关键思想是您正在对信息进行分区;域模型中的任何给定信息最多由一个聚合“拥有”,也就是说只允许一个聚合获取该数据的锁并对其进行修改。

使用该数据的其他所有人都在查看未锁定的副本。关于未锁定的副本,需要记住的重要一点是它们可能已过时(帐户聚合可以更改信息而无需请求订单聚合的许可)。

那么您真正要问的是“订单聚合 是否应该总是 在需要时索取帐户信息的新副本?或者我们应该 缓存订单聚合中该信息的副本?

答案将取决于许多因素,例如“帐户信息是否始终可用?” “您的订单业务逻辑对过时的帐户信息有多大的容忍度?”等等。

(提示:如果您的订单业务逻辑根本无法容忍过时的帐户信息,这强烈表明您错误地设计了聚合边界)

处理下游系统的一种非常常见的方法是使用某种消息传递机制。 事件驱动架构 可以很好地完成这项工作。

您有时不得不问自己的是,是否真的需要更新数据。也许对于有效订单,您可能希望在上游 BC 发布包含新名称的相关事件时更新客户名称。已经完成的订单很可能会被搁置。当某人的姓氏发生变化时,通常会出现这种情况。

您可能不想更改数据的另一个例子是产品描述。如果客户订购了 SKU BP-001 的“红笔盒”并且后端更新了 error 并将描述更改为“蓝笔盒”那么这可能会导致一个有趣的论点。

任何需要更新的下游系统都将拥有很可能陈旧的数据。在大多数情况下,这应该不是问题,因为它们最终会保持一致。

有时您发牌,有时您玩已经发牌的手牌。