当前,我正在为我的一个项目建模基于事件源的域逻辑。
它基于 CQRS ,具有非规范化的sql读取端,而写入端则具有事件流。
我有一个要求,一个域的实体应具有某种status
属性(基本上是一个枚举)。 status
可以通过两种方式进行更改:由系统用户直接更改或由于系统中其他更改而更改。从域的角度来看,只有用户的更改是 true 更改,因此对于自己的事件应得到,可以从当前状态(其他属性)计算其他状态转换。
但是。 status
属性在读取模型中至关重要。此外,系统应提供当前实体status
和所有历史状态。但是,为了做到这一点,我似乎需要针对所有状态转换的技术事件,系统会在计算出的状态真正发生变化后发出该事件。
从理论上讲,我可以避免发生那些技术事件。我考虑此选项的唯一原因是因为实体的更改日志,现在它是相关事件的简单漂亮打印。
答案 0 :(得分:1)
简短的回答:事件来源警察不会追随您。
更长的答案:在短期内,将计算的值存储在事件中还是只写先行数据,然后让读取的模型自己运行计算,就无关紧要了。
在处理从一个发行版到另一个发行版的计算时,事情开始变得复杂。
示例:“过去,购买金额超过100美元需要经理的批准,但从现在起,该门槛是50美元”。因此,我们有75美元的购买请求。需要批准吗?好吧,这取决于制定价格时生效的规则集。你要去哪里捕捉?
通常的做法是,事件日志不仅用于捕获模型的输入,而且还用于基于这些输入做出的决策。换句话说,一旦有了事件,您就不再需要业务规则来了解正在发生的事情。
答案 1 :(得分:1)
状态可以通过两种方式更改:要么由系统用户直接更改,要么由于系统中其他更改的结果。
然后,您应该在域事件中捕获此事件。从纯粹的逻辑观点来看,status
发生更改的事实并不取决于以下原因:如果用户更改了它,则它更改了;如果系统更改了它,那么它也会更改(使用过的人会看到它已更改,对吗?)。因此,从状态的角度来看,它在任何情况下都会发生变化。
在您的域中,为什么更改status
很重要,所以您应该在事件本身中捕获这一点。例如,事件可能看起来像这样:StatusChanged(enum newValue, bool changedByTheUser)
。
多亏了事件源,您之后才能在Aggregates或ReadModels中使用此信息(为什么更改)。例如,当有关自动状态更改的业务规则更改时,您可以使用以下代码忽略系统先前所做的更改:
if(!event.changedByTheUser and event.date < '2019-01-02'){ /* ignore it */}