Str*_*dox 3 oop domain-driven-design value-objects event-sourcing
事件源域模型中是否有值对象的位置?
让我们将值对象定义为具有不可变状态的对象,它保护其不变量并且没有特定的标识符。
在这种情况下,事件源域模型是完全或部分事件源的域,这意味着它的当前状态可以通过应用过去发生的所有事件来派生。事件本身被认为是不可变的,即使随着时间的推移也是如此。
关于在事件中使用值对象的有效性已经发生了争论- 这个问题稍微更进一步:值对象在事件源域中是否有一席之地?
使用值对象的(潜在)问题是,以收紧不变量的方式改变域变得相当棘手。
此场景的一个示例是拥有一个Username值对象,唯一的限制是名称必须介于 2 到 16 个字符之间。
虽然这种方法已经运行良好一段时间了,但该企业决定只允许使用至少 5 个字符的用户名。迁移期开始,名称少于 5 个字符的用户将被要求更新其名称。
可以说这个过程是成功的,纠正事件被应用,每个人都很高兴。我们收紧了对值对象的限制,Username要求至少 5 个字符。
有一段时间每个人都很高兴,但后来我们发现快照有问题并重播所有事件。
现在,我们的Username对象面临一个异常:通过加载历史数据,我们破坏了域的不变量。
值对象的规则具有追溯力- 这是否使它们本质上不适合事件溯源?是否值得应用值对象的版本控制?有没有更简单的方法来避免此类问题?
我想说,在你重新定义了Username含义的那一刻,并且你没有以某种方式迁移历史数据,你本质上已经创建了两种不同的Username含义。
因为这个词有两种不同的含义,所以你必须以某种方式在代码中明确它。“版本控制”是一种方法,虽然我不会使用这样的通用解决方案,但有不同的建模选项。
您可以明确表示“用户名”的历史就是历史。例如,创建一个HistoricUsername,它是事件源对象,如果需要的话甚至可以是值对象。并创建一个Username始终是具有最新规则的用户名,该用户名根本不保留,而是从 a 创建HistoricUsername(如果可以的话)。
有些人建议有时从对象中提取“规则”,然后重新应用它。这样,对象本身始终有效,您可以要求它根据可能更改的规则来验证自身。我不太喜欢这些类型的解决方案,但它是一种选择,并且Username仍然是一个值对象。
因此,问题并不在于值对象不适合事件溯源,而只是建模必须更加准确。
| 归档时间: |
|
| 查看次数: |
1477 次 |
| 最近记录: |