概述
當今的企業應用程式無疑是復雜的,并且依靠某些專門技術(持久性、AJAX、WEB服務器等)來完成其作業,作為開發人員,我們傾向于專注于這些技術細節是可以理解的,但事實就是,不能解決業務需求的系統對任何人都沒有用,無論它的外觀多么漂亮或其基礎架構的如何牛逼,
領域驅動設計
(DDD)的哲學是關于將我們的注意力放在應用程式的核心,專注于業務領域固有復雜性本身,我們還將核心域(對于業務而言是唯一的)與支持子域(本質上通常是通用的,例如金錢和時間)區分開來,并將我們更多設計作業適當地放在核心上,領域驅動設計由一組模式組成,這些模式用于從領域模型開始構建企業應用程式,在你的軟體職業生涯中,你可能已經遇到了許多這樣的想法,尤其是如果你是一位使用OO語言經驗豐富的開發人員,將他們一起應用將使您能夠構建真正滿足業務需求的系統,
下圖是要展現的模式和模式間關系的總圖,

代碼和模型
借助DDD,我們正在尋求創建問題域的模型,持久性,用戶界面和訊息傳遞的內容可能會在以后出現,這是需要了解的領域,從模型中去除在設計中使用的術語和所賦予的基本職責后,代碼就成了模型的運算式,所以對代碼的一個變更就可能稱為對模型的變更,
這個影響會涉及到專案的實作中,為了緊密捆綁起實作和模型,通常需要支持建模范型的軟體開發工具和語言,例如面向物件編程,面向物件編程非常適合對模型的實作,因為它們基于同一個范型,面向物件編程提供了物件的類和類之間的關聯關系、物件實體、
以及物件實體之間的訊息通信,面向物件編程語言讓建立模型物件、物件關系與它們的編程副本之間的直接映射成為可能,程序化語言提供了有限的模型驅動設計的支持,這樣的語言不能提供實作模型關鍵組件所必須的構建能力,

這是DDD模式的第一個:模型驅動設計,這意味著能夠將模型中的概念(理想情況下完全按字面意義)映射到設計/代碼的概念,模型的改變意味著代碼的改變,更改代碼意味著模型已更改,DDD并不要求你使用面向物件對域進行建模-例如,我們可以使用規則引擎來構建模型-但鑒于主要的企業編程語言是基于OO的,因此大多數模型的本質上都是OO,畢竟,OO是基于建模范例的,模型的概念將表示為類的介面,職責將表示類成員,
模型背景關系
每當我們討論模型時,它總是在一定范圍內,通常可以從使用該系統的最終用戶集合中推斷出此背景關系,因此,我們有一個部署到交易員的前臺交易系統,或一個超市收銀員使用的銷售點系統,這些用戶以特定的方式與模型的概念相關,并且模型的術語對這些用戶有意義,但對于背景關系之外的任何其他人則不一定,不是試圖保持一個遲早要四分五裂的大模型,我們應該做的是有意識地將大模型分解成數個較小的部分,只要遵守相系結的契約,整合得好的小模型會越來越有獨立性,每個模型都應該有一個清晰的邊界,模型之間的關系也應該被精確地定義,DDD將此稱為有界背景關系(BC),每個領域模型僅存在于一個BC中,而BC恰好包含一個領域模型,

我必須承認,當我第一次讀到BC時,我看不出要點:如果BC與領域模型同構,為什么要引入一個新術語?如果只有最終用戶與BC進行互動,那么也許不需要這個術語,但是不同的系統(BC)也彼此互動,發送檔案,傳遞訊息,呼叫API等.如果我們知道有兩個BC相互互動,則我們必須注意在一個概念之間進行傳換,域或其他域,
在模型周圍放置明確的邊界還意味著我們可以開始討論這些BC之間的關系,實際上,DDD標識了BC之間的一整套關系,以便我們可以合理化當我們需要將不同的BC鏈接在一起應該采取的的措施:
- 已發布的語言:互動的BC商定一種共同的語言(例如,企業服務總線上的一堆XML模式),通過它們可以彼此互動,
- 開放的主機服務:BC指定任何其他BC可以使用其他服務協議(例如Restful
Web服務); - 共享內核:兩個BC使用通用的代碼內核(例如,庫)作為通用的通用語言,但其他方式則以自己的特定方式執行;
- 客戶-供應商:一個BC使用另一個服務的服務,并且是另一個BC的利益相關者(客戶),因此,它可以影響該BC提供的服務;
- 順從者:一個BC使用另一個服務,但不是該另一個BC的利益相關者,因此,它使用原樣(符合)該BC提供的協議或API;
- 防崩潰層:一個BC使用另一方的服務,而不是利益相關者,但其目的是引入一組配接器將一個BC依賴的BC的變化所產生的影響降至最低,即反腐層,
可以看到,當我們在串列中單擊時,兩個BC之間的合作水平逐漸降低,使用已發布的語言,我們從BC開始建立它們可以互動的通用標準,他們都不擁有這種語言,而是由他們所居住的企業擁有(甚至可能是行業標準),使用開放主機,我們仍然做的不錯;BC提供了作為運行時服務的功能,供任何其他BC呼叫,但隨著服務的發展,它將(可能)保持向后兼容性,

圖 2:有界背景關系關系的頻譜
然而,當我們開始循規蹈矩時,我們只是生活在我們身邊;一個 BC 顯然是從屬于另一個的,如果我們必須與以百萬美元購買的總系統集成,那很可能就是我們所希望的情況,如果我們使用反腐敗層, 那么我們通常會與遺留系統集成,但引入一個額外的一層來盡可能地將我們自己隔離開來,當然,這需要花錢來實施,但它降低了依賴性風險,反腐敗層也比重新實施該遺留系統便宜得多,這充其量會分散我們對核心領域的注意力,最壞的情況是以失敗告終,
DDD 建議我們繪制一個背景關系映射來識別我們的 BC 以及我們依賴或依賴的那些,識別這些依賴的性質,圖 3 顯示了我過去 5 年左右一直在研究的系統的背景關系映射,

圖 3:背景關系映射示例
所有這些關于背景關系映射和 BC 的討論有時被稱為戰略 DDD,這是有充分理由的,畢竟,當你想到它時,弄清楚 BC 之間的關系都是非常政治化的:我的系統將依賴哪些上游系統,我是否容易與它們集成,我是否對它們有影響力,我是否信任它們?下游也是如此:哪些系統將使用我的服務,我如何將我的功能公開為服務,他們是否對我有影響力?誤解這一點,您的應用程式很容易失敗,
層和六邊形
現在讓我們轉向內部,考慮我們自己的 BC(系統)的架構,從根本上說,DDD 只真正關心領域層,實際上,它并沒有對其他層有很多話要說:表示層、應用程式或基礎設施(或持久層),但它確實希望它們存在,這就是分層架構模式,

圖 4:分層架構
當然,我們多年來一直在構建多層系統,但這并不意味著我們一定很擅長,確實,過去的一些主導技術 - 比如,EJB2,- 對域模型可以作為有意義的層存在的想法產生了積極的危害,所有的業務邏輯似乎都滲入了應用層或(甚至更糟的)表示層,留下了一組貧乏的領域類 [3] 作為資料持有者的空殼,這不是 DDD 的內容,
所以,絕對清楚,應用層不應該有任何域邏輯,相反,應用層負責諸如事務管理和安全性之類的事情,在某些體系結構中,它還可能負責確保從基礎結構/持久層檢索的域物件在與互動之前正確初始化(盡管我更喜歡基礎結構層來代替),
當表示層在單獨的記憶體空間中運行時,應用層還充當表示層和域層之間的中介,表示層通常處理域物件或域物件(資料傳輸物件,或 DTO)的可序列化表示,通常每個“視圖”一個,如果這些被修改,則表示層將任何更改發送回應用層,應用層又確定已修改的域物件,從持久層加載它們,然后將更改轉發到這些域物件,
分層架構的一個缺點是它暗示了依賴關系的線性堆疊,從表示層一直到基礎設施層,但是,我們可能希望在表示層和基礎設施層中支持不同的實作,如果(我認為我們是!)我們想要測驗我們的應用程式,那就肯定是這種情況:
- 例如,FitNesse [4] 等工具允許我們從最終用戶的角度驗證系統的行為,但是這些工具一般不經過表示層,而是直接進入下一層,即應用層,所以從某種意義上說,FitNesse 充當了另一種觀看者的角色,
- 同樣,我們很可能有多個持久性實作,我們的生產實作可能使用 RDBMS 或類似技術,但對于測驗和原型設計,我們可能有一個輕量級實作(甚至可能在記憶體中),因此我們可以模擬持久性,
我們可能還想區分“內部”和“外部”層之間的互動,其中內部我的意思是兩個層都完全在我們的系統(或 BC)內的互動,而外部互動則跨越 BC,
因此,與其將我們的應用程式視為一組層,不如將其視為六邊形 [5],如圖 5 所示,我們最終用戶使用的查看器以及 FitNesse 測驗使用內部客戶端API(或埠),而來自其他 BC 的呼叫(例如用于開放主機互動的 RESTful,或用于已發布語言互動的 ESB 配接器呼叫)命中外部客戶端埠,對于后端基礎設施層,我們可以看到替代物件存盤實作的持久埠,此外,我們域層中的物件可以通過外部服務埠呼叫其他 BC,

圖 5:六邊形架構
這種大規模的東西已經足夠了,讓我們多干實事,少扯虛的.
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/308444.html
標籤:領域驅動設計
上一篇:java OA系統 自定義表單 流程審批 電子印章 手寫文字識別 電子簽名 即時通訊
下一篇:代理模式(學習筆記)
