流和聚合的事件溯源组织
Event Sourcing organization of streams and Aggregates
在 ES 中组织事件流的最佳方式是什么。对于事件流,我的意思是将所有事件聚合在一起。
假设我有一个 project
,其中包含一些数据和 tasks
的列表。
现在我有一个 Guid
作为 AggregateID
作为我的 streamID
。
到目前为止我可以
-> 使用该 ID 为给定项目重新创建状态
-> 我可以 assemble 使用自定义投影
的 projects
列表
问题是如何处理todos
?
这也应该在 project
stream id
下面处理还是应该有自己的 todo stream id
?
如果 todo
有它是单独的 stream
如何将它 link 给拥有者 project
。 project
如何知道给定 project
的所有 todo streams
。
这意味着对 todo list
的所有更改也应在项目中被识别为 Commands
和 Events
(更多事件)。
如果我也想允许 free todo's
与项目无关。它是否需要有自己的类型和 stream
来处理顶部的 freeTodo
。所有 todos
的列表是否 project
相关与否将是所有 todo
和 freeTodo
相关流的投影?
所以我想主要问题是如何处理嵌套聚合以及如何定义事件存储流和 linking?
我们将不胜感激任何提示、技巧、最佳实践或资源。
// 编辑更新
首先感谢@VoiceOfUnreason 花时间详细回答这个问题。我添加了标签 DDD,因为我有一种奇怪的感觉,它与限界上下文问题相关联,而限界上下文问题在大多数情况下都没有非黑即白的决定。显然领域有更多的深度和细节,我简化了例子。下面我分享了一些让我质疑的更多细节。
在我的第一个想法中,我为 todo
定义了一个聚合,并为 project id
定义了一个 属性。我将此 project
属性 定义为 option type (Nullable)
以涵盖项目相关和免费待办事项之间的区别。但是遵循用例/业务规则让我重新思考。
系统还应包含免费 todo's
,允许用户安排与项目无关的个人 tasks
(人力资源培训等)。所有 todo's
应该出现在他们的 projects
或完整的 todo
列表中(项目相关和免费)。
一个project
只有todo's
全部完成才能finished/closed。
这会以某种方式混合来自 aggregate project
的信息和来自 aggregate todo
的信息。所以这里没有明确的界限。我的想法是:a) 我可以利用 project aggregate
中的 todo read model
进行验证。 b) 在项目聚合范围内为 todo's
定义某种列出的结构(如果是这样的话)。这将在项目上下文中处理待办事项并定义明确的界限
c) 提供某种服务,为项目验证提供 todo
信息,以某种方式引用 a.)。
而且感觉真的很结合=-/
如果您或其他人有时间在这里分享更多细节和意见,那就太好了。太感谢了。
提醒:ddd中的战术模式主要是对 OO 最佳实践的列举。如果它在 OO 中是个坏主意,那么它在 DDD 中可能是个坏主意。
the main question is how do I handle nested aggregates
您重新设计了模型。
嵌套聚合表明您已经完全迷失了情节;聚合边界不应重叠。重叠边界类似于封装违规。
If a todo has it's separate stream how would one link it to the owning project.
最有可能的答案是 Todo 会有一个 projectId 属性,它的值通常指向系统中其他地方的项目。
How is the project aware of all the todo streams for a given project.
不是。您可以构建包含项目历史和待办事项历史的读取模型以生成单个只读结构,但项目聚合——负责确保边界内状态的完整性——不会无法查看待办事项对象的内部。
Meaning all changes to the todo list should be also recognized as Commands and Events (more Events) in the project.
不,如果它们是单独的集合,那么事件是完全分开的。
在某些情况下,您可能会将待办事项产生的事件中写入的值用作分派给项目的命令中的参数,反之亦然,但您需要将它们视为具有对话的独立事物可能会,也可能不会达成协议。
可能性:独立的待办事项可能与与项目关联的待办事项确实不同。请咨询您的领域专家——他们可能在通用语言中有单独的术语,或者在讨论细节时您可能会发现他们应该在 UL 中有不同的术语。
或者,待办事项可以是单独的聚合,业务适应有时项目状态和待办事项状态不一致的事实。您可以检测差异并根据需要缓解问题,而不是试图阻止模型进入聚合不一致的状态。
在 ES 中组织事件流的最佳方式是什么。对于事件流,我的意思是将所有事件聚合在一起。
假设我有一个 project
,其中包含一些数据和 tasks
的列表。
现在我有一个 Guid
作为 AggregateID
作为我的 streamID
。
到目前为止我可以
-> 使用该 ID 为给定项目重新创建状态
-> 我可以 assemble 使用自定义投影
projects
列表
问题是如何处理todos
?
这也应该在 project
stream id
下面处理还是应该有自己的 todo stream id
?
如果 todo
有它是单独的 stream
如何将它 link 给拥有者 project
。 project
如何知道给定 project
的所有 todo streams
。
这意味着对 todo list
的所有更改也应在项目中被识别为 Commands
和 Events
(更多事件)。
如果我也想允许 free todo's
与项目无关。它是否需要有自己的类型和 stream
来处理顶部的 freeTodo
。所有 todos
的列表是否 project
相关与否将是所有 todo
和 freeTodo
相关流的投影?
所以我想主要问题是如何处理嵌套聚合以及如何定义事件存储流和 linking?
我们将不胜感激任何提示、技巧、最佳实践或资源。
// 编辑更新
首先感谢@VoiceOfUnreason 花时间详细回答这个问题。我添加了标签 DDD,因为我有一种奇怪的感觉,它与限界上下文问题相关联,而限界上下文问题在大多数情况下都没有非黑即白的决定。显然领域有更多的深度和细节,我简化了例子。下面我分享了一些让我质疑的更多细节。
在我的第一个想法中,我为 todo
定义了一个聚合,并为 project id
定义了一个 属性。我将此 project
属性 定义为 option type (Nullable)
以涵盖项目相关和免费待办事项之间的区别。但是遵循用例/业务规则让我重新思考。
系统还应包含免费
todo's
,允许用户安排与项目无关的个人tasks
(人力资源培训等)。所有todo's
应该出现在他们的projects
或完整的todo
列表中(项目相关和免费)。一个
project
只有todo's
全部完成才能finished/closed。 这会以某种方式混合来自aggregate project
的信息和来自aggregate todo
的信息。所以这里没有明确的界限。我的想法是:a) 我可以利用project aggregate
中的todo read model
进行验证。 b) 在项目聚合范围内为todo's
定义某种列出的结构(如果是这样的话)。这将在项目上下文中处理待办事项并定义明确的界限
c) 提供某种服务,为项目验证提供 todo
信息,以某种方式引用 a.)。
而且感觉真的很结合=-/
如果您或其他人有时间在这里分享更多细节和意见,那就太好了。太感谢了。
提醒:ddd中的战术模式主要是对 OO 最佳实践的列举。如果它在 OO 中是个坏主意,那么它在 DDD 中可能是个坏主意。
the main question is how do I handle nested aggregates
您重新设计了模型。
嵌套聚合表明您已经完全迷失了情节;聚合边界不应重叠。重叠边界类似于封装违规。
If a todo has it's separate stream how would one link it to the owning project.
最有可能的答案是 Todo 会有一个 projectId 属性,它的值通常指向系统中其他地方的项目。
How is the project aware of all the todo streams for a given project.
不是。您可以构建包含项目历史和待办事项历史的读取模型以生成单个只读结构,但项目聚合——负责确保边界内状态的完整性——不会无法查看待办事项对象的内部。
Meaning all changes to the todo list should be also recognized as Commands and Events (more Events) in the project.
不,如果它们是单独的集合,那么事件是完全分开的。
在某些情况下,您可能会将待办事项产生的事件中写入的值用作分派给项目的命令中的参数,反之亦然,但您需要将它们视为具有对话的独立事物可能会,也可能不会达成协议。
可能性:独立的待办事项可能与与项目关联的待办事项确实不同。请咨询您的领域专家——他们可能在通用语言中有单独的术语,或者在讨论细节时您可能会发现他们应该在 UL 中有不同的术语。
或者,待办事项可以是单独的聚合,业务适应有时项目状态和待办事项状态不一致的事实。您可以检测差异并根据需要缓解问题,而不是试图阻止模型进入聚合不一致的状态。