1. 程式人生 > >DDD(7)--瞭解領域事件

DDD(7)--瞭解領域事件


1、引言

繼領域服務之後繼續學習領域事件,那麼我們要知道領域事件的作用又是什麼?為什麼要使用領域事件?

領域專家所關心的發生在領域中的一些事件。將領域中所發生的活動建模成一系列的離散事件。每個事件都用領域物件來表示...領域事件是領域模型的組成部分,表示領域中所發生的事情。

當領域事件確定下來時,領域事件便是通用語言的正式組成部分。


2、瞭解領域事件

一個領域事件可以理解為是發生在一個特定領域中的事件,是你希望在同一個領域中其他部分知道併產生後續動作的事件。但是並不是所有發生過的事情都可以成為領域事件。一個領域事件必須對業務有價值,有助於形成完整的業務閉環,也即一個領域事件將導致進一步的業務操作。

領域事件可以是業務流程的一個步驟,例如訂單提交,客戶付費100元,訂單完成等。領域事件也可以是定時發生的事情,例如每晚對賬完成。或者是一個事件發生後引發的後續動作,例如客戶輸錯密碼三次後發生鎖定賬戶的事件。

如果在通用語言中存在“當a發生時,我們就需要做到b。”這樣的描述,則表明a可以定義成一個領域事件。領域事件的命名一般也就是“產生事件的物件名稱+完成的動作的過去式”的形式,比如:訂單已經發貨的事件(OrderDispatchedEvent)、訂單已被收貨和確認的事件(OrderConfirmedEvent)等。

如何實現支付訂單成功,更新訂單狀態為已支付,扣減庫存,並推送撿貨通知資訊到撿貨中心。傳統思想肯定是簡單直接的方法呼叫,在一個事務中分別去呼叫狀態更新方法、扣減庫存方法、傳送撿貨通知方法。

那這樣設計有問題嗎?

試想一下,若現在要求支付成功後,需要額外發送一條付款成功通知到微信公眾號,怎麼實現?想必我們需要額外定義傳送微信通知的介面並封裝引數,然後再新增對方法的呼叫。這種做法雖然可以解決需求的變更,但很顯然不夠靈活耦合性強,也違反了OCP。

OCP Open-Closed Principle軟體設計中的“開-閉原則”,一個軟體實體應當對擴充套件開放,對修改關閉.也就是說,我們在設計一個模組的時候,應當使這個模組可以在不被修改的前提下被擴充套件,換句話說就是,應當可以在不必修改原始碼的情況下改變這個模組的行為.

將多個操作放在同一個事務中,使用事務一致性可以保證多個操作要麼全部成功要麼全部失敗。在一個事務中處理多個操作,若其中一個操作失敗,則全部失敗。但是,這在業務上是不允許的。客戶成功支付了,卻發現訂單依舊為待付款,這會導致糾紛的。

違反了聚合的一大原則:在一個事務中,只對一個聚合進行修改。在這個用例中,很明顯我們在一個事務中對訂單聚合和庫存聚合進行了修改。

那如何解決這些問題?我們可以藉助領域事件的力量。

3、為什麼需要領域事件

上面所舉的例子,按照傳統的方式去開發,會導致系統高耦合。

如果改為事件驅動模式,把訂單提交後觸發一個事件,在訂單儲存後,觸發訂單提交事件。通知和後續的各種服務動作可以通過訂閱這個事件,在自己的實現空間內實現對應的邏輯,這樣就把訂單提交和後續其他非主要活動從訂單提交業務中剝離,實現了訂單提交業務高內聚和低耦合性和系統可擴充套件性。

4、小結

上一章說到領域服務處理業務,比較容易程式碼耦合,領域事件解耦,所以可以確定的是領域事件是領域服務中重要的組成部分。並且我們要知道,領域事件是用來處理已經發生的事情,比如訂單狀態改變後,商品新增到購物車後這類事件。而且不是所有的事件都要建模領域事件,只有有價值的業務才建模領域事件。領域事件是需要跟蹤的、希望被通知的、會引起其他模型物件改變狀態的,發生在領域