核心領域(Core-Domain)
為了使領域模型成為企業真正的資產, 模型中的關鍵核心部份需要足夠靈活和充分利用來創建應用程序的功能; 簡而言之, 核心領域是系統中最有價值的部份.
濃縮模型, 將最有價值, 最體現專門知識的概念突顯出來, 並開發出滿足系統願景的柔性設計.
核心領域取決於個人的觀點, 也是通過反複迭代來確定的.
精煉的逐步升級
應用以下的技術沒有嚴格的順序要求, 但不同的技術對設計產生的影響會有所不同:
領域願景聲明(Domain Vision Statement): 描述領域的基本概念與價值.
突出核心(Highlighted Core): 增進交流並指導我們的決策.
隔離核心(Segregated Core): 重新封裝使核心更清晰.
抽象核心(Abstract Core): 以抽象形式表達基本的概念與關系, 並對模型進行大面積的重組和重構
通用子域(Generic Subdomains)
通用子域可能是系統中一些通用元素, 與主要目標無關的輔助功能, 但對系統的功能卻是不可或缺的; 它所抽離出來概念也是與其他商業應用同樣需要的概念, 但別讓它們包含任何的專業領域知識.
對於通用子域的開發可採用現成的解決方案或公開的模型.
一個子域具有通用性, 並不代表它的代碼具有重用性, 通用子域主要是要滿足某些特地需求, 不應該去關注它的代碼重用性, 盡可能的將精力投入在核心領域.
應避免為了可重用性而設計, 但必須嚴格遵守通用概念的思想.
項目面臨的風險來自兩方面:(1) 技術風險 (2) 領域建模風險
領域願景聲明:
以約一頁緍的篇幅簡短描核心領堿及其帶來的價值(價值主張, value proposition), 說明領域模型如何維護和平衡各方利益, 並為開發團隊指明了一個共同開發的方向突出核心(Highlighted Core)
突出核心(Highlighted Core)
我們需要對模型有全面性的了解, 因此核心領域必須要顯而易見.
精煉文檔可使用UML或順序圖..等. 但它並不是一份完全設計的文檔, 只是提供最低限度的要求. 寫一份"非常簡短"(3~7頁)的文檔, 集中描述核心領域及核心元素之間的主要交互作用.
將模型倉庫中的核心領域的元素標記起來, 而不是去闡述它們的任務.
精煉文檔給出核心領域主要的輪廓, 若模型或代碼的改變影響到精煉文檔, 那麼就需與其他團隊協商, 在改變實施後需立即通知團隊所有成員, 並發布新版的精煉文檔.內聚機制(Cohesive Mechanisms)
模型中的概念應用"是什麼(what)"來解釋, 而不是"怎麼做(how)".
將(算法)概念上的內聚機制分離到一個獨立的輕量型框架, 用一個釋意接口說明該框架的功能, 現在領域中的其他元素可以集中描述問題"是什麼"了, 而"怎麼做"的細節交給框架去完成.
通用子域v.s. 內聚機制所承担責作的不同在於:
通用子域: 團隊應如何看待領域中一些的方面, 這點與核心領域無異, 但它沒有核心領域這麼重要與專業化.
內聚機制: 不是用來表示領域, 而是負責解決一些由描述性模型提出的棘手(計算)問題.
總而言之, 模型提出問題, 內聚機制解決問題若機制本身就是一項資產, 或屬於軟體價值的一個關鍵部份, 那麼就是一種例外.(ex: 排班演算法?)
精煉到聲明性風格
精煉的價值是在於能看到正在做的工作, 而不受不無關的內容干擾, 直指系統本意
隔離核心(Segregated Core)
重構模型, 將核心概念與輔助概分離開來, 加強核心的內聚力, 同時減少核心與其他的代碼的聯系.
分離隔離核心步驟如下:
(1) 確定一個核心子域
(2) 把相關類移至新的模塊, 並為模塊指定一個與概念相符的名稱
(3) 重構代碼, 將無法直接表示核心概念的數據或方法分離出來, 盡量把它們放在概念上相關的模塊中, 但別花太多時間,
把工作重點放在精煉核心子域上, 核心子域對其他的模塊引用必須突出明確.
(4) 對得到的隔離核心重構, 使其中關係與交互作用簡單易懂, 同時減少它與其他模塊的關係(此步驟的重點)
(5) 對其他核心子域重複以上步驟.
對核心進行隔離有時會破壞原本的非核心類之間緊密聯系, 使之變的模糊甚至複雜, 但它可使核心領域更加清晰, 更容易處理.
由於核心領域和設計中的其他部份一樣是不斷演進的, 團隊成員對哪些是核心元素, 哪些是輔助元素也會產生新的認識, 而這些認識應該反饋到核心領域和隔離核心模塊中來, 使它們的定義得到進一步精化.
團隊內部溝通必要非常高效, 保證每個人對核心認識都是一致的抽象核心(Abstract Core)
當不同模塊的子塊之間有很多交互作用時, 要嘛引用, 要嘛只能間接實現這些交互作用. 前者喪失了劃分模塊的很多優點, 後者會使模型變的難以理解.
找出模型中最根本的"概念", 並把它們分離為不同具體類, 抽象類或接口. 設計一個抽象模型來表重要組件間的大部分交互作用. 把這個抽象的網領性模型放在它自己的模塊中, 而那些專用的, 具體的實現類則放在由其子域的模塊中.