1. 程式人生 > >領域驅動設計(DDD)部分核心概念的個人理解

領域驅動設計(DDD)部分核心概念的個人理解

  1. 領域驅動設計(DDD)是一種基於模型驅動的軟體設計方式。它以領域為核心,分析領域中的問題,通過建立一個領域模型來有效的解決領域中的核心的複雜問題。Eric Ivans為領域驅動設計提出了大量的最佳實踐和經驗技巧。只有對領域的不斷深入認識,才能得到一個解決領域核心問題的領域模型。如果一個應用的複雜性不是在技術方面的,而是在領域本身,即領域內的業務很複雜,那這種應用,使用領域驅動設計的價值就越大。
  2. 領域驅動開發也是一種敏捷開發過程(極限程式設計,XP),強調迭代開發。在迭代過程中,強調開發人員與領域專家需要保持密切的合作關係。極限程式設計假設我們能通過不斷快速重構完善設計。所以,對開發人員的要求非常高。
  3. 領域驅動設計提出了一套核心構造塊(Building Blocks,如聚合、實體、值物件、領域服務、領域工廠、倉儲、領域事件,等),這些構造塊是對面向物件領域建模的一些核心最佳實踐的濃縮。這些構造塊可以使得我們的設計更加標準、有序。
  4. 統一語言(Ubiquitous Language),是領域驅動設計中一個非常重要的概念。任何一個領域驅動設計的專案,都需要一種通用語言,一套通用的詞彙。因為沒有通用的語言,就沒有一致的概念,溝通就會遇到障礙,最後的領域模型和軟體也就無法滿足領域內的真實業務需求。通用語言是領域專家和開發人員在對領域問題的溝通、需求的討論、開發計劃的制定、領域模型的設計,以及開發人員之間對領域模型的具體編碼落地實現,等一系列過程中,所有人員使用的一種通用語言。話句話說,就是無論是溝通時所用的詞彙、還是領域模型中的概念、還是程式碼中出現的類名與方法,只要是相同的意思,那就應該使用相同的詞彙。可以看出,這種通用語言不是一下子就可以形成,而是在一個各方人員討論的過程中,不斷髮現、明確,與精煉出來的。
  5. 領域模型是領域驅動設計的核心。統一語言中的所有關鍵詞彙,在領域模型上應該都能找到。各方人員溝通時,都應該以領域模型為基礎。通過討論的不斷深入,大家對領域的認識也會不斷深入,領域模型也會不斷得到完善,統一語言的詞彙也會不斷豐富和精準。需要特別強調的是,開發人員應該儘量保證程式碼實現和領域模型相繫結,時刻保持程式碼與模型的一致。如果不繫結,那程式碼就會慢慢和模型相脫節,就會出現像我們以前那樣的設計文件和程式碼相脫節一樣的問題,甚至模型還會起到誤導作用。通過這樣一種思路,我們確保語言、模型、程式碼三者緊密繫結,確保最後實現出來的軟體可以準確無誤的實現業務需求,並且還能讓我們的軟體可以快速的和業務同時演進。而不像傳統的開發方式那樣,分析、設計、實現三個階段完全脫節,最後出來的軟體沒有很好的滿足業務需求,也不能在未來很快的跟業務需求一起演進。所以,領域模型同時承載了分析的結果和設計的結果,這裡的分析是指對領域內業務需求的分析,設計是指對模型的設計以及軟體的設計。所以,我們的領域模型,不能只考慮業務需求,還要同時考慮軟體設計的原則,是一種綜合考慮的、平衡的設計結果。
  6. 領域模型可以複用,因為特定的領域模型解決的都是某個特定的問題域;比如淘寶網有個商品中心,有個商品模型,核心概念有商品分類、商品;商品模型負責解決電子商務領域中的商品目錄(Product Catalog)子域。後來阿里又出了個天貓,也會有商品中心,但是這兩個商品中心基本是一樣的問題域。所以,我們可以複用之前淘寶實現的商品中心領域模型,並複用之前淘寶商品中心的解決方案,來解決天貓的商品維護和展示。當然,這個只是我個人的認識,一個例子。具體阿里是否是一個商品中心同時解決淘寶和天貓的業務,沒具體調研過。
  7. Bounded Context,屬於一種軟體構件,作用是用來對領域模型進行劃分。Bounded Context有兩層含義:
    • Bounded,即有邊界的,表示領域模型有邊界;這個邊界定義了模型的適用範圍,以便讓負責該模型的團隊知道什麼該在模型中實現,什麼不該;
    • Context,即領域模型的產生是在某個上下文中產生的;上下文是一個和環境相關的概念。比如一次頭腦風暴會議大家達成了一個模型,那這次會議的討論就是該模型的上下文;比如某本書中談到了某個東西,那這個東西的上下文就是那本書,那個東西要有意義的前提離不開那本書這個上下文;所以,上下文是模型有意義的前提;
  8. 領域建模的方法有很多種,我分享一下自己的一種基於場景為核心的分析方法。大概的思路是:
    • 通過與領域專家和業務需求人員溝通,找出領域中的關鍵業務場景;
    • 針對每個業務場景分析出有哪些場景參與者,哪些參與者以物件(聚合)的形式參與,哪些參與者以服務的形式參與;
    • 分析每個場景參與者物件的基本狀態特徵;
    • 分析每個場景參與者物件分別扮演什麼角色參與場景,整個場景的完整互動過程是怎樣的,物件在參與場景的過程中執行了哪些互動行為;
    • 分析如何記錄和跟蹤這一次互動行為,分析這次互動行為會產生哪些額外的資訊;
    • 上面,只是簡單列了一下條目,具體的描述,請參看我的另一篇文章,有詳細的敘述。
  9. 關於領域(Domain)、領域模型(Domain Model)、邊界上下文(Bounded Context)的關係
    • 領域就是問題域,問題空間;
    • 領域模型是一種模型,表達了領域中哪些業務需求以及業務規則必須被滿足;
    • 每一個領域中的問題,都會有一個對應的領域模型去解決;
    • Bounded Context的作用是用來對領域模型進行劃分;
    • 劃分領域就是對問題空間的劃分,通俗的理解,就是將大問題拆分為小問題;
    • 劃分Bounded Context就是將一個大的領域模型劃分為多個小的領域模型;
    • 可以把Bounded Context看成是一種解決方案空間,所以,Bounded Context也可以理解為是對解決方案空間的劃分;
    • 理論上,一個Domain可能會對應多個Bounded Context;同樣,一個Bounded Context可能也會對應多個Domain;所以他們之間沒有絕對的關係。主要是他們劃分的依據不同,一個是針對領域(問題空間),一個是針對領域模型(解決方案空間);理想情況,一個Domain最好對應一個Bounded Context;
  10. 關於Domain、Sub Domain、Core Domain、Generic Domain,以及Shared Kernal的理解:
    • 一個領域(Domain)會拆分為多個子領域(Sub Domain);
    • 子領域中最核心(最重要)的那個叫Core Domain;我們應該講團隊的核心資源用在核心子域上,因為它是產品成敗的關鍵;
    • 除了Core Domain外,其他的是支撐子域(Supporting Subdomain);
    • 有些支撐子域比較特殊,因為它解決的是一類通用問題,比如賬號和許可權;這類子域我們叫做通用子域(Generic Subdomain);通常,通用子域對應的Bounded Context,會跨域多個子域;
    • 多個子領域有時會有相交的部分,我們稱作共享核心(Shared Kernel);體現到程式碼上,就是同一份程式碼,在兩個領域模型中複用;
    • 一般只有Domain比較大的時候,我們才會劃分出Sub Domain;
  11. 為什麼一個大的領域模型需要劃分?因為,通常一個大的領域模型需要多個團隊合作完成。如果多個團隊基於一個共同的領域模型工作,由於每個團隊的關注點不同,且一些看似叫法一樣的概念,對於不同的團隊,其背後的意思完全不同。所以,這樣的概念含義模糊會給團隊以及成員之間的合作帶來很大的困擾。所以,我們需要通過一種手段(Bounded Context),將領域模型劃分為不同的部分,確保同一個Bounded Context內的領域模型所表達的概念含義明確。然後,同一個Bounded Context下面,相關人員都使用一種統一的語言,以此來保證團隊成員之間溝通能暢通無阻;

相關推薦

no