alp*_*ogg 65 events command event-driven-design cqrs
强调事件的体系结构中的命令和事件之间有什么区别?我能看到的唯一区别是命令通常由系统外的actor来源/调用,而事件似乎是由处理程序和系统中的其他代码提供的.但是,在我看到的许多示例应用程序中,它们具有不同(但功能相似)的接口.
que*_*rin 139
命令可以被拒绝.
事件已经发生.
这可能是最重要的原因.在事件驱动的体系结构中,毫无疑问,引发的事件代表了已发生的事情.
现在,因为命令是我们想要发生的事情,并且事件已经发生了,所以当我们命名这些事情时,我们应该使用不同的动词.这会驱动单独的表示.
我可以看到,命令通常由系统外的actor来源/调用,而事件似乎是由处理程序和系统中的其他代码提供的.
这是他们分开代表的另一个原因.概念清晰度.
命令和事件都是消息.但它们实际上是独立的概念,应该明确地对概念进行建模.
Ali*_*yat 11
该事件是过去的事实。
该命令只是一个请求,因此可能会被拒绝。
命令的一个重要特性是它应该只被一个接收器处理一次。这是因为命令是您要在应用程序中执行的单个操作或事务。例如,不应多次处理同一个订单创建命令。这是命令和事件之间的重要区别。事件可能会被多次处理,因为许多系统或微服务可能对事件感兴趣。'msdn'
小智 8
在研究了一些示例,尤其是 Greg Young 演示文稿 ( http://www.youtube.com/watch?v=JHGkaShoyNs ) 之后,我得出的结论是命令是多余的。它们只是来自您的用户的事件,他们确实按下了那个按钮。您应该以与其他事件完全相同的方式存储它们,因为它是数据,您不知道是否要在将来的视图中使用它。您的用户确实添加了该项目,然后从篮子中删除了该项目,或者至少尝试这样做。您稍后可能希望使用此信息来提醒用户以后注意这一点。
另外,除了此处公开的所有答案之外,事件处理程序在接收到事件发生的通知后也可能能够触发命令。
举例来说,创建客户后,您还想初始化一些帐户值,等等。在客户AR将事件添加到EventDispatcher并由CustomerCreatedEventHandler对象接收到之后,此处理程序可以触发命令的分派将执行您需要的任何东西,等等。
另外,还有DomainEvents和ApplicationEvents。区别仅仅是概念上的。您想首先分派所有域事件(其中一些事件可能会产生应用程序事件)。我是什么意思
在发生CustomerCreatedEvent之后初始化帐户是DOMAIN事件。向客户发送电子邮件通知是一个应用程序事件。
您不应该混合使用它们的原因很明显。如果您的SMTP服务器暂时关闭,那并不意味着您的DOMAIN OPERATION应该会受到影响。您仍然希望保持聚合的未损坏状态。
我通常在“聚合根”级别将事件添加到我的调度程序。此事件是DomainEvents或ApplicationEvents。可以是两者,也可以是很多。完成命令处理程序后,我又回到堆栈中执行命令处理程序的代码,然后检查我的Dispatcher并分派其他任何DomainEvent。如果所有这些都成功,那么我将关闭交易。
如果我有任何应用程序事件,这是分发它们的时间。发送电子邮件不一定需要打开数据库连接,也不需要打开事务作用域。
我偏离了最初的问题,但对您来说,了解事件在概念上也可能会有所不同也很重要。
然后您有了Sagas ....但是这个问题的范围有WAYYYY OFF :)
是否有意义?
只是为了补充这些精彩的答案。我想指出耦合方面的差异。
命令针对特定处理器。因此,命令发起者和处理器之间存在一定程度的依赖/耦合。
例如,UserService在创建新用户时,将“发送电子邮件”命令发送到EmailService.
事实上, 知道UserService它需要EmailService,这已经是耦合了。如果EmailService更改其 API 架构或出现故障,则会直接影响UserService功能。
事件不针对任何特定的事件处理程序。因此,事件发布者变得松散耦合。它不关心什么服务消耗其事件。事件的 0 个消费者甚至是有效的。
例如,UserService在创建新用户时发布“用户创建事件”。可能EmailService可以使用该事件并向用户发送电子邮件。
这里UserService是不知道的EmailService。他们是完全脱钩的。如果EmailService出现故障,或者业务规则发生变化,我们只需要编辑EmailService
两种方法各有优点。纯粹的事件驱动架构设计更难跟踪,因为它的耦合过于松散,尤其是在大型系统上。而命令重架构具有高耦合度。因此,良好的平衡是理想的。
希望这是有道理的。