關(guān)于我們
書單推薦
新書推薦
|
實現(xiàn)領(lǐng)域驅(qū)動設(shè)計(DDD之父作序力薦 讓DDD思想真正落地的首創(chuàng)巨著)
領(lǐng)域驅(qū)動設(shè)計(DDD)是教我們?nèi)绾巫龊密浖,同時也是教我們?nèi)绾胃玫厥褂妹嫦驅(qū)ο蠹夹g(shù)的。它為我們提供了設(shè)計軟件的全新視角,同時也給開發(fā)者留下了一大難題:如何將領(lǐng)域驅(qū)動設(shè)計付諸實踐?Vaughn Vernon 的這本《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》為我們給出了全面的解答。
《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》分別從戰(zhàn)略和戰(zhàn)術(shù)層面詳盡地討論了如何實現(xiàn)DDD,其中包含了大量的最佳實踐、設(shè)計準則和對一些問題的折中性討論!秾崿F(xiàn)領(lǐng)域驅(qū)動設(shè)計》共分為14 章,在DDD 戰(zhàn)略部分,《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》向我們講解了領(lǐng)域、限界上下文、上下文映射圖和架構(gòu)等內(nèi)容,戰(zhàn)術(shù)部分包括實體、值對象、領(lǐng)域服務、領(lǐng)域事件、聚合和資源庫等內(nèi)容。一個虛構(gòu)的案例研究貫穿全書,這對于實例講解DDD 實現(xiàn)來說非常有用。 《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》在DDD 的思想和實現(xiàn)之間建立起了一座橋梁,架構(gòu)師和程序員均可閱讀,同時也可以作為一本DDD 參考書。
著譯俱佳 ThoughtWorks資深咨詢師傾力譯、! ⊥暾wDDD各方面知識 提供大量示例代碼 案例貫穿全書 理論與實踐緊密銜接之典范 架構(gòu)師、程序員境界提升不可或缺之必選書目
作者:Vaughn Vernon是一個經(jīng)驗豐富的軟件工匠,在軟件設(shè)計、開發(fā)和架構(gòu)方面擁有超過25年的從業(yè)經(jīng)驗。他提倡通過創(chuàng)新來簡化軟件的設(shè)計和實現(xiàn)。從20世紀80年代開始,他便開始使用面向?qū)ο笳Z言進行編程;在 20世紀 90年代早期,他便在領(lǐng)域建模中應用了領(lǐng)域驅(qū)動設(shè)計,那時他使用的是Smalltalk語言。他在很多業(yè)務領(lǐng)域都有從業(yè)經(jīng)驗,包括航空、環(huán)境、地理、保險、醫(yī)學和電信等領(lǐng)域。同時,Vaughn在技術(shù)上也取得了很大的成功,包括開發(fā)可重用的框架和類庫等。他在全球范圍之內(nèi)提供軟件咨詢和演講,此外,他還在許多國家教授《實現(xiàn)領(lǐng)域驅(qū)動設(shè)計》的課程。
序 xix
前言 xxi 致謝 xxxi 關(guān)于作者 xxxv 如何使用本書xxxvii 第1章 DDD入門 我能DDD嗎? 為什么我們需要DDD 如何DDD 使用DDD的業(yè)務價值 1你獲得了一個非常有用的領(lǐng)域模型 2你的業(yè)務得到了更準確的定義和理解 3領(lǐng)域?qū)<铱梢詾檐浖O(shè)計做出貢獻 4更好的用戶體驗 5清晰的模型邊界 序 xix 前言 xxi 致謝 xxxi 關(guān)于作者 xxxv 如何使用本書xxxvii 第1章 DDD入門 我能DDD嗎? 為什么我們需要DDD 如何DDD 使用DDD的業(yè)務價值 1你獲得了一個非常有用的領(lǐng)域模型 2你的業(yè)務得到了更準確的定義和理解 3領(lǐng)域?qū)<铱梢詾檐浖O(shè)計做出貢獻 4更好的用戶體驗 5清晰的模型邊界 6更好的企業(yè)架構(gòu) 7敏捷、迭代式和持續(xù)建模 8使用戰(zhàn)略和戰(zhàn)術(shù)新工具 實施DDD所面臨的挑戰(zhàn) 虛構(gòu)的案例,真實的實踐 本章小結(jié) 第2章 領(lǐng)域、子域和限界上下文 總覽 工作中的子域和限界上下文 將關(guān)注點放在核心域上 戰(zhàn)略設(shè)計為什么重要 現(xiàn)實世界中領(lǐng)域和子域 理解限界上下文 限界上下文不僅僅只包含模型 限界上下文的大小 與技術(shù)組件保持一致 示例上下文 協(xié)作上下文 身份與訪問上下文 敏捷項目管理上下文 本章小結(jié) 第3章 上下文映射圖 上下文映射圖為什么重要 繪制上下文映射圖 產(chǎn)品和組織關(guān)系 映射3個示例限界上下文 本章小結(jié) 第4章 架構(gòu) 采訪一個成功的CIO 分層 依賴倒置原則 六邊形架構(gòu)(端口與適配器) 面向服務架構(gòu) REST REST作為一種架構(gòu)風格 RESTful HTTP服務器的關(guān)鍵方面 RESTful HTTP客戶端的關(guān)鍵方面 REST和DDD 為什么是REST? 命令和查詢職責分離——CQRS CQRS的各個方面 處理具有最終一致性的查詢模型 事件驅(qū)動架構(gòu) 管道和過濾器 長時處理過程(也叫Saga) 事件源 數(shù)據(jù)網(wǎng)織和基于網(wǎng)格的分布式計算 數(shù)據(jù)復制 事件驅(qū)動網(wǎng)織和領(lǐng)域事件 持續(xù)查詢 分布式處理 本章小結(jié) 第5章 實體 為什么使用實體 唯一標識 用戶提供唯一標識 應用程序生成唯一標識 持久化機制生成唯一標識 另一個限界上下文提供唯一標識 標識生成時間 委派標識 標識穩(wěn)定性 發(fā)現(xiàn)實體及其本質(zhì)特征 揭開實體及其本質(zhì)特征的神秘面紗 挖掘?qū)嶓w的關(guān)鍵行為 角色和職責 創(chuàng)建實體 驗證 跟蹤變化 本章小結(jié) 第6章 值對象 值對象的特征 度量或描述 不變性 概念整體 可替換性 值對象相等性 無副作用行為 最小化集成 用值對象表示標準類型 測試值對象 實現(xiàn) 持久化值對象 拒絕由數(shù)據(jù)建模泄漏帶來的不利影響 ORM與單個值對象 多個值對象序列化到單個列中 使用數(shù)據(jù)庫實體保存多個值對象 使用聯(lián)合表保存多個值對象 ORM與枚舉狀態(tài)對象 本章小結(jié) 第7章 領(lǐng)域服務 什么是領(lǐng)域服務(首先,什么不是領(lǐng)域服務) 請確定你是否需要一個領(lǐng)域服務 建模領(lǐng)域服務 獨立接口有必要嗎 一個計算過程 轉(zhuǎn)換服務 為領(lǐng)域服務創(chuàng)建一個迷你層 測試領(lǐng)域服務 本章小結(jié) 第8章 領(lǐng)域事件 何時/為什么使用領(lǐng)域事件 建模領(lǐng)域事件 創(chuàng)建具有聚合特征的領(lǐng)域事件 身份標識 從領(lǐng)域模型中發(fā)布領(lǐng)域事件 發(fā)送方 訂閱方 向遠程限界上下文發(fā)布領(lǐng)域事件 消息設(shè)施的一致性 自治服務和系統(tǒng) 容許時延 事件存儲 轉(zhuǎn)發(fā)存儲事件的架構(gòu)風格 以REST資源的方式發(fā)布事件通知 通過消息中間件發(fā)布事件通知 實現(xiàn) 發(fā)布NotificationLog 發(fā)布基于消息的事件通知 本章小結(jié) 第9章 模塊 通過模塊完成設(shè)計 模塊的基本命名規(guī)范 領(lǐng)域模型的命名規(guī)范 敏捷項目管理上下文中的模塊 其他層中的模塊 先考慮模塊,再是限界上下文 本章小結(jié) 第10章 聚合 在Scrum核心領(lǐng)域中使用聚合 第一次嘗試:臃腫的聚合 第二次嘗試:多個聚合 原則:在一致性邊界之內(nèi)建模真正的不變條件 原則:設(shè)計小聚合 不要相信每一個用例 原則:通過唯一標識引用其他聚合 通過標識引用使多個聚合協(xié)同工作 建模對象導航性 可伸縮性和分布式 原則:在邊界之外使用最終一致性 誰的任務? 打破原則的理由 理由之一:方便用戶界面 理由之二:缺乏技術(shù)機制 理由之三:全局事務 理由之四:查詢性能 遵循原則 通過發(fā)現(xiàn),深入理解 重新思考設(shè)計 估算聚合成本 常見用例場景 內(nèi)存消耗 探索另外的設(shè)計 實現(xiàn)最終一致性 這是Scrum團隊成員的任務嗎? 決定的時候到了 實現(xiàn) 創(chuàng)建具有唯一標識的根實體 優(yōu)先使用值對象 使用迪米特法則和“告訴而非詢問”原則 樂觀并發(fā) 避免依賴注入 本章小結(jié) 第11章 工廠 領(lǐng)域模型中的工廠 聚合根中的工廠方法 創(chuàng)建CalendarEntry實例 創(chuàng)建Discussion實例 領(lǐng)域服務中的工廠 本章小結(jié) 第12章 資源庫 面向集合資源庫 Hibernate實現(xiàn) TopLink實現(xiàn) 面向持久化資源庫 Coherence實現(xiàn) MongoDB實現(xiàn) 額外的行為 管理事務 警告 類型層級 資源庫 vs 數(shù)據(jù)訪問對象(DAO) 測試資源庫 以內(nèi)存實現(xiàn)進行測試 本章小結(jié) 第13章 集成限界上下文 集成基礎(chǔ)知識 分布式系統(tǒng)之間存在根本性區(qū)別 跨系統(tǒng)邊界交換信息 通過REST資源集成限界上下文 實現(xiàn)REST資源 使用防腐層實現(xiàn)REST客戶端 通過消息集成限界上下文 從Scrum的產(chǎn)品負責人和團隊成員處得到持續(xù)通知 你能處理這樣的職責嗎? 長時處理過程,以及避免職責 長時處理過程的狀態(tài)機和超時跟蹤器 設(shè)計一個更復雜的長時處理過程 當消息機制或你的系統(tǒng)不可用時 本章小結(jié) 第14章 應用程序 用戶界面 渲染領(lǐng)域?qū)ο? 渲染數(shù)據(jù)傳輸對象 使用調(diào)停者發(fā)布聚合的內(nèi)部狀態(tài) 通過領(lǐng)域負載對象渲染聚合實例 聚合實例的狀態(tài)展現(xiàn) 用例優(yōu)化資源庫查詢 處理不同類型的客戶端 渲染適配器以及處理用戶編輯 應用服務 示例應用服務 解耦服務輸出 組合多個限界上下文 基礎(chǔ)設(shè)施 企業(yè)組件容器 本章小結(jié) 附錄A 聚合與事件源:A+ES 應用服務內(nèi)部 命令處理器 Lambda語法 并發(fā)控制 A+ES所帶來的結(jié)構(gòu)自由性 性能 實現(xiàn)事件存儲 關(guān)系型持久化 BLOB持久化 專注的聚合 讀模型投射 與聚合設(shè)計一道使用 增強事件 工具和模式 事件序列器 事件不變性 值對象 協(xié)議生成 單元測試和需求規(guī)范 事件源和函數(shù)式語言 參考文獻
所有的計算都表明它不工作,唯一的做法是:使其工作。 ——Pierre-Georges Latécoère早期法國航空企業(yè)家
是的,我們將使其工作。然而,在軟件開發(fā)過程中采用領(lǐng)域驅(qū)動設(shè)計卻是困難的。即便是有能力的開發(fā)者,也很難找到實現(xiàn)領(lǐng)域驅(qū)動設(shè)計的正確方法。 起飛,著陸 在我小的時候,我的父親學習過駕駛小型飛機。我們經(jīng)常會全家出去飛行,有時會飛到另一個機場,在那里吃過午飯后再返回。當父親時間有限而他依然想飛時,父親便帶上我一起在機場上空盤旋,起飛,著陸,再起飛,再著陸。 也會有些長途飛行,這時我們會帶上一張由父親先前繪制好的路線圖。我們幾個小孩便當起了領(lǐng)航員:將圖上的標志對應著陸地上的地標,以確保我們沒有跑偏航線。這是一件很有趣的事情,因為要識別遠在地面上的物體是很有挑戰(zhàn)性的。事實上,我敢肯定父親根本不用我們領(lǐng)航便知道我們處于什么方位——他能看到儀表盤上的所有信息,并且他擁有儀表飛行執(zhí)照。 空中的景觀的確改變了我的視野。不時地,父親和我會飛過我們鄉(xiāng)下的房子。在幾百英尺的高空中,我體會到了另一種“家”的概念,而這在之前是沒有過的。當我們飛過自家的房子時,母親和我的姐妹們便會跑到院子里向我們揮手。我知道那是她們,即便我看不清楚她們是誰。談話肯定是不行的,連大聲喊都不行,她們是聽不見的。我還可以看到將我家和外面公路分開的護欄,平時我們會像走平衡木一樣在護欄上面走來走去。從空中看,它們就像被細心編排過的小樹枝一樣。我們 家的院子很大,每每到了夏天,我都會開著割草機一排一排地修理院子里的草坪。而在空中時,我只能看到一片綠色,小草的葉子肯定是看不清楚的。 我喜歡在空中的時刻,直到現(xiàn)在我還不時回想起這些時刻,好像那個降落飛 機的黃昏就發(fā)生在不久以前一樣。雖然如此,在地面上的感覺依然是無法取代的, 因為它給我一種腳踏實地的感覺。 著陸于領(lǐng)域驅(qū)動設(shè)計 一開始接觸領(lǐng)域驅(qū)動設(shè)計( DDD)就像一個小孩之于飛行一樣。天空中的景色是令人驚嘆的,但有時我們卻因為過于陌生而搞不明白它們到底是什么。要從甲地到乙地顯得如此的遙遠。然而, DDD的“成年人 ”們卻總知道他們所處的方位,因為他們在很早之前便繪制好了路線圖,并且能夠完全按照儀表進行相應的操作。而還有很多人找不到“在地面上”的感覺,此時我們需要的是“穩(wěn)定著陸”的能力,然后找到一張地圖給我們指引方向。 Eric Evans的《領(lǐng)域驅(qū)動設(shè)計:軟件核心復雜性應對之道》是一本經(jīng)得住時間考驗的經(jīng)典之作。我堅定地相信,在接下來的幾十年里,本書依然會是開發(fā)者的實用指導。和其他模式一樣,該書為我們建立起了一種高屋建瓴式的寬闊視野。然而,對于如何實現(xiàn) DDD,我們可能將面對更多的挑戰(zhàn)。通常來說,我們更渴望看到一些具體的例子。 我的目標之一便是幫助你來一個“軟著陸”,保全飛機,然后沿著一條周知的線路帶你回家。這將幫助你如何更好地去實現(xiàn) DDD,并且通過你所熟悉的工具和技術(shù)給出示例演示。當然,任何一個人都不可能一直呆在家里,所以我還會帶領(lǐng)你到新的地帶去冒險,這些地帶你可能從來沒有去過。冒險之路是險峻的,但是在正確的戰(zhàn)術(shù)應對下,征服這些困難是可能的。在這條冒險之路上,你將學到另外的架構(gòu)和模式來集成多個領(lǐng)域模型。你將接觸到先前沒有被研究過的集成方法,并且學到如何開發(fā)自治性服務。 我將向你提供一張對短途旅行和長途旅行均適用的地圖,它可以幫助你更好地享受沿途風景,同時又不至于迷失途中。 對照地形,繪制飛行圖 在軟件開發(fā)的過程中,我們經(jīng)常做的一件事便是將一種東西映射到另一種東西。我們將對象映射到數(shù)據(jù)庫,映射到用戶界面,或者映射到不同的應用層展現(xiàn)(包括作為消費方的其他系統(tǒng)或應用程序)。在所有這些映射中,我們很自然地希望在Evans提出的高層模式和具體實現(xiàn)之間存在一種映射。 即便你已經(jīng)接觸過 DDD,你依然有很多可以獲益的地方。有時, DDD首先被看作是一套技術(shù)工具集,有人將此稱為 DDD-Lite。我們可能已經(jīng)對實體、服務等 DDD概念非常熟悉了,并且大膽地嘗試著設(shè)計聚合,還通過資源庫來管理持久化。這些模式是大家相對熟知的,使用起來很容易,我們甚至還使用了值對象。以上這些都屬于戰(zhàn)術(shù)設(shè)計模式范疇,也即更加偏向技術(shù)層面。這些模式可以很好地幫我們解決軟件問題。而同時,對于戰(zhàn)術(shù)性模式,我們依然有許多需要學習的。我將戰(zhàn)術(shù)模式映射到實現(xiàn)層面。 你曾了解過戰(zhàn)術(shù)建模之外的東西嗎?你曾了解過被稱為 DDD“另一半”的戰(zhàn)略設(shè)計模式嗎?如果你還沒有使用過限界上下文和上下文映射圖,那么你很有可能也沒有使用過通用語言。 如果說 Evans在軟件開發(fā)社區(qū)有一項發(fā)明,那便是通用語言。通用語言是一種團隊協(xié)作模式,用于捕捉特定業(yè)務領(lǐng)域中的概念和術(shù)語。一個特定領(lǐng)域的軟件模型通過不同的名詞、形容詞和動詞來表達,這些詞匯是開發(fā)團隊正式使用的,而團隊中應該包含一個或多個領(lǐng)域?qū)<。然而,將通用語言僅限定于一些詞匯則是錯誤的。就像自然語言反映人們的思想一樣, DDD的通用語言反映了領(lǐng)域?qū)<覍τ谲浖到y(tǒng)的思維模型。通用語言和那些戰(zhàn)略和戰(zhàn)術(shù)性的建模模式同等重要,在有些情況下甚至更具有持久性。 簡單地講, DDD-Lite將導致劣質(zhì)的領(lǐng)域?qū)ο,因為通用語言、限界上下文和上下文映射圖的作用太大了,你從其中獲得的并不只是一套團隊共用的語言。在限界上下文中用通用語言來表述一個領(lǐng)域模型可以增加業(yè)務價值,并且使我們確信所開發(fā)軟件的正確性。即使從技術(shù)的角度,它也可以幫助我們創(chuàng)建更好的領(lǐng)域模型,這樣的模型行為豐滿,業(yè)務純凈,并且可以減少犯錯誤的可能性。因此,我將戰(zhàn)略設(shè)計模式映射到了可理解的實際例子中。 本書對于 DDD的映射可以幫助你同時體會到戰(zhàn)略設(shè)計和戰(zhàn)術(shù)設(shè)計的好處。通過一些具體的例子,你將感受到這些 DDD映射的業(yè)務價值和技術(shù)展現(xiàn)力。 如果我們對于 DDD的所有實踐都只是停留在“地面上”,那將是令人失望的。過度地拘泥于細節(jié)將使我們喪失在空中俯瞰的機會。所以,不要將自己局限在地面的細節(jié)上,要勇敢地飛翔在空中,居高臨下。搭上戰(zhàn)略設(shè)計的航班,去了解限界上下文和上下文映射圖,你將獲得更廣闊的視野。當你從 DDD的航班中獲益時,我的目的也就達到了。 各章概要 以下是各章的主要內(nèi)容以及你將如何從中獲益。 第1章:DDD入門 本章向你介紹 DDD的好處,并且教你如何盡可能多地去實現(xiàn) DDD。你將學到當你在應對復雜的軟件系統(tǒng)時, DDD可以為你的項目和團隊帶來什么。同時,你將了解到通常的 DDD替代方案以及這些方案為什么會導致問題。作為對 DDD的基礎(chǔ)講解,本章將教你如何在項目中開始采用 DDD,還有如何向你的領(lǐng)域?qū)<液图夹g(shù)團隊推銷 DDD。在DDD的武裝下,你將學會如何迎接挑戰(zhàn),勇往直前。 本章將介紹關(guān)于一個公司及其團隊的案例研究,雖然該公司是虛構(gòu)的,但是他們所面臨的 DDD挑戰(zhàn)卻是真實存在的。該公司旨在開發(fā)一個新的多租戶 SaaS(Software as a Service,軟件即服務)軟件產(chǎn)品。不出所料,在使用 DDD時,他們犯了一些常見的錯誤。不過還好,他們發(fā)現(xiàn)了這些錯誤,并解決了一些問題,因此項目還算沒有偏離正軌。該團隊需要開發(fā)一套基于 Scrum的項目管理軟件。該案例還會在本書的后續(xù)章節(jié)中連續(xù)講到。每一種戰(zhàn)略和戰(zhàn)術(shù)模式都將教給這個團隊。在這個過程中,團隊有誤入歧途的時候,但最終他們將向著成功的 DDD實踐昂首闊步。 第2章:領(lǐng)域、子域和限界上下文 領(lǐng)域、子域和核心域分別是什么?限界上下文是什么,我們?yōu)槭裁匆褂盟⑶胰绾问褂?這些問題將在這個 SaaS項目團隊犯錯誤的時候給予解答。在他們的第一個 DDD項目中,他們并不了解子域、限界上下文和通用語言這些概念。事實上,他們根本不知道什么是戰(zhàn)略設(shè)計,只是采用了戰(zhàn)術(shù)設(shè)計來解決一些技術(shù)問題。這樣他們在開始設(shè)計領(lǐng)域模型的時候便遇到了不少問題。幸運的是,他們及時地意識到了這些問題,項目還有挽回的余地。 本章還講到了如何使用限界上下文對模型進行分離,這是非常重要的;同時還講到了一些模型分離不當?shù)姆蠢,并且給出了有效的實現(xiàn)建議。在采用了這些建議之后,該團隊的成員們重新創(chuàng)建了兩個不同的限界上下文。這種合理的模型分離帶來的好處是引出了第三個限界上下文——核心域,這將是本書使用的主要例子。 對于那些苦于單單從技術(shù)層面應用 DDD的人來說,本章應該能引起你的共鳴。如果你還是 DDD戰(zhàn)略設(shè)計的外行,那么本章將為你指明方向。 第 3章:上下文映射圖 上下文映射圖幫助我們理解業(yè)務領(lǐng)域、模型間的邊界,以及這些模型之間的集成方式。 上下文映射圖絕對不只是繪制系統(tǒng)架構(gòu)圖這么簡單,它處理的是不同限界上下文之間的關(guān)系,以及如何在不同的模型之間映射對象。對于在復雜的業(yè)務系統(tǒng)中使用好限界上下文,這是至關(guān)重要的。在第 2章中,團隊成員們在首次嘗試限界上下文時碰到了問題。本章中,他們將學著如何利用上下文映射圖來解決這些問題。這樣的結(jié)果是產(chǎn)生了兩個體面的限界上下文,這兩個上下文將被另外一個負責核心域的團隊所使用。 第 4章:架構(gòu) 我們都知道分層架構(gòu),但它是開發(fā) DDD軟件的唯一方式嗎,也或許還存在另外的方式?在本章中,我們將講到:六邊形架構(gòu)(端口和適配器)、面向服務架構(gòu)、REST、CQRS、事件驅(qū)動(管道和過濾器,長時處理過程,事件源)和數(shù)據(jù)網(wǎng)格,其中好幾種架構(gòu)都將被該團隊成員所采用。 第 5章:實體 在DDD的戰(zhàn)術(shù)模式中,我們將首先講到實體。團隊成員們一開始過于強調(diào)實體的作用而忽視了值對象。受到數(shù)據(jù)庫和持久化框架的影響,實體被該團隊濫用了,此時他們開始討論如何避免大范圍地使用實體。 在本章中,你將看到很多優(yōu)秀的實體設(shè)計例子。同時,本章還將講到如何使用實體來表達通用語言,以及如何對實體進行測試、實現(xiàn)和持久化。 第 6章:值對象 早些時候,團隊成員們錯過了采用值對象的好機會。他們過于注重為實體創(chuàng)建一些單一的屬性,這種方式是欠妥的,更好的方式是將這些單一的屬性聚合成一個不變的整體。本章將從不同的角度講解如何設(shè)計值對象,以及在什么時候采用值對象會優(yōu)于實體。同時,本章還包含了一些其他話題,比如值對象在集成中的角色和對標準類型的建模等。然后,本章講到了如何設(shè)計以領(lǐng)域為中心的測試,如何實現(xiàn)值對象。此外,本章還講到了在聚合中存儲值對象時,如何避免持久化機制所帶來的不利影響。 第 7章:領(lǐng)域服務 本章將講到,在領(lǐng)域模型中,什么時候應該將一個概念建模成粒度適中,并且無狀態(tài)的領(lǐng)域服務。你將學到何時應該使用領(lǐng)域服務而不是實體或值對象,以及如何使用領(lǐng)域服務來處理業(yè)務邏輯和技術(shù)上的集成。團隊成員們向我們展示了何時應該使用領(lǐng)域服務,以及如何設(shè)計領(lǐng)域服務。 第 8章:領(lǐng)域事件 Eric Evans并沒有在他的書中正式介紹領(lǐng)域事件,領(lǐng)域事件是在他那本書出版之后才進入人們視野的。在本章中,你將學到為什么領(lǐng)域事件如此有用,以及使用領(lǐng)域事件的不同方法。領(lǐng)域事件甚至被用來輔助集成和自治性服務。在軟件系統(tǒng)中,我們經(jīng)常使用一些技術(shù)層面的事件機制,但本章將著重講解領(lǐng)域事件與這些事件機制的區(qū)別。本章還將指導你如何設(shè)計并實現(xiàn)領(lǐng)域事件,包括一些可行的方案和對這些方案的權(quán)衡選擇。然后,本章將講到如何創(chuàng)建一個發(fā)布 -訂閱機制;如何利用事件來集成整個企業(yè)軟件中的各個訂閱方;如何創(chuàng)建和管理事件存儲;如何處理消息機制所面臨的常見挑戰(zhàn)等。 第 9章:模塊 對于模型中的對象,我們應該如何將他們組織在大小適中的容器中呢?我們又如何保證不同容器中的對象之間只存在有限的耦合?另外,我們?nèi)绾螌@些容器進行命名以體現(xiàn)通用語言?除了包和命名空間之外,我們?nèi)绾问褂糜烧Z言和框架提供的現(xiàn)代模塊化機制,比如 OSGi和Jigsaw?在本章中,你將看到 SaaS團隊成員是如何在不同的項目中使用模塊的。 第 10章:聚合 在DDD的戰(zhàn)術(shù)模式中,聚合可能是最不容易理解的了。然而,在遵循一定的經(jīng)驗法則的情況下,我們是能夠更簡單、更快地實現(xiàn)聚合的。在本章中你將學到:如何利用聚合在不同的小規(guī)模對象集群間創(chuàng)建一致性邊界,從而降低模型的復雜性。由于在細枝末節(jié)上花了太多精力, SaaS團隊成員們在設(shè)計聚合時總是磕磕絆絆。我們將仔細研究該團隊所面臨的挑戰(zhàn),并且分析錯誤的原因以及他們的應對策略。結(jié)果,團隊成員們對他們的核心域有了更深層次的理解。我們將看到,在合理的事務處理和保證最終一致性(Eventual Consistency)的前提下,該團隊更正了他們所犯的錯誤,并且在一個分布式環(huán)境中設(shè)計出了更具有伸縮性和更高效的模型。 第 11章:工廠 工廠已經(jīng)在 [Gamma et al.]中被大量地談及了,為什么還要講呢?本章并不打算重蹈覆轍,而是將重點放在“工廠應該存在于何處”這個問題上。在本章中,我們將講到在 DDD中實現(xiàn)工廠的技巧。團隊成員在他們的核心域中創(chuàng)建的工廠可以簡化客戶端接口,并且對模型的消費方起到保護作用,從而避免了在多租戶環(huán)境中引入災難性的 bug。 第 12章:資源庫 資源庫只是一個數(shù)據(jù)訪問對象( Data Access Object, DAO)嗎?如果不是,它們之間有什么區(qū)別呢?我們?yōu)槭裁磻搶①Y源庫看成是對集合的模擬而非數(shù)據(jù)庫呢?在本章中,我們將講到如何利用 ORM來實現(xiàn)資源庫,其中有兩種 ORM方案,一種采用基于網(wǎng)格的分布式緩存,另一種則采用 NoSQL的鍵值對存儲。團隊成員們可以采用任何一種作為他們的持久化機制。 第 13章:集成限界上下文 到現(xiàn)在為止,你已經(jīng)了解了戰(zhàn)略層次的上下文映射圖和多種戰(zhàn)術(shù)層次的模式。本章將講到,在 DDD中,我們?nèi)绾瓮ㄟ^上下文映射圖來集成不同的模型。在團隊對核心域和其他輔助性的限界上下文進行集成時,我們將給出相應的建議和指導。 第14章:應用程序 對于每一個核心域的通用語言,我們都設(shè)計了相應的模型,并且進行了足夠的測試,模型工作正常。然而,客戶應該如何使用我們的模型呢?他們應該使用 DTO將數(shù)據(jù)在模型和用戶界面之間傳輸嗎?或者存在其他方案可以實現(xiàn)模型和展現(xiàn)組件間的數(shù)據(jù)傳遞? DDD中的應用服務和基礎(chǔ)設(shè)施是如何工作的?對于這些問題,本章都將做出解答。 附錄A:聚合與事件源: A+ES 事件源是一種持久化聚合的重要技術(shù),同時也是事件驅(qū)動架構(gòu)的基礎(chǔ)。事件源通過一系列的事件來表示聚合的所有狀態(tài)。通過有序的事件重放,我們可以重新構(gòu)建聚合的狀態(tài)。當然,使用事件源的前提是:它能夠簡化對數(shù)據(jù)的持久化,并且能夠捕捉到那些具有復雜行為屬性的概念。 Java和開發(fā)工具 本書中的絕大多數(shù)例子都是使用 Java語言編寫的。我本來可以用 C#的,但是我有意識地使用了 Java。 首先,我認為 Java社區(qū)正在拋棄好的軟件設(shè)計和開發(fā)實踐,F(xiàn)在,對于多數(shù) Java項目而言,要在其中找到一個好的領(lǐng)域?qū)ο罂峙率抢щy的。在我看來, Scrum和敏捷被人們看成了優(yōu)良設(shè)計的替代品,而其中的產(chǎn)品待定項(Product Backlog)被看成了設(shè)計本身。多數(shù)敏捷人士并不會過多地去思考這些待定項是否會影響到業(yè)務模型。我得說明, Scrum的本意絕對不是要取代設(shè)計。不管有多少項目經(jīng)理想將你捆綁在持續(xù)交付這條路上,我得說 Scrum并不僅僅是要取悅于那些甘特圖( Gantt chart)的追隨者們。然而,太多的時候,情況的確是這樣的。 我認為這是個很大的問題,所以我想鼓勵 Java社區(qū)重新回到領(lǐng)域建模中來,同時我會通過本書向大家說明,設(shè)計是可以使我們獲益的。 此外,在 .NET社區(qū)中已經(jīng)有很好的DDD資源了,比如Jimmy Nilsson的《領(lǐng)域驅(qū)動設(shè)計與模式實戰(zhàn)》[Nilsson]。由于Jimmy的出色工作和其他人對Alt.NET的倡導,.NET社區(qū)中正掀起一陣優(yōu)秀設(shè)計的開發(fā)浪潮,這是Java社區(qū)需要注意的。 其次,我意識到 C#.NET人員在理解 Java代碼上并不存在什么困難。由于很多 DDD社區(qū)的人都在使用 C#.NET,而本書的早期校對人員也都是 C#程序員,但是我從來就沒有收到他們的抱怨。因此,我便不用顧慮這些了。 在我寫這本書時,業(yè)內(nèi)正將目光從關(guān)系型數(shù)據(jù)庫轉(zhuǎn)向基于文檔和鍵值對的存儲方案。這是有原因的, Martin Fowler將這些存儲方案稱為“面向聚合存儲”。這種命名是恰當?shù)模芎玫孛枋隽嗽?DDD中使用 NoSQL的好處。 但是,就我從事咨詢的經(jīng)驗來看,很多開發(fā)者還是認定了關(guān)系型數(shù)據(jù)庫和對象-關(guān)系映射。因此我想, NoSQL追隨者們應該能夠理解我在書中包含對象 -關(guān)系映射的章節(jié)。然而,我的確得承認,這可能會招致那些認為存在對象 -關(guān)系阻抗失配(Object-Relational Impedance)的人的鄙視。這無所謂,對此我表示接受,因為絕大多數(shù)人在他們的日常工作中都還得面對這種對象 -關(guān)系阻抗失配。 當然,在第 12章“資源庫”中,我同樣提供了基于文檔的、鍵值對的和數(shù)據(jù)網(wǎng)格的存儲方案。在多處地方,我都討論到了 NoSQL對聚合設(shè)計的影響。 NoSQL趨勢很有可能持續(xù)下去,那些對象 -關(guān)系型的開發(fā)者們應該注意了。在本書中你將看到,我能夠同時理解兩個陣營的觀點,并且對于雙方的觀點我都同意。這些都是技術(shù)趨勢所導致的摩擦,而這對于積極的變革是有必要的。
你還可能感興趣
我要評論
|