事件源域模型中是否有值对象的位置?
让我们定义一个 值对象作为具有不可变状态的对象,保护其不变量并且没有特定标识符。
安 事件来源 在这种情况下,领域模型是一个完全或部分源自事件的领域,这意味着它的当前状态可以通过应用过去发生的所有事件得出。事件本身被认为是不可变的,即使随着时间的推移也是如此。
关于the validity of using value objects within events的争论已经发生- 这个问题更进一步:Do value objects have a place in event source domain在所有 ?
使用值对象的(潜在)问题是,以不变量被收紧的方式改变域变得相当棘手。
这种情况的一个例子是有一个 Username
值对象,唯一的限制是名称必须介于 2 到 16 个字符之间。
虽然这已经运行了一段时间,但公司决定只允许至少 5 个字符的用户名。
迁移期开始,名称少于 5 个字符的用户将被要求更新其名称。
让我们说这个过程是成功的,应用了更正事件,每个人都很高兴。
我们收紧了对 Username
的限制值对象至少需要 5 个字符。
有一段时间每个人都很高兴,但后来我们发现快照有问题并重播所有事件。
我们现在面临来自 Username
的异常。对象:通过加载历史数据,我们打破了我们领域的不变量。
一个值对象的规则追溯申请 - 这是否使它们本质上不适合事件溯源?是否值得应用值对象的版本控制?有没有更简单的方法来避免这些问题?
最佳答案
我会说,那一刻你重新定义了什么 Username
意味着,并且您不以某种方式迁移历史数据,您实际上已经创建了 2 个不同的 Username
意义。
因为这个词有 2 种不同的含义,所以您必须以某种方式在代码中明确表示。 “版本控制”是一种方式,虽然我不会使用这种通用解决方案,但有不同的建模选项。
您可以明确指出“用户名”的历史就是这样,一段历史。因此,例如创建一个 HistoricUsername
,这是事件源对象,如果需要,甚至可以是值对象。并创建一个 Username
它始终是具有最新规则的用户名,它根本不持久化,而是从 HistoricUsername
创建的如果可以。
有些人建议有时从对象中提取“规则”,然后再重新应用。这样对象本身在任何时候都是有效的,你可以要求它根据可能改变的规则来验证自己。我不是很喜欢这些类型的解决方案,但它是一种选择,而且 Username
仍然是一个值对象。
所以问题并不是真正的值对象不适合事件溯源,只是建模必须更准确。
关于oop - 事件溯源中的值对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52356127/