DDD、事件来源和聚合状态的形状



我很难理解state的形状,它是应用该实体的事件与该实体数据的投影派生而来的。

聚合的状态是否仅用于确定是否可以成功应用命令?还是应该以其他方式使用该状态?

举个例子——我有一个标准博客文章的Post实体。我可能有postCreatedpostPublishedpostUnpublished等事件。对于我将在读取表中保留的预测,我需要一个基本posts的投影(它将包括所有帖子,无论状态如何,都有很多细节(以及published_posts投影(它只表示当前发布的帖子,只包含渲染所需的信息(。

在上述情况下,我的聚合状态是否应该仅用于确定,例如,一篇帖子是否可以发布或未发布,等等?如果是这样的话,我的状态在聚合中的形状是否完全由这些验证所需的内容定义例如,在我的基本post投影中,我想要一个对帖子进行了更改的所有用户的列表。在聚合/命令的验证方面,我非常关心已经进行了更改的用户列表。这是否意味着这个列表而不是在我的聚合中成为我的状态的一部分

TL;DR:是-限制";状态";聚合到您选择缓存以支持数据更改的数据。


在我的聚合中,我区分了两种不同的想法:

  • 历史,也就是描述聚合生命周期变化的事件序列
  • 缓存,也就是我们隐藏的数据值,因为每次查询事件历史都有点糟糕

缓存结果没有太多我们永远不会使用的价值。

CQRS的一个基本教训是,我们不需要到处都有聚合

AGGREGATE是一组相关对象,我们将其视为数据更改的一个单元。--Evans,2003

如果我们不更改数据,那么我们可以安全地直接使用数据的不可变副本。

聚合的唯一基本目的是确定需要应用哪些事件(如果有的话(来使聚合的状态与命令保持一致(如果聚合可以保持一致(。所有不需要的状态都可以卸载到读取端,这可以被认为是事件流的重新混合(每个读取端只保持它需要的状态(。

也就是说,在实践中,直接使用聚合状态是有原因的,主要原因是希望聚合具有更强的一致性:CQRS本质上最终是一致的。与一致性更新的所有问题一样,重要的是要认识到一致性不是免费的,而且通常甚至不便宜;我倾向于认为一个项目有一个一致的预算,我对花它很吝啬。

在您的情况下,可能没有理由将更改帖子的用户列表包括在聚合状态中,除非例如有类似";没有单个用户可以修改给定帖子超过n次";。

最新更新