Domain driven design 流和聚合的事件来源组织
在ES中组织活动流的最佳方式是什么。对于事件流,我指的是聚合的所有事件 假设我有一个Domain driven design 流和聚合的事件来源组织,domain-driven-design,cqrs,event-sourcing,ddd,Domain Driven Design,Cqrs,Event Sourcing,Ddd,在ES中组织活动流的最佳方式是什么。对于事件流,我指的是聚合的所有事件 假设我有一个项目,其中包含一些数据和任务列表 现在我有一个Guid作为AggregateID作为我的streamID。 到目前为止我能做到 ->使用该ID重新创建给定项目的状态 ->我可以用自定义投影组合项目列表 问题是如何处理待办事项? 这也应该在项目流id下处理,还是应该有自己的todo流id 如果一个todo有一个独立的流如何将它链接到所属的项目。对于给定的项目,项目如何识别所有待办事项流。 这意味着对待办事项列表的所
项目
,其中包含一些数据和任务列表
现在我有一个Guid
作为AggregateID
作为我的streamID
。
到目前为止我能做到
->使用该ID重新创建给定项目的状态
->我可以用自定义投影组合项目列表
问题是如何处理待办事项?
这也应该在项目流id
下处理,还是应该有自己的todo流id
如果一个todo
有一个独立的流
如何将它链接到所属的项目
。对于给定的项目
,项目
如何识别所有待办事项流
。
这意味着对待办事项列表的所有更改也应被识别为项目中的命令
和事件
(更多事件)
如果我还想允许自由待办事项
与项目无关。它是否需要有自己的类型和stream
才能在顶部处理freeTodo
。所有todo
是否相关的列表将是所有todo
和freeTodo
相关流的投影
因此,我想主要的问题是如何处理嵌套聚合,以及如何定义事件存储流及其链接
任何提示、技巧、最佳实践或资源都将受到高度赞赏
//编辑更新
首先感谢@VoiceOfUnreason花时间详细回答这个问题。我添加了标记DDD,因为我有一种奇怪的感觉,它与有界上下文问题相关,这在大多数情况下不是黑或白的决定。显然这个领域有更多的深度和细节,我简化了这个例子。下面我分享了更多细节,这让我产生了疑问
首先,我为todo
定义了一个聚合,并为项目id
定义了一个属性。我将此project
属性定义为选项类型(可为空)
,以覆盖与项目相关和免费todo之间的差异。但以下用例/业务规则让我重新思考
- 系统还应包含免费的
todo
,允许用户安排与项目无关的个人任务
(进行人力资源培训等)。所有的todo
应该出现在他们的项目中,或者出现在完整的todo
列表中(项目相关和免费)
- 只有当所有待办事项都已完成时,
项目才能完成/关闭。
这会以某种方式将聚合项目
中的信息与聚合todo
中的信息混合在一起。所以这里没有明确的界限。我的想法是:a)我可以利用项目聚合中的todo-read模型进行验证。b) 为项目聚合范围内的todo
定义某种列出的结构(如果是,如何定义)。这将在项目上下文中处理todo,并定义明确的界限
c) 提供某种服务,为项目验证提供todo
infos,以某种方式参考a.)点
所有的人都感觉很好=-/
如果你或某人有时间在这里分享更多的细节和观点,那就太好了。非常感谢 提醒:中的战术模式主要是OO最佳实践的枚举。如果这在OO中是个坏主意,那么在DDD中可能是个坏主意
主要问题是如何处理嵌套聚合
你重新设计你的模型
嵌套聚合表示您完全失去了绘图;聚合边界不应重叠。重叠边界类似于封装冲突
如果todo有单独的流,如何将其链接到所属项目
最可能的答案是Todo将具有projectId属性,其值通常指向系统中其他位置的项目
项目如何知道给定项目的所有todo流
事实并非如此。您可以构建包含项目历史和todo历史的读取模型,以生成单个只读结构,但负责确保边界内状态完整性的项目聚合无法查看todo对象内部
这意味着对todo列表的所有更改也应被识别为项目中的命令和事件(更多事件)
不,如果它们是单独的聚合,则事件是完全独立的
在某些情况下,您可能会使用todo生成的事件中写入的值作为发送到项目的命令中的参数,反之亦然,但您需要将它们视为单独的东西,进行可能会或可能不会达成一致的对话
可能性:可能是独立的todo项与项目相关的todo项实际上是不同的。请咨询您的领域专家——他们可能在通用语言中有单独的术语,或者在讨论细节时,您可能会发现他们在UL中应该有不同的术语
或者,todo可以是单独的集合,业务可以接受这样一个事实,即有时项目状态和todo状态不一致。不要试图阻止模型进入聚合不一致的状态,而是检测差异并根据需要缓解问题。提醒:中的战术模式主要是枚举