淺談DDD(領域驅動設計)

狼爺發表於2020-11-14

領域驅動設計

背景(Why)

2003 年埃裡克·埃文斯(Eric Evans)發表了《領域驅動設計》(Domain-Driven Design –Tackling Complexity in the Heart of Software)這本書,從此領域驅動設計(Domain Driven Design,簡稱 DDD)誕生。DDD 核心思想是通過領域驅動設計方法定義領域模型,從而確定業務和應用邊界,保證業務模型與程式碼模型的一致性。

但 DDD 提出後在軟體開發領域一直都是“雷聲大,雨點小”!直到 Martin Fowler 提出微服務架構,DDD 才真正迎來了自己的時代。

大部分的Java程式設計師開發生涯是從學習J2EE經典的分層理論開始的(Action、Service、Dao),在這種分層理論中,我們基本沒有啥機會使用那些所謂的“行為型”的設計模式,這裡的核心原因,就是J2EE經典分層的開發方式是“貧血模型”。

是什麼(What)

DDD,全稱Domain-Driven Design, 是一種處理複雜領域的設計思想,它試圖分離技術實現的複雜性,並圍繞業務概念構建領域模型來控制業務的複雜性,以解決軟體難以理解,難以演進的問題。它通過邊界劃分將複雜業務領域簡單化,幫我們設計出清晰的領域和應用邊界,可以很容易地實現架構演進。

DDD是物件導向的設計思想,是物件導向設計的一種昇華。

實施(How)

DDD的實施分戰略設計與戰術設計

  • 戰略建模:戰略設計主要從業務視角出發,建立業務領域模型,劃分領域邊界,建立通用語言的限界上下文,限界上下文可以作為微服務設計的參考邊界。戰略建模是以一種最巨集觀的角度去審視整個專案對它進行拆分,來劃分“界限上下文”,最終形成一個具有俯瞰視角的“上下文對映圖”。
  • 戰術建模:戰術設計則從技術視角出發,側重於領域模型的技術實現,完成軟體開發和落地,包括:聚合根、實體、值物件、領域服務、應用服務和資源庫等程式碼邏輯的設計和實現。

在實施過程中,我們需要明確“通用語言”,通用語言和限界上下文(Bounded Context)同時構成了DDD的兩大支柱,並且它們是相輔相成的。

通用語言是以一種領域專家、設計人員、開發人員都能理解的語言作為相互交流的工具,在不斷交流的過程中發現和挖出一些主要的領域概念,然後將這些概念設計成一個領域模型。由領域模型驅動軟體設計,用程式碼來表現該領域模型。領域需求的最初細節,在功能層面通過領域專家的討論得出。

領域模型貫穿軟體分析、設計,以及開發的整個過程;領域專家、設計人員、開發人員通過領域模型進行交流,彼此共享知識與資訊;因為大家面向的都是同一個模型,所以可以防止需求走樣,可以讓軟體設計開發人員做出來的軟體真正滿足需求。

在這個過程中,需要業務專家的參與,他們才是最懂業務的人,他們能用他們已有的對這個領域的知識,與我們一起設計開發系統,讓我們的系統更符合實際需要。典型的例子,在設計一個系統時,如果兩個物件或模型有關聯關係,那麼這個關聯關係是一對多、一對一還是多對多,有時我們並不能很好的判斷出來,這個時候就需要領域專家應用他們的知識來幫助我們一起處理這部分的設計。

領域專家並不是一個職位,他可以是精通業務的任何人。可能是軟體產品的設計者,甚至可能是銷售員。

在設計的過程中,我們書面設計的文件不可能面面俱到,應儘量將文件減至最少,並且主要用它來補充程式碼和口頭交流,解釋我們模型中的概念,避免文件與專案脫節,設計的重要細節應該在程式碼中體現出來。

區別

那麼DDD跟我們平時面向資料庫程式設計,使用SpringMVC又有什麼區別呢?
下面以一個例子作為說明。
在以往的專案中,我們接到了一個需求,我們會分析需求,然後設計我們的資料庫表,設計DO、DAO、service、controller等,會把業務邏輯的實現寫在service,假設在編碼的過程中,我們發現多個service中有重複的業務邏輯,我們一般的做法有抽取方法到BaseXXX中,或者向下封裝抽離一層manager等處理方式,然後大家一起呼叫公共的方法。
而使用DDD,會先設計出模型,同時模型是具備業務邏輯,在遇到有重複的業務邏輯時,我們考慮的是這部分的邏輯應該屬於哪個模型的,它屬於哪個限界上下文的,DDD中的模型不僅僅只是承載屬性,他還有自己的邏輯,比如業務引數校驗。

參考資料

相關文章