首页 > 解决方案 > 值对象和业务逻辑演进

问题描述

特别是在使用 DDD 和值对象时,我遇到了一些问题。

VO 将验证逻辑隐藏在构造函数\fabric 方法中,使我们能够依靠对象始终处于一致状态这一事实。因此,在我们使用的所有地方都不需要显式验证,例如,可以用字符串表示的电话号码。

因此,不会从错误的输入数据构造任何对象。或者我们可以创建一个特殊的“无效”旁白。但我认为这是一种倒退,因为每次我们使用它时都将被迫检查它的有效性。

我的问题是当我们的业务逻辑发生变化而数据库中存储的数据没有变化时我们应该怎么做。一直以来,我们都能够接受来自用户输入的数字、连字符和括号的任意组合作为有效电话号码。但有时验证逻辑已更改为更严格:有效电话号码只能以 +1 开头,缩小到美国号码。

从 DB 中的此类数据创建 VO PhoneNumber 时,我们无法引发异常,因为它不允许 UI 填充用户可以修复的数据。此外,我们无法从无效数据创建 VO,因为这将消除始终处于一致状态的好处,并使我们回到我们一直在检查输入数据的情况下使用它。

什么方法可以让我们使用 VO 并且仍然能够读取无效(旧规则有效,已不复存在)数据?可能是某种版本的 VO?当新的业务逻辑到来时,我们不是更改旧的 VO,而是创建(继承)新的?或者是其他东西?不管是什么,我相信它不应该放弃 VO 始终保持一致的能力。

谢谢。

标签: architecturedomain-driven-design

解决方案


从 DB 中的此类数据创建 VO PhoneNumber 时,我们无法引发异常,因为它不允许 UI 填充用户可以修复的数据。此外,我们无法从无效数据创建 VO,因为这将消除始终处于一致状态的好处,并使我们回到我们一直在检查输入数据的情况下使用它。

听起来您没有使用 CQRS,否则这首先不是问题。

在 CQRS 中,您可以将命令(以及数据模型)拆分为查询和命令,其中命令会改变数据(=对聚合进行操作),而查询对读取模型(聚合数据的投影)进行操作。

对于您不需要验证的查询,它只是一种投影数据的形式(即,您可以查询它或具有快速读取访问权限,而不会阻止它对命令的变异操作进行阻止)。

如果使用两个单独的模型(读取和写入模型)正确应用 CQRS,仍然可以读取“无效”数据。但是对这些数据的任何更改都必须遵守新的业务规则。


推荐阅读