2

我正在从纯 DDD 范式转向 CQRS。我目前关心的是 Event Sourcing,更具体地说,是组织 Event Store。我已经阅读了大量的博客文章,但仍然无法理解某些内容。如果我错了,请纠正我。

每个事件基本上包括: - 事件日期/时间 - 事件类型(我们也可以从中找出 AggregateRoot 的类型) - AggregateRoot id (Guid) - AggregateRoot 版本(维护更新顺序) - 事件数据(一些具有更新所需数据的序列化类)

现在,如果我的事件数据由简单的值类型(整数、字符串、枚举等)组成,那么这很容易。但是如果我必须通过另一个 AggregateRoot 怎么办?我不能将整个 AR 序列化为事件数据的一部分(想想所有数据和延迟加载),基本上我只需要存储那个 AR 的 Id。但是,当我需要应用该事件时,我需要先从数据库中获取该 AR。而且从我的域模型(调用存储库和使用 AR Id)中这样做感觉不对。

最好的方法是什么?

ps 对于一个具体的例子,我们假设有一个模型,它由任务和用户实体(都是 AR)组成。任务持有对用户负责人的引用。但是可以更改负责的用户。

更新: 我想我找到了困惑的根源。我相信事件溯源应该只用于构建读取模型。在这种情况下,传递 ID 和原始数据是可以的。但是聚合本身使用的相同事件。这是我无法理解的。

4

3 回答 3

3

在 DDD 中,聚合是一个一致性/不变性边界,因此一个人可能永远不会依赖另一个人来维护其不变性。当我们开始使用这个设计限制时,我们发现很少有需要存储对另一个的完整引用的情况,通常我们存储它的 id 和(如果需要)版本以及相关属性的副本。

例如,使用通常的 Order/LineItem 和 Product 问题,我们将在 LineItem 中复制 Product 的 id 和价格,而不是完整的参考。这种方式可以防止产品价格的变化影响 Order/LineItem 聚合的不变量。如果需要在产品价格更改后更新 LineItem 价格,我们需要跟踪使用过的产品的 PriceChanged 事件,并向 Order/LineItem 发送补偿命令。通常这种协调/同步由 saga 处理。

于 2011-07-08T09:54:07.037 回答
0

在事件溯源中,聚合的状态由事件定义,仅此而已。所有领域模型的东西(ala DDD)只是为了决定应该引发哪些领域事件。事件应该对您的域一无所知,它应该是简单的 DTO。事实上,在没有 DDD 的情况下拥有 Event Sourcing 是完全可以的。

于 2011-07-08T14:33:49.820 回答
0

据我了解事件溯源,它应该帮助人们摆脱关系数据模型和像 NHibernate 或实体框架这样的 ORM,因为它们每个都是独立的科学。然后,程序员可以简单地专注于业务逻辑。我在这里看到了一些用于事件存储的关系模式,它们只是 ID、版本、时间戳加上一个 NClob 或 NVarchar(max) 列来存储事件有效负载模式。

于 2015-11-09T01:00:32.447 回答