我实际上正在阅读一本名为“DDD in PHP”的书,以帮助我理解域驱动设计。到目前为止一切都很好,但我很难理解如何在不耦合有界上下文的情况下实现一个特定主题:域事件
假设我必须参加BC:
当放置Order
时,将调度OrderCreated
事件。
Payments
BC与订阅者一起捕获此事件,并创建发票。
问题是,如果我想将两个BC完全分开,那么OrderPlaced
事件应该在哪里,因为它被两个BC使用?它应该住在两个BC之外吗?在他们两个?如果我想将Invoices模块作为独立模块部署,而无需访问Orders模块及其OrderPlaced事件定义,会导致一些致命错误,该怎么办?
提前感谢您的答案!
答案 0 :(得分:2)
问题是,如果我想完全分离两个BC,OrderPlaced事件应该在哪里存在,因为它被两个BC使用?它应该住在两个BC之外吗?在他们两个?
我会将事件存储在拥有它的上下文中,即Orders上下文。你打算如何分离上下文?它是物理/网络边界分离,还是只是概念?
如果我想单独部署Invoices模块而无法访问Orders模块及其OrderPlaced事件定义会导致一些致命错误,该怎么办?
这取决于您使用OrderPlaced做什么。如果您从某种事件流订阅它,然后通过将其转换为内部到发票概念的方式在InvoicesBC内对其做出反应,那么您可能会很好,因为您可能无法部署订阅者。如果InvoicesBC中的代码无需了解OrderPlaced即可运行,那么您应该没问题
一般来说,有几种方法可以解决这个问题:
答案 1 :(得分:1)
虽然答案已经被接受,但我还是想加上我的观点:)
您当前的BCs集成方式是直接订阅发布的消息:Payments
订阅OrderCreated
。这种交互方式称为编排。这不一定是坏事,但你必须权衡利弊。例如,当您需要在中间添加一个步骤时,您可以让Address
BC订阅OrderCreated
,以便它可以验证传递地址。现在Payments
BC必须订阅AdressValidated
事件。但是再一次,这个事件发布了很多,因为我们在注册客户时也使用它。嗯...
另一种选择是使用 orchestration ,您可以在其中明确存储相关流程的状态。您有OrderProcess
和CustomerOnboardingProcess
。然后,您可以让当前的BCs仅处理其BC内的消息。然后,另一个进程 BC将协调消息并跟踪状态。
编舞可能遇到的另外两个问题是:
我希望这是有道理的。
答案 2 :(得分:0)
问题是Payments
BC是否必须创建发票,因为顾名思义,它应该是payments
而不是orders
或invoices
。
也许是这样的:
Orders -> 'order created' -> Payments -> 'payment done' -> Orders -> 'invoice created'