在複雜領域中設計軟體:領域驅動設計 - levelup

banq發表於2022-07-08

軟體的核心是處理和解決可用的業務上下文和問題。今天的企業業務領域通常是龐大而複雜的,並且正在增長/變化——以及接受這種增強的軟體。領域驅動設計 (DDD) 是一種軟體開發方法,其中軟體工件與核心業務概念和目標完全一致。
領域驅動設計由Eric Evans在他的《領域驅動設計:解決軟體核心的複雜性》一書中提出。它由模式、原則和集合組成,使團隊能夠專注於業務成功的核心。
“領域驅動設計 (DDD) 是一種通過將實現與核心業務概念的演變模型深度連線來開發複雜需求的軟體的方法” — http://dddcommunity.org

建模問題域——戰略 DDD
戰略 DDD 側重於高階架構設計決策。它涉及對業務流程進行建模、將域分解為子域以及它們之間的整合模式。無處不在的語言、有界上下文和上下文對映是領域戰略圖景的關鍵組成部分。

無處不在的語言——提煉領域知識
與領域專家的持續合作是戰略設計的核心,以理解和傳達領域見解。領域概念需要在利益相關者(領域專家、開發人員、產品經理、設計師)之間以相同的術語、含義和上下文進行交流,而不會產生歧義。
最終目標是在對話中建立術語/語言的一致性,以建立反映通訊語言的模型/程式碼。例如,如果您需要在訂閱期間定義建立使用者的方法,請使用方法名稱signupForSubscription而不是create方法。
有效的領域建模者是優秀的知識處理器。有關無處不在的語言的發展和挑戰,請參閱此處

在複雜領域中設計軟體:領域驅動設計   - levelup

限界上下文——大而複雜的領域?分而治之
“哪裡出了問題,就是太大了”——利奧波德·科爾
一個複雜的領域模型可以分成更集中的領域來管理複雜性並帶來設計和執行的靈活性。為了劃分(和征服)複雜的域,我們需要建立一個邏輯邊界來分解為子域。子域是反映組織業務流程的問題空間的一部分。
在這篇博文中,我們將考慮一個典型的電子商務應用程式示例——

在複雜領域中設計軟體:領域驅動設計   - levelup
有多個子域(核心、支援或通用)。為了解決這個問題,我們引入了限界上下文Bounded Context ,它是特定領域模型一致適用的子領域適用性的有形邊界。

在複雜領域中設計軟體:領域驅動設計   - levelup
讓我們考慮兩個有界上下文——付款和運輸。在支付上下文中,客戶代表信用卡資訊、稅率、公司編號和賬單地址等屬性。在運輸上下文中,客戶資料可以是送貨地址、送貨時間偏好。這兩個上下文的術語(語言)和領域專家可以是不同的。

在複雜領域中設計軟體:領域驅動設計   - levelup
上圖是同一個物件攜帶不同的上下文

識別域中的限界上下文
領域知識的深度洞察對於識別限界上下文至關重要。業務相關性、自主性、語言邊界、資料流以及與其他上下文的關係是識別有界上下文的線索。事件風暴(用於高階概述的研討會方法)和限界上下文畫布(用於設計和文件的工具)有助於探索限界上下文。
上下文對映
有界上下文在實現業務目標方面不是獨立的。需要它們之間的整合。上下文對映是對系統的不同有界上下文之間的關係進行識別、分類和視覺化描述的過程。下圖顯示了不同的上下文對映模式。

在複雜領域中設計軟體:領域驅動設計   - levelup
上圖是上下文對映模式(圖片來源:https ://github.com/ddd-crew )

戰術設計模式——在有界上下文中塑造程式碼
戰術設計模式是在程式碼級別實現有界上下文的指南。需要精確定義域模型並在有界上下文中應用。

  • 實體:實體是具有唯一標識(資料庫中的主鍵或系統生成的 ID)的物件,該標識隨時間持續存在。客戶可以是電子商務應用程式中具有名稱、電子郵件和地址屬性的實體。
  • 值物件:沒有身份的物件,純粹由其屬性定義。讓我們考慮一個貨幣價值物件 - 100 AUD。這個值物件是可比較的(可以與 比較90 USD)、不可變的(建立一個新的而不是替換它)和自我驗證器(不能有一個25 ABC無效貨幣的值物件)。
  • 聚合:聚合是定義事務一致性邊界的實體和值物件的封裝。假設你有一個OrderwithOrderInfo和OrderItems。更改OrderInfo可能會更改訂單的狀態。同樣,訂單總量可以隨著變化而變化,OrderItems所有這些都有一個嚴格的事務邊界,需要始終保持一致。一起,Order和OrderInfo形成OrderItems一個聚合體。聚合中的確切一個實體是其識別符號用於查詢的根。根實體的子實體通過來自根的以下指標來引用。
  • 儲存庫和工廠:工廠用於通過提供實體和值物件來建立新的聚合。儲存庫提供了訪問持久儲存的邏輯封裝。


分層架構
每個有界上下文都被劃分為以下有凝聚力的水平層。

使用者介面
該層為使用者提供介面。該層負責顯示資料和捕獲使用者命令。

應用層
業務流程在這一層處理。域實體在此處建立並進行更新。

領域模型層
域的資料和行為在域模型中進行概念建模。這裡定義了實體、值物件、聚合、工廠和介面來表達領域規則和邏輯。領域模型的設計通常不依賴於其他層、第三方或持久層。然後應用層協調這些決策。領域模型層和應用層分離的細節參考這裡

基礎設施層
最初儲存在域實體中的資料被持久儲存在資料庫或另一個持久儲存中。

在複雜領域中設計軟體:領域驅動設計   - levelup

程式碼實現



DDD什麼時候適用?
DDD 不僅僅是一個編碼配方。它是關於有助於需要理解業務語義(概念和行為)的系統的戰略思維方式。然而,這不是一個全有或全無的交易。我們可以根據您的專案實施這些想法(戰略或戰術方法)。DDD 方法可能不適合以 CRUD 為中心的系統。

DDD 和微服務
微服務是一種架構模式,用於通過鬆散耦合、可獨立部署、小型且可重用的服務(微單元)來設計應用程式。DDD 有助於通過“有界上下文”來保持服務範圍較小。單個有界上下文通常對映到一個微服務,但它可以具有一對多的關係。DDD 有助於識別子域和上下文對映,這有助於微服務之間的通訊。
Uber 實現了基於 DDD的面向領域的微服務架構 (DOMA) 。您可以在此處找到設計面向 DDD 的微服務的指南。

處理單體
單片應用程式非常適合開始。隨著產品的發展,它會變得難以管理,我們需要進入SOA。這種過渡可以通過基於 DDD 的中間模組化方法來促進。

應用 DDD 的挑戰
應用 DDD 時的一些常見挑戰包括建立通用語言的時間和精力、領域專家一開始的需求、抽象開銷、事務管理、領域建模的合理性。

相關文章