無論有沒有軟體支援, 無論軟體是好是壞, 世界各地每個領域每天都發生著數以億計可以理解的業務
領域驅動設計是一種設計方法, 試圖解決的問題是軟體的難以理解, 難以演化. 採用的方法是圍繞業務概念來構建模型.
不過你也可以從兩個角度來理解領域驅動設計: 作為設計結果的DDD和作為開發方法的DDD, 即 What and How.
作為結果的領域驅動設計是這樣一種設計(What): 它建立了一個模型, 這個模型具有以下一些特徵:
它是用Ubiquitous Language描述的, 可以用於未必懂編程的業務專家和Team Dev之間的交流, 以及Team Dev內部的交流, 以及代碼中類和方法的名字.
它包含了業務領域中一些基本的概念, 以及概念之間的關係, 它們如何彼此合作, 完成業務領域的各種日常工作. 這些概念是與軟體無關的, 無論你有沒有用軟體來建模它們, 它們每天都出現在從業人員的頭腦中, 交談中, 公司的賬本中. 換句話說, 它反映了這個領域的知識. 任何理解了這個模型的人, 就理解了這個領域是如何運轉的.
它很少是一個大而全的模型, 因為同一件事物, 在不同的業務情境中有不同的概念, 術語, 角色. 同一份資料, 在不同的情境中也有不同的含義和解讀. 因此, 模型裡的概念按照應用情境自然的分組, 它們與另外情境中的概念的關聯則通過一種內在的映射來保持.
它是一種說明性的模型, 沒有實現細節, 因為它將軟體本身的技術複雜性分離出去, 而主要致力於描述業務領域. 這樣模型的複雜性就只由業務領域的複雜性來決定. 而通常的結果是這會使它更簡單.
這樣的模型很容易隨著業務的變化而變化, 至少不應該比業務本身的變化更困難, 更劇烈. 保守一點講, 業務領域的變化比技術領域的變化緩慢的多, 模型反映業務, 因此也穩定的多. 當業務漸層時, 模型只需跟隨做簡單的調整. 業務其實並不複雜, 無論有沒有軟體支援, 每個領域每天都實際發生著數以億計的從財務的角度可以追溯的,從從業人員的角度可以理解的, 從管理者的角度可以掌控的業務. 軟體卻難以正確表達的原因不在於業務本身多複雜, 而在於我們用的工具, 用的方法. DDD試圖分離實現(solution domain)的複雜性, 還原業務(problem domain)的簡單性, 並提供了相應的工具和方法支援.
這個模型描繪的前景是激動人心的, 但是如何? (How)? 我們需要實現技術的支援和開發過程實踐的支援
書裡描述了一些通用的構造塊(Building Block), 即實現技術的支援:
Entity, Value Object and Aggregate
Repository and Factory
Layered Architecture, Module and Service etc.
Side-effect-free-function
Intention-revealing-interface, Specification and Assertion etc.
...
當然這些構造塊並不是全部, 新的模式會不斷被開發出來 彌合分析與設計及實現之間的Gap. 這些構造塊也不是必需的. 雖然Eric在書裡說設計必須考慮實現, 但實現並不非得就是書裡提供的構造塊, 比如 Entity, Value Object, Repository. 反過來說也可以: 用了Entity, Value Object, Repository等並不一定意味著你就是在進行DDD. 事實上, 類似Entity和Value Object這樣的基本概念上的區別, Side effect free function這樣的常識, 是任何一種設計, 任何一種設計方法都應該考慮的.
而更重要的是, 開發過程中哪些實踐可以支援DDD的實現? 事實上這一部分是DDD的核心, 甚至你可以把它理解為What而不是How. 因此描述可以反過來: 我們無法保證最終能得出一個完美的領域模型, 我們只能在開發過程中儘力去改進我們手頭的模型, 然後順其自然. 因此如何改進模型才是關鍵, DDD提供了一些基本的方法來促成這種改進.
Team Dev與領域專家的合作: 頭腦風暴, 草圖, 持續學習, 知識消化...
模型作為統一語言: 捕捉語言的不一致性; 通過對話改進模型.
綁定模型與設計實現: 消除分析和設計之間的Gap; 建模人員同時負責實現
把隱含概念轉變為顯式概念: 傾聽表達用語, 檢查不協調之處, 研究矛盾之處, 查閱書籍, 不斷嘗試重構
借力分析模式
借力設計模式, 尤其是類似策略模式這樣偏重於模型概念而不是實現的模式.
更深層次的重構: 組建探索團隊, 抓住每個模型與現實不匹配的時機, 將危機視為機會.
...
然而我們通常面臨更多的現實約束, 比如我們不是每次都是從頭開始建造一個新的系統, 我們不得不與遺留系統進行整合; 也不是只有我們一個Team Dev, 我們需要與其他團隊合作. Eric將解決這部分問題的方法叫做戰略性設計(Strategic Design)
系統涉及面廣, 規模龐大: Bounded Context, Context Map, System Metaphor, Responsibility Layers, Knowledge Level
多個團隊並行開發, 彼此需要互動: Shared Kernel, Customer/Supplier Team, Conformist, Anticorruption Layer
有另外的系統(通常是遺留的)需要整合: Anticorruption Layer, 各走各路, Open Host Service, Published Language
有限的資源,無限的問題: 好鋼用在刀刃上, Distill Core Domain
這確實是最困難的一部分, 如果在戰略上選擇了不合適的方向, 則前面的構造塊, 領域模型只能算是局部最佳化. TaoWen說DDD這本書只看第四部分就可以了, 這也是一種Distill Core Domain吧.