DDD 領域驅動設計學習(三) 領域事件

2021-10-09 18:07:53 字數 3317 閱讀 8868

在eric的《領域驅動設計》中並沒有提到領域事件,領域事件是在後來才被正式提出來的,並成為ddd通用語言(ul)的正式組成部分。領域事件(de)是什麼?領域事件的作用又是什麼?

介紹領域事件的書籍和文章也比較多了,本文最後也推薦了幾篇很好的文章。寫這篇文章更希望多思考一下自己的一些疑問,乙個是為什麼要用領域事件?領域事件和一般事件驅動的區別是什麼?順便也想理一下event相關的幾個概念和工具。

在《實現領域驅動設計》一書中對領域事件的定義如下:

領域專家所關心的發生在領域中的一些事件。

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

martin fowler對領域事件的定義是:「重要的事件肯定會在系統其它地方引起反應,因此理解為什麼會有這些反應同樣也很重要。」

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

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

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

領域事件也是一種基於事件的架構(eda)。事件架構的好處可以把處理的流程解耦,實現系統可擴充套件性,提高主業務流程的內聚性。

舉例而言:使用者提交乙個訂單,系統在完成訂單儲存後,可能還需要傳送乙個通知,另外可以產生一系列的後台服務的活動。如果把這一系列的動作放入乙個處理過程中,會產生幾個的明顯問題:

乙個是訂單提交的的事務比較長,效能會有問題,甚至在極端情況下容易引發資料庫的嚴重故障;另外訂單提交的服務內聚性差,可維護性差,在業務流程發生變更時候,需要頻繁修改主程式。

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

領域事件也繼承了事件的作用,當領域中發生了一些活動後,通過領域事件可以把這些活動所產生的***顯式而不是隱式的表達出來,這種影響可以影響乙個或多個聚合物件,而且可以獲得更好的擴充套件性,對資料的鎖影響也更小。

既然領域事件是一種事件,領域事件獨特之處又在**?

個人的理解:

首先是解決領域的聚合性問題。ddd中的聚合有乙個原則是,在單個事務中,只允許對乙個聚合物件進行修改,由此產生的其他改變必須在單獨的事務中完成。如果乙個業務跨多個聚合物件,領域事件會是乙個不錯的工具來解決這個問題。通過領域事件的方式可以達到各個元件之間的資料一致性,通過最終一致性取代事務一致性。

其次領域事件也是一種領域分析的工具,有時從領域專家的話中,我們看不出領域事件的跡象,但是業務需求依然有可能需要領域事件。動態流的事件模型加上結合ddd的聚合實體狀態和bc,可以有效進行領域建模。

領域事件可以通過觀察者模式和訂閱模式進行實現。比較常見的實現方式是事件匯流排(event bus)。

事件風暴也被稱為事件建模,形式有點類似於頭腦風暴的方法,通過事件風暴的方法可以快速分析複雜業務領域,完成領域建模的目標。

事件風暴是一項團隊活動,旨在通過領域事件識別出聚合根,進而劃分微服務的限界上下文。在活動中,團隊先通過頭腦風暴的形式羅列出領域中所有的領域事件,整合之後形成最終的領域事件集合,然後對於每乙個事件,標註出導致該事件的命令(command),再然後為每個事件標註出命令發起方的角色,命令可以是使用者發起,也可以是第三方系統呼叫或者是定時器觸發等。最後對事件進行分類整理出聚合根以及限界上下文。

事件風暴建模是一種基於領域驅動設計ddd的業務建模方式,它能夠直接分析動態業務流程,克服以往靜態結構分析方法的侷限性。

所謂靜態結構分析方法,主要表現為使用資料表結構來表達業務需求,雖然也有使用uml等物件導向的分析設計方法,但人們的分析思維還是拘泥於靜態類圖分析,例如ddd分析結果主要以產出類圖為主、順序圖或狀態圖等動態分析往往被忽視。

事件建模還是一種全新的動態思維方式,代表思維方向的轉變,是由「靜」到「動」的轉變。

事件風暴方法通常有以下幾個步驟:

邀請合適的人參加

提供無限制的建模空間

發掘領域事件,可使用橙色貼紙標識

發掘領域事件的**,探詢命令,可使用藍色貼紙標識。多種**也可以考慮用不同顏色來區分,例如用黃色表示角色,粉色表示外部系統,紅色表示時間觸發。

尋找聚合,可用綠色貼紙標識

持續探索,發掘子域,bc,使用者角色,驗收測試標準,補充資訊等。

事件風暴的步驟可以如下圖所示:

在我們的一次產品的重構活動中也採用了事件風暴方法。系統**維護了10幾年,**中存在大量的「壞味道」:重複**,過長函式,過大的類,過長的引數列表,發散式變化,霰彈式修改,鍍金問題,注釋不清等問題。實際研發過程中也是經常出現一點改動都可能會引起不可**的結果,重構勢在必行。

但是在重構過程中,也沒有人可以說清楚現有系統的邏輯,如何重構成為了乙個難題。重構過程我們引入了諮詢公司給我們的方法,採用了事件風暴的辦法,通過對領域中所發生的事情(也就是領域事件)來探索這個領域,並且使用便簽來描述領域中的事件,這些便簽會沿著時間軸貼到乙個很大的建模面板上。

舉例來說,能夠引發事件的事情包括使用者行為、外部系統所發生的事情以及時間的流逝。事件也有助於找到領域的邊界,對術語的不同闡述可能就意味著存在邊界。

準備工作,四色貼紙:

橙色:事件,某個動作的結果,以「xx已xx」的方式表示,比如「使用者資訊已查詢」

藍色:屬性,事件相關的輸入、輸出資料等

黃色:命令,某個動作,比如「查詢使用者資訊」

綠色:實體,命令的觸發者

開始梳理業務,將結果貼到白版上

繼續深入梳理,將整個過程的模型、關鍵資料等梳理出來,貼在白板上

確定重構指導思路,執行重構動作,重構的同時引入單元測試保障重構的質量

DDD領域驅動設計

公司裡面敏捷專案要講ddd領域驅動設計,加緊學習了一下,找了一些資料研究。eric evans的 domain driven design領域驅動設計 簡稱ddd,evans ddd是一套綜合軟體系統分析和設計的物件導向建模方法,本站jdon.com是國內公開最早討論ddd 之一,可訂閱 ddd專題...

DDD(領域驅動設計)

domain 領域 driven 驅動 design 設計 由eric evans最先提出,目的是對軟體所涉及到的領域進行建模,以應對系統規模過大時引起的軟體複雜性的問題。整個過程大概是這樣 開發團隊和領域專家一起通過 通用語言 ubiquitous language 去理解和消化領域知識,從領域知...

DDD領域驅動設計

極客時間學習筆記 為什麼微服務設計的時候需要ddd?1 軟體架構模式演進的三個階段 第一階段是單機架構 第二階段是集中式架構 第三階段是分布式微服務架構 2 在單機和集中式架構這兩種模式下,軟體無法快速響應需求和業務的迅速變化,最終錯失發展良機。3 微服務拆分困境產生的根本原因就是不知道業務或者微服...