首页 文章

来自外部系统的事件采购命令或事件?

提问于
浏览
9

在大多数情况下,我理解命令与CQRS ES系统中的事件之间的区别 . 但是,有一种情况我无法弄清楚 .

假设我正在构建个人财务跟踪系统,用户可以在其中输入借方/贷方 . 显然这些是命令,一旦验证它们,域模型就会更新并发布一个事件 . 但是,假设信用/借记信息也直接来自外部系统,例如用户的花店发送一条消息,说明他已经向用户的信用卡收取了他的定期母亲节交付费用 . 在这种情况下,消息似乎是一个事件(已经发生了收费),但消息可能格式错误并且将被拒绝 . 它真的是一个命令吗?但是后来需要一种发送ACK / NACK的方法,这不是这里的情况(花店只有在知道借记已经发生时才发送消息) .

编辑:只是为了澄清,我不是在谈论外部系统对我的事件和/或命令的了解 . 我有一个组件从外部系统接收数据,然后必须发布事件或发送命令 . 问题是,我的组件应该使用哪个事件或命令?

2 回答

  • 2

    这是有界上下文的完美示例 .

    在另一个表示相同或业务流程步骤的系统(或有界上下文)中发生的事件不应被视为接收系统中发生的事件 .

    Florist System Debit事件的结构可能与财务跟踪系统中可能发生的Debit事件的结构不同 .

    为了解决这个问题,我将有一个能够收听花店系统事件的终点,并且我会根据事件中的信息使财务跟踪系统发出命令,如果需要,可以将其与财务跟踪系统中的信息结合起来 . 如果发生这种情况,可以将其视为财务跟踪系统的客户,如果愿意,甚至可以将其视为“域名服务” .

    在这种特殊情况下,来自Florist系统的事件带有在Florist系统中发生的交易的信息(有界上下文) . 我不会在域名服务中做出任何决定,而是向财务跟踪系统域发出命令,在该域中进行决策并发布财务跟踪系统事件 . 如果Florist系统事件在财务跟踪系统中显示格式不正确,您可能不希望以请求/响应或Ack / Nack方式告知Florist系统 . 该活动是从花店发布的,如果你实现类似的东西,你会打破消息模式 . 您的消息传递基础结构应该允许您重试消息,甚至修复接收代码并使用新代码重试消息 .

    但是,如果您确实需要回复Florist有界的背景,Florist系统可以订阅财务跟踪系统中的事件,以确定交易是否成功处理 . 只有在主系统决定是否可能发生交易时才需要这样做 .

    如果您描述财务跟踪系统更像是一个交易日志,您唯一需要做的就是不将Florist事件视为财务跟踪系统事件 . 在介于导致财务跟踪系统事件的命令之间加入一些东西 .

    编辑:

    作为对您的编辑的回复 . 您接收组件应该向财务跟踪系统域发送命令,而财务跟踪系统域又会发出事件(像往常一样) .

  • 11

    我在想到同样的事情时发现了这个问题 .

    我喜欢Mikael的回答并赞成它 . 但是,我在DDD / CQRS论坛上找到了另一个采用不同方法的答案,因此我想在这里将其发布给其他正在寻找的人 .

    Here's a quote from Greg Young关于跟踪外部状态的类似问题:

    在大多数库存系统中,没有命令 .

    或者解释:

    专门跟踪外部状态的系统将没有命令 .

    让我们回顾并思考一下你的系统如何根据这个想法发展(让我们假设你不是为自己构建它):

    • 您决定创建一个个人财务跟踪器,记录来自外部世界的交易,显示图表,汇总总数等 .

    • 因为事件是用于跟踪状态更改而不是命令,所以您可以记录这些更改 . 你也是在事件处理程序中编写投影,以将事件聚合为总计和图形数据点 .

    • 然后你得到用户 . 他们称赞应用程序,但使用率仍然很低 . 在深入挖掘之后,你会发现他们仍然使用其他应用程序来跟踪财务状况,比如说,那些日期卡,他们希望"split"外部交易成多个,他们的银行没有在线访问权限,他们想跟踪现金等等 .

    • 所以你添加了用户输入的交易 . 您可以通过添加跟踪用户输入的事务的命令来执行此操作 . 现在,我们与您的问题处于同一系统 .

    请注意,此变体接受命令和事件 . 您不会返回并将所有现有事件转换为命令,因为您现在允许用户更改内容 . 相反,您有一个系统接受外部事务事件,用户输入事务的命令和事务更正(创建修改内部状态的事件),以及组合这些内部和外部事件以在应用程序中显示的投影 .

    我很好奇 . 事后看来,接受的答案最终是一个好方法吗?或者像Greg一样直接记录和处理花店的事件会更好?

相关问题