是否应使用方法参数或引用将命令信息传递给聚合?

时间:2015-01-21 16:49:29

标签: c# .net cqrs event-sourcing

我正致力于实施基本的CQRS + ES应用程序。我已经看过很多例子,但我不了解命令处理程序和聚合之间的路由。

在某些例子中,工作是这样做的:

XCommandHandler:

void Handle(XCommand command) {
   var aggregate = this.repository.Find<Aggregate>(command.aggId);

   aggregate.InvokeSomeBusinessLogic(command.property1, command.property2);
   this.repository.Save(aggregate);
}

但其他人则采用另一种方式:

XCommandHandler:

void Handle(XCommand command) {
   var aggregate = this.repository.Find<Aggregate>(command.aggId);

   aggregate.InvokeSomeBusinessLogic(command);
   this.repository.Save(aggregate);
}

最好的方法是什么,特别是在命令中有多个属性(15个或更多)时?

2 个答案:

答案 0 :(得分:9)

这不是一个关于CQRS + ES的问题,而是关于整体API设计的问题。正如Clean Code所解释的那样,没有参数的方法比具有一个参数的方法更好,这比具有两个参数的方法更好等。

盲目遵循该规则应始终让您选择第二个选项:

aggregate.InvokeSomeBusinessLogic(command);

然而,盲目遵守任何规则很少是一个好主意。在这种情况下,将Interface Segregation Principle视为反作用力是个好主意:

  

客户不应该被迫依赖他们不使用的方法。

由于getter和setter也是方法,我认为这个原则也适用于命令对象。

因此,如果您有15个或更多属性,但所讨论的方法只需要其中两个,那么传递这两个值可能会更好。

另一件事是,如果你有一个包含15个属性的命令对象,你可能想重新考虑你的设计。 CQRS + ES背后的基本假设之一是应用程序呈现task-based UIs,这可确保每个命令(以及相应的事件)都很小。


使用链接在Mark的评论中进行编辑,因为其中一个链接已被破坏:

更新汇总信息不是基于任务的;它的CRUD。也许Udi Dahan的这两篇文章会有所帮助。

Queries, Patterns, and Search – food for thought

Tasks, Messages, & Transactions – the holy trinity

答案 1 :(得分:3)

我原则上同意马克的观点。然而,我会注意到CQRS已经从领域驱动的设计世界发展而来。他们强调语言的重要性(ubiquitous language)。您可以捕获命令对象的实际名称中的意图和意义。

在实际层面上,通过添加参数的重构方法如果从多个地方调用,可能会变得非常痛苦。单个对象可以显着减轻这种情况。

我有一些您可能会发现有用的相关帖子。 Aggregate Root – How to Build One for CQRS and Event Sourcing6 Code Smells with your CQRS Events – and How to Avoid Them。虽然最后一个是关于事件的,但许多原则都适用。

希望你觉得它们很有帮助。