2013-01-15 68 views
4

我正在实施使用事件采购的有界上下文,但遇到了问题。假设我正在模拟一场足球比赛,并且我对个人进球(得分等)和总成绩感兴趣。所以如果我有一个Match聚合根,我最好想要提出的事件叫做GoalScored和ScoreChanged。我希望从这个领域明确表达的分数的原因是,我不希望很多不同的听众和其他有界的上下文都计算相同的东西。事件采购链接事件

这看起来很简单,但:匹配对象有一个Goal()方法,它添加了一个新的目标。本着事件采购的精神,这不会直接改变匹配状态,但会引发一个在匹配中处理的GoalScored事件,然后突变状态(以及将事件推送到非标准化器)。因此,就提高ScoreChanged而言,直到GoalScored事件得到处理之前,得分并没有真正改变,那么我是否会针对该事件引发另一个事件(ScoreChanged),从而有效地链接事件?我不这么认为,当一个聚合根从事件存储库重新加载时开始,每次都要创建大量额外的事件来响应每个GoalScored。

我也考虑过在提高GoalScored的命令处理程序中计算得分会是多少,会出现'假设'的情况。然后我可以在命令处理程序中引发这两个事件。我真的宁愿不这样做 - 它看起来并不合适。制作足球比分足够简单,但其他比赛(例如板球)需要更多的工作。

我可以把目标和得分都放在GoalScored事件中,这足够公平,但它看起来并不正确 - 得分与GoalScored事件本身无关。

讨论事件采购时使用的所有示例似乎都使用电子商务客户/订单域,而我从未见过类似的情况。

有没有人有处理这种情况的经验?

感谢

回答

11

干净域事件的选择,就像其他的造型,应该导致了在该领域镜像概念。你说“得分与GoalScored事件本身无关”。但它确实如此。在足球方面,得分可以改变的唯一方式是如果进球。尽管可以收回目标,例如越位通话或其他处罚。目前还不清楚你是否要模拟这个模型。

域方法一次发出多个事件是很常见的。一个好的框架可以很容易地将它们看作一堆,例如作为一次提交。为什么不放出GoalScored和ScoreChanged事件?

您可能还想考虑这个域是否有任何命令。足球比赛本身就是记录系统。来自比赛的事件已经成为历史记录。你可能只是写一个处理事件流成更多事件流的系统?

+0

是的我可能会只从一个方法发出这两个事件。 该域确实有命令 - 至少如果我们正在说相同类型的命令。 StartMatch,PlayerSentOff等等。 最后一点,它看起来很像一个将事件流处理成更多事件的系统,当然也用于评分方面。 感谢您的回答。 – user303754

3

有一件事情在考虑事件采购时常常会帮助你注意你的时态 - 你说的是StartMatch,但事实上它实际上是事件MatchStarted。

至于ScoreChanged,你是否在比赛之外使用此事件?如果不是,Score应该是可公开访问的唯一部分,而GoalScored事件只是改变了这一点。这使得CQRS以小的方式存在(我如何得分并不取决于我如何改变它)。然后分数可以在内部保持一个状态,或者可以重放所有的GoalScored事件以在每次被调用时到达一个数字。设计合理的事件源解决方案的'感觉'可以始终从事件中重新生成任何状态。

现在,如果ScoreChanged需要警惕系统的其他部分(例如玩家排名),则可以将事件多播到不同的根,或者您可能需要重构设计。在这种情况下,你是想实时更新玩家,还是仅在比赛结束后才更新?