为什么分别表示命令和事件?

问题描述 投票:60回答:7

强调事件的体系结构中的命令和事件之间有什么区别?我能看到的唯一区别是命令通常由系统外的actor来源/调用,而事件似乎是由处理程序和系统中的其他代码提供的。但是,在我看到的许多示例应用程序中,它们具有不同(但功能相似)的接口。

events command cqrs event-driven-design
7个回答
131
投票

命令可以被拒绝。

事件已经发生。

这可能是最重要的原因。在事件驱动的体系结构中,毫无疑问,引发的事件代表了已发生的事情。

现在,因为命令是我们想要发生的事情,并且事件已经发生了,所以当我们命名这些事情时,我们应该使用不同的动词。这会驱动单独的表示。

我可以看到,命令通常由系统外的actor来源/调用,而事件似乎是由处理程序和系统中的其他代码提供的。

这是他们分开代表的另一个原因。概念清晰度。

命令和事件都是消息。但它们实际上是独立的概念,应该明确地对概念进行建模。


5
投票

此外,除了此处公开的所有答案之外,事件处理程序也可以在接收到事件发生的通知后触发命令。

例如,在创建Customer之后,您还想初始化一些帐户值等。在您的Customer AR将事件添加到EventDispatcher并且CustomerCreatedEventHandler对象接收到该事件之后,此处理程序可以触发命令的调度。将执行你需要的任何东西等。

此外,还有DomainEvents和ApplicationEvents。差异只是概念上的。您希望首先调度所有域事件(其中一些可能会生成应用程序事件)。这是什么意思?

在CustomerCreatedEvent发生后初始化帐户是DOMAIN事件。向客户发送电子邮件通知是应用程序事件。

你不应该混合它们的原因很明显。如果您的SMTP服务器暂时关闭,这并不意味着您的DOMAIN操作应受此影响。您仍希望保持聚合的未损坏状态。

我通常在Aggregate Root级别向Dispatcher添加事件。此事件是DomainEvents或ApplicationEvents。可以是两者并且可以是其中许多。一旦我的命令处理程序完成,我回到堆栈中执行命令处理程序的代码,然后我检查我的Dispatcher并调度任何其他DomainEvent。如果所有这些都成功,那么我关闭交易。

如果我有任何应用程序事件,现在是时候发送它们了。发送电子邮件不一定需要打开到数据库的连接,也不需要打开事务范围。

我从原始问题中略微偏离了一点,但同样重要的是要了解事件在概念上是如何被区别对待的。

然后你有Sagas ....但这是问题范围的WAYYYY OFF :)

是否有意义?


4
投票

通过一些例子,特别是Greg Young的演讲(http://www.youtube.com/watch?v=JHGkaShoyNs),我得出的结论是命令是多余的。它们只是来自用户的事件,他们按下了那个按钮。您应该以与其他事件完全相同的方式存储它们,因为它是数据,您不知道是否要在将来的视图中使用它。您的用户确实添加了,然后从篮子中删除该项目或至少尝试。您稍后可能希望使用此信息在以后提醒用户。


2
投票

它们代表性很强,因为它们代表了截然不同的东西。正如@qstarin所说,命令是可以被拒绝的消息,并且成功时会产生一个事件。命令和事件是Dtos,它们是消息,它们在创建和实体时往往看起来非常相似,但从那时起,不一定。

如果您担心重用,那么您可以使用命令和事件作为您的(消息)有效负载的包络

class CreateSomethingCommand
{
    public int CommandId {get; set;}

    public SomethingEnvelope {get; set;}
 }

但是,我想知道的是你为什么要问:D你是否有太多的命令/事件?


2
投票

除了上面提到的概念差异之外,我认为还有另一个与常见实现相关的差异:

事件通常在需要轮询事件队列的后台循环中处理。任何对该事件采取行动感兴趣的方通常都可以注册由于事件队列处理而调用的回调。所以一个事件可能是一对多。

可能不需要以这种方式处理命令。命令的发起者通常可以访问命令的预期执行者。例如,这可以是执行者的消息队列的形式。因此,命令旨在用于单个实体。


1
投票

我想添加到quentin-santin的答案是:他们:

将请求封装为对象,从而允许您使用不同的请求,队列或日志请求参数化客户端,并支持可撤销操作。

Source


1
投票

这件事是过去的事实。

该命令只是一个请求,因此可能会被拒绝。

命令的一个重要特征是它应该由单个接收器处理一次。这是因为命令是您要在应用程序中执行的单个操作或事务。例如,不应多次处理相同的订单创建命令。这是命令和事件之间的重要区别。事件可能会被多次处理,因为许多系统或微服务可能会对事件感兴趣。 'MSDN'

© www.soinside.com 2019 - 2024. All rights reserved.