讀<<領域驅動設計-軟件核心復雜性應對之道>>有感

道可道,非常道.

名可名,非常名.

無名天地之始,有名萬物之母.

---老子

關于標題

好久沒寫東西了,動筆的動機是看完了一本書,想寫點總結性的東西,一是為了回顧一下梳理知識點,二是為了日后遺忘時能有個簡短的文章幫助自己快速回憶.

標題看著像上學時寫的作文題目,原本想找個高大上的題目好拉拉人氣,但關于領域驅動設計我也才處在守破離得級別,還是老老實實用個規矩的標題吧.

核心內容

作者在書中反復強調領域通用語言(Ubiquitous Language)的重要性,依據領域通用語言剝離出核心領域(Core Domain),隨著業務的發展和技術人員對領域知識的學習,不斷的調整領域通用語言,從而提煉核心領域.在這個閉環中,有這么幾點很重要:

  • 溝通

    項目組的成員要保證溝通的態度和效率.大家(包括并不限于開發,測試,需求,客戶)愿意圍繞業務知識進行溝通.有效的溝通能夠得出領域通用語言,反饋認知的偏差,編寫更接近自然語言的代碼.

  • 重構

    項目組的成員要勇于挑戰,勇于糾錯,勇于提煉核心領域知識.只有這樣才能夠讓核心領域更精煉,普通子域(Generic Subdomain)更內聚,讓有界上下文(Bounded Context)的邊界更清晰.讓眾神歸位各司其職.

  • 一些模式和設計技巧

    這是一本寫設計的書,但是作者是站在一個類似項目經理的角度寫的,其關注的重點不在于算法和數據結構的精妙,而是項目的整體.所以溝通和重構很重要,所有的這些技術相關的模式也多數為項目的推進而服務.目的是讓技術人員寫出誰都能看懂的代碼,寫出擴展性更好的代碼,寫出更接近自然語言的代碼,寫出能夠自解釋的代碼.

總結一下,核心內容就是有效的組織協調人,有效的組織協調代碼,最終成功完成項目.

梳理知識點

領域驅動設計01.png

不管怎樣作者給出了很多模式,有代碼級別的,作者叫模型驅動設計的構造塊.有管理級別的,作者叫戰略設計.給出的概念更是一堆一堆的.老子說的好,"非常道,非常名",能闡述出來的都不是永恒不變的,但有效的溝通需要我們建立在很多理解一致的概念上,讓我們挨個梳理一下作者的概念吧.

領域通用語言(Ubiquitous Language)

這個概念我也是第一次看到,作者在整個書中時不時要提一下這個概念.其實領域通用語言主要解決的是溝通問題,主要是業務人員和技術人員的溝通問題.不然開會的時候業務人員說自己的,技術人員說自己的,然后還誰都看誰不爽.

其實,這個東西還是讓技術人員妥協了,因為組成領域通用語言的以領域知識的概念為主.當然這也是必然的,除了一些技術性很強的項目(比如搞個云平臺),多數項目的目的都是為了服務于業務,幫助公司業務部門為公司創造更多的利潤.完成技術人員學習領域知識的過程作者稱之為消化知識.

模型驅動設計(Model-Driven Design)

10年聽說了TDD,其目的是讓每一個功能有一個明確的完成界限.這回又聽一個新東西MDD.模型驅動設計其實就是從模型開始出發,將領域通用語言中的概念映射到代碼上,這樣可以讓代碼直接體現出領域知識.讓技術人員和業務人員的溝通在一件事情上,如果沒有這層映射,他們的溝通必然存在轉換.

其實這里作者是反對根據功能點開發的流程的.比如很多項目的業務模型體現在數據庫上,而一個http請求過來后,順序的調用 control,service,dao最終在數據庫中體現模型內容的變化.作者更期望的是一種面向語義化得開發.

比如一個用戶加另一個用戶好友,前面那一種的代碼可能是這樣的:


interface UserService{
    void addFriend(User user1, User user2);
}

到底是user1加user2好友,還是user2加user1好友,調用該接口的程序員必須去看實現,要不就是實現的程序員要把實現細節在接口上的注釋里寫明白.

而后面那種設計的代碼可能是這樣的:

interface User{
    void addFriend(User user);
}

代碼的自解釋在這里體現了出來.

模型驅動設計將很多具體實現都交給了模型來完成,讓計算更接近數據.

手工建模(Hands-On Modeler)

還是為了解決信息傳遞,建模人員必須參與開發,防止模型圖沒有很好的傳遞設計意圖和設計細節.一定要用代碼體現出模型.要做能編碼的設計師.

分層架構(Layered Archiecture)

分層在領域驅動開發中也是有用武之地的,分層可以隔離各個子領域,能夠讓模型更內聚.作者給出了一個分層建議:

-----------------------------------
用戶界面層(或表示層)
-----------------------------------
應用層
-----------------------------------
領域層(或模型層)
-----------------------------------
基礎設施層
-----------------------------------

智能用戶界面"反模式"(The Smart UI "Anti-Pattern")

這是一個和領域驅動設計相反的設計方法,其主要特點就是展現層直接和數據庫交互.

優點是可以快速完成功能開發.

缺點是可維護性較差.

實體(Entity)

有唯一ID,能夠反映領域模型.最重要的是要有業務邏輯.

值對象(Value Object)

沒有唯一ID,能夠反映領域模型,也要有業務邏輯.與實體最大的區別是兩個相同對象比較時的邏輯,兩個實體只要ID相同,我們就認為他們指向了同一個對象;而值對象只要所有屬性相同,我們就認為指向了同一個對象.

服務(Service)

好的Service有如下三個特征:

  1. 與領域概念相關的操作不是ENTITY或VALUE OBJECT的一個自然的部分.
  2. 接口是根據模型的其他元素定義的.
  3. 操作是無狀態的.

模塊(Module)

高內聚低耦合是軟件設計的一條原則.用作者的話說:一個人一次考慮的事情是有限的,因此才有低耦合.不連貫的思想和一鍋粥似的思想同樣難于理解,因此才有高內聚.

劃分模塊就是遵循該原則,每個模塊包含一個內聚的概念集合.并盡可能把實現單一概念對象的所有代碼放到同一個模塊中.

聚合(Aggregate)

聚合主要用來封裝對象的內部結構.其作用就是將關聯的對象聚合在一起,由一個對象對外暴露遍歷接口.這樣能夠降低對這組關聯對象的維護的復雜度.每個聚合都要有一個根(root)和一個邊界(boundary).

為了實現概念上的聚合根,需要對所有事物應用一組規則.

  1. 根實體具有全局標識,它最終負責檢查固定規則.
  2. 根實體具有全局標識.邊界內的實體具有本地標識,這些標識只有在聚合根內部才唯一.
  3. 聚合外部的對象不能引用除根實體之外的任何內部對象.根實體可以把對內部實體的引用傳遞給它們,但這些對象只能臨時使用這些引用,而不能保持引用.根可以把值對象的副本傳遞給另一個對象,而不必關心它發生什么變化,因為它只是一個值對象,不再與聚合根有任何關聯.
  4. 作為上一條規則的推論,只有聚合的根才能直接通過數據庫查詢獲取.所有其他對象必須通過關聯的遍歷才能找到.
  5. 聚合內部的對象可以保持對其他聚合根的引用.
  6. 刪除操作必須一次刪除聚合之內的全部對象.
  7. 當提交對聚合邊界內部的任何對象的修改時,整個聚合中的所有固定規則都必須被滿足.

工廠(Factory)

工廠用來創建和重建復雜對象.對象的構造方法原本就可以完成對象的創建,但是如果對象比較復雜,創建方法就會和對象的行為方法混在一起,這時就不如將對象的創建邏輯放到工廠中來完成.這樣就講對象創建的邏輯抽離出來,而對象去關系自己的業務邏輯.

好的工廠都需要滿足如下兩個基本需求:

  1. 每個創建方法都是原子方法,而且滿足被創建對象或聚合的所有固定規則.工廠應該以一致的狀態來生成對象.如果工廠通過其接口收到了一個創建對象的請求,而它又無法正確地創建出對象,那么它應該拋出一個異常,或者調用某種其他機制,以確保不會返回錯誤的值.
  2. 工廠應該被抽離為所需的類型,而不是創建出具體的類.

沒必要讓多有類的創建都用工廠,不復雜或客戶關系實現的可以直接用構造方法.

資源庫(Repository)

將所有對象存儲和訪問操作交給資源庫來完成,而對于聚合一定控制只能從聚合根開始訪問遍歷.

使用資源庫有很多好處:

  1. 它們為客戶提供了一個簡單的模型,可以來獲取持久對象并管理它們的生命周期.
  2. 它們使應用程序與持久化技術解耦.
  3. 它們體現了有關對象訪問的設計決策.
  4. 可以很容易將它們替換為"啞實現",以便在測試中使用.

釋意接口(Intention-Revealing Interfaces)

這個模式其實主要解決的還是溝通問題.強調要面向接口設計,而且接口及參數的命名一定要表達出意思來,這樣調用者不會迷糊.還是那句話,寫出人能看懂的代碼.

無副作用函數(Side-Effect-Free Function)

這個模式強調一些值對象的操作一定是無副作用的.所謂無副作用就是,一個地方調用該方法,不會導致其他引用該對象的地方調用該方法得到不同的結果.作者用顏色這個值對象做了示范,其實Java中的BigDecimal里的運算方法都是無副作用的.

斷言(Assertion)

對于這章的內容,我的理解是針對無副作用的函數增加單元測試,用于保障函數無歧義.作者也說了如果語言支持斷言,可以直接在程序中增加斷言.Java有個關鍵字assert可以來做斷言,但是這個關鍵字要生效需要啟動程序是增加JVM參數-ea,多數情況下Java除測試的程序外很少使用.

概念輪廓(Conceptual Contour)

這個模式就是讓相關的操作,類,接口,聚合 放到一起,使其更內聚,讓其內部更加穩定.

獨立類(Standalone Class)

這個模式強調低耦合,防止對象互相依賴,要講對象無關的操作放到對象外.讓理解對象更容易.

閉合操作(Closure of Operation)

所謂閉合操作,就是方法的返回值和參數類型相同,而且一般閉合操作的都是值對象.

聲明式設計

其實這章作者描述的就是語義化編程,讓程序編寫更接近自然語言,讓程序能夠自解釋.比如下面這段代碼

Specification ventilatedType1 = new ContainerSpecification(VENTILATED_TYPE_1);
Specification ventilatedType2 = new ContainerSpecification(VENTILATED_TYPE_2);

Specification either = ventilatedType1.or(ventilatedType2);

策略模式(Strategy 也稱Policy)

雖然標題叫策略模式,其實作者是想表達過去的很多設計模式也很適合領域設計.比如策略模式,能夠很好的將對象的多態表述出來.

組合模式(Composite)

作者介紹了組合模式在領域設計中的使用,拿航線做了示例.

戰略設計

領域驅動設計02.png

戰略設計在我看來更多的是規劃開發.通過一些模式或方法來確定工作重心,并將資源花在核心上.

(戰略設計很多名稱譯者也沒給出中文名,我也沒找到中文譯名,就直接用英文了)

Bounded Context

領域驅動設計04.png

這個模式就是告訴我們一定要劃清模型邊界,在不同的模型中有不同的上下文,而這些領域知識僅限于當前的上下文,而模型的邊界很重要,邊界清晰,能夠降低溝通成本,而且能夠很好的安排工作.

持續集成(Continuous Integration)

如果模塊劃分的多,或者團隊大,及時邊界劃分的清晰,溝通成本也是很高的.而集成成本也就體現出來了,盡早的集成能夠跟早的發現問題.而集成不僅有代碼的集成,還有概念的集成.

多數集成有如下特征:

  • 分步集成,采用可重復使用的合并/構建技術.
  • 自動測試工具.
  • 概念集成.
  • 在討論模型和應用程序時堅持使用通用語言.

Context Map

模塊要劃清邊界,但是模塊間要互相調用和通信的,這就需要有一個 Context Map 來對模塊間的對象進行相互轉換.

Shared Kernel

為解決Context Map,最簡單的辦法就是共享核心,這樣就不存在模型間的轉換了.但前提是能夠共享,而且有專人在維護這個核心.

Customer/Supplier

如果兩個模塊間存在上下游關系,而且下游有更大的決策權,那么這種Customer/Supplier模式就比較適合.

這個模式有兩個關鍵要素:

  1. 關系必須是客戶與供應商的關系,其中客戶需求是至關重要的,由于下游團隊并不是唯一的客戶,因此不同客戶的要求必須通過協商類平衡,但這些要求都是非常重要的.這種關系與通常出現的窮親戚關系相反,在后者下游團隊不得不祈求上游團隊滿足其需求.
  2. 必須有一個自動化測試工具,使上游團隊在修改代碼時,不必擔心破壞下游團隊的工作,并能夠使下游團隊能夠專注于自己的工作,而不用總是密切注意著上游的行動.

作者用接力賽來比喻這個模式,接棒的人要相信上一棒能準確的傳到自己手里.

Conformist

當兩個開發團隊具有上下游關系時,如果上游團隊沒有動機來滿足下游團隊的需求,那么下游團隊將無能為力.處于利他主義的考慮,上游開發人員可能會做出承諾,但他們可能不會履行承諾.下游團隊處于良好的意愿會相信這些承諾,從而根據一些永遠不會實現的特性來制定計劃.下游項目只能被擱置,直到團隊最終學會利用現有條件自力更生為止.下游團隊不會得到根據他們的需求而量身定做的接口.

這是一個現實存在的問題,團隊間溝通總是存在障礙,尤其上游的KPI內容和服務下游無關時.作者告訴我們如果下游是弱勢,最簡單和省時間的方式就是成為追隨者,順著上游的接口開發.

Anticorruption Layer

如果追隨者發現,如果順著上游的接口開發會破壞自己模型結構,或者讓自己的模型混亂時.那就請使用Anticorruption Layer.創建一個隔離層,這個層通過現有接口與另一個系統進行通信.而且適配器模式(Adapter)和外觀模式(Facade)能很好的完成這個隔離層架構.創建隔離層還有個好處就是外部接口發現變化后,只需要修改隔離層代碼就好,不會影響到核心代碼.

Separate Way

作者說這是個模式,好吧,這是個模式,這個模式告訴我們:如果集成的性價比不高,那就不要集成,下游獨立開發自己需要的功能.

Open Host Service

讀完這節讓我想到了幾年前吵得火熱的面向服務編程,也有點像現在的微服務框架.就是說上游將自己的服務標準化,提供統一的協議和穩定的接口.這樣下游團隊只需要根據上游團隊提供的文檔就能夠集成.

Published Language

這個公共語言其實就是說,如果我們開發的軟件已經有一套行業標準術語了,那就直接拿來作為我們的通用語言就好,沒必要再自定義一套.

精煉

領域驅動設計05.png

我感覺精煉的目的就是梳理業務,讓核心,核心起來來.

領域模型的戰略精煉包括以下部分:

  1. 幫助所有團隊成員掌握系統的總體設計及協調.
  2. 找到一個具有濕度規模的核心模型并把它天津到通用語言中,從而促進溝通.
  3. 指導重構.
  4. 專注于模型中最有價值的那部分.
  5. 知道外包,現成組件的使用以及任務委派.

Core Domain

一個嚴峻的現實是我們不可能對又有設計進行同等的精化,而是必須分出優先級.為了使領域模型成為有價值的資產,必須整齊地梳理出模型的真正核心,并完全根據這個核心來創建應用程序的功能.但本來就稀缺的高水平開發人員往往會把工作重點放在技術基礎設施上,或者支取解決那些不需要專門領域知識就能解決的領域問題.

因此,對模型進行提煉.找到Core Domain 并提供一種易于區分的方法把它與那些起輔助作用的模型和代碼分開.最有價值和最專業的概念要輪廓分明.盡量壓縮Core Domain.

讓最有才能的人來開發Core Domain ,并相應地招募新人來補充這些人空出來的位置.在Core Domain中努力開發能夠確保實現系統藍圖的深層模型和柔性設計.仔細判斷任何其他不得投入,看它是否能夠支持這個提煉出來的Core.

一句話,好鋼用在刀刃上.

找到重要的是什么,讓重要的事重要起來,投入資源在重要的事上.

Generic Subdomain

除了核心領域外,一些輔助的子領域也要抽離出來,雖然子領域不是最重要的,但是確是整個軟件需要的.對于子領域的開發方式也可以有多種選擇:

  1. 現成的解決方案

    有時可以購買一個已實現的解決方案,或使用開源代碼.

優點

* 可以減少代碼的開發.
* 維護負擔轉移到外部.
* 代碼已經在很多地方使用過,可能較為成熟,因此比自己開發的代碼更可靠和完備.

缺點

* 在使用之前,仍需要花時間來評估和理解它.
* 就業內目前的質量控制水平而言,無法保證它的正確性和穩定性.
* 它可能設計的過于細致了(遠遠超出了你的目的), 集成的工作量可能比開發一個最小化的內容實現更大.
* 外部元素的集成常常不順利.它可能有一個與你的項目完全不同的Bounded Context.即使不是這樣,它也很難順利的引入你的其他軟件包中的Entity.
* 它可能會引入平臺,編譯器版本依賴.
  1. 公開發布的設計或模型

    優點

    • 比自己開發的模型更為成熟,并且反映了很多人的深層知識.
    • 提供了隨時可用的高質量文檔.

缺點

* 可能不是很符合你的需要,或者設計得過于細致了(遠遠超出了你的需要).
  1. 把實現外包出去

    優點

    • 使核心團隊可以脫身去處理Core Domain,這是需要知識和經驗積累的部分.
    • 開發工作的增加不會使團隊規模無限擴大下去,同時又不會導致Core Domain知識的分散.
    • 強制團隊采用面向接口設計,并且有助于保持子領域的通用性,因為規格已經被傳遞到外部.

缺點

* 仍需要核心團隊花費一些時間,因為他們需要與外包人員商量接口,編碼標準和其他重要方面.
* 當把代碼的所屬權交回團隊時,團隊需要耗費大量精力來理解這些代碼.(但是這個開銷比理解專用子領域要小一些,因此通用子領域不需要理解專門的背景知識.)
* 代碼質量或高或低,這取決于兩個團隊能力的高低.

自動化測試在外包中可能起到重要作用.需要邀請外包人員為他們的交付的代碼提供單元測試.
  1. 內部實現

    優點

    • 易于集成
    • 只開發自己需要的,不做多余的工作.
    • 可以臨時把工作分包出去.

缺點

* 需要承受后續的維護和培訓負擔.
* 很容易低估開發這些軟件包所需要的時間和成本.

Domain Vision Statement

這一節將的有點像目標管理.領導者需要在核心領域確定前,找好項目目標,也就是項目的核心價值,這有助于我們的工作不會偏離方向.

寫一份Core Domain的簡短描述以及它將會創造的價值(大約一頁紙),也就是"價值主張".那些不能將你的領域模型與其他領域模型區分開的方面就不要寫了.展示出領域模型是如何實現和均衡各方利益的.這份描述要盡量精簡.盡早把它寫出來,等到獲得新的理解后再修改它.

Highlighted Core

讓重要的重要起來.為了強調核心領域,作者給了個方法,就是寫一個精煉文檔(3~7頁,每頁內容不必太多),用于描述核心領域和核心元素之間的主要交互過程.

寫這個文檔同時會出現這些風險:

  1. 文檔可能得不到維護.
  2. 文檔可能沒人閱讀.
  3. 由于有多個信息來源,文檔可能達不到簡化復雜性的目的.

但是沒關系,有了它才能讓整個團隊有一個明確的目標.就像茫茫大海中的燈塔.

Cohesive Mechanism

計算有時會非常復雜,使設計開始變得膨脹.機械性的"如何做"大量增加,而把概念性的"做什么"完全掩蓋.為了解決問題提供算法的大量方法掩蓋了那些用于表達問題的方法.

因此,把概念上的Cohesive Mechanism(內聚機制)分離到一個單獨的輕量級框架中.要特別注意公式算法或那些有完備文檔的算法.用一個Intention-Revealing Interface來公開這個框架的功能.現在,領域中的其他元素就可以只專注于如何表達問題(做什么)了,而把解決方案的復雜細節(如何做)轉移給了框架.

還是那句話:寫出自解釋的代碼.

Segregated Core

模型中的元素可能有一部分屬于Core Domain, 而另一部分起支持作用.核心元素可能與一般元素緊密耦合在一起.Core的概念內聚性可能不是很強,看上去也不明顯.這種混亂性和耦合關系抑制了Core的分離.設計人員如果無法清晰地看到最重要的關系,就會開發出一個脆弱的設計.

因此,對模型進行重構,把核心概念從支持性元素(包括定義得不清楚的那些元素)中分離出來,并增強Core的內聚性,同時減少它與其他代碼的耦合.把所有通用元素或支持性元素提取到其他對象中,并把這些對象放到其他的包中-即使這會把一些緊密耦合的元素分開.

通過重構得到Segregated Core的一般步驟如下:

  1. 識別出一個核心子領域(可能是從精煉文檔中得到的).
  2. 把相關的類移到新的模塊中,并根據與這些類有關的概念為模塊命名.
  3. 對代碼進行重構,把那些不直接表示概念的數據和功能分離出來.把分離出來的元素放到其他包的類(可以是新的類)中.盡量把它們與概念上相關的任務放到一起,但不要為了追求完美而浪費太長時間.把注意力放在提煉核心子領域上,并且使核心子領域對其他包的引用變得更明顯且易于理解.
  4. 對新的Segregated Core Module 進行重構,使其中的核心子領域對其他包的引用變得更明顯且易于理解.
  5. 對新的Segregated Core Module 進行重構,使其中的關系和交互變得更簡單,表達更清楚,并且最大限度的減少并澄清它與其他模塊的關系(這是后續重構的目標).
  6. 對另一個核心子領域重復這個過程,直到完成Segregated Core 的工作.

Abstract Core

當不同模塊的子領域之間有大量交互時,要么需要在模塊之間創建很多引用(在很大程度上抵消了劃分模塊的價值),要么就必須間接的實現這些交互,而后者會使模型變得晦澀難懂.

因此,把模型中最基本的概念識別出來,并分離到不同的類,抽象類或接口中.設計這個抽象模型,使之能夠表達出重要組件之間的大部分交互.把這個完整的抽象模型放到它自己的模塊中,而專用的詳細的實現類則留在由子領域定義的模塊中.

作者還強調:盡管任何一次突破都會得到一個有價值的深層次模型,但只有Core Domain中的突破才能改變整個項目的軌道.

大比例機構

領域驅動設計06.png

大比例結構這部分內容我就看得暈暈乎乎,不能明確的表述作者所云了,隱隱感覺作者就是在強調模塊的職責要劃清.的確,很多時候模塊間的功能和作用是相互糾纏在一起的.

由于自己也沒有很好的理解作者所述,就摘抄一些內容了.

Evolving Order

應該允許這種概念上的大比例結構隨著應用程序一起演變,甚至可以變成一種完全不同的結構風格.有些設計決策和模型決策必須在掌握了詳細知識之后才能確定,這樣的決策不必過早地指定.

當發現一種大比例結構可以明顯使系統變得更清晰,而又沒有為模型開發施加一些不自然的約束時,就應該采用這種結構.使用不合適的結構還不如不使用它,因此最好不要為了追求設計的完整性而勉強去使用一種結構,而應該找到能夠最精簡地解決所出現問題的方案.要記住寧缺毋濫的原則.

System Metaphor

軟件設計往往非常抽象且難于掌握.開發人員和用戶都需要一些切實可行的方式來理解系統,并共享系統的一個整體視圖.

因此,當系統的一個具體類比正好符合團隊成員對系統的想象,并且能夠引導他們向著一個有用的方向進行思考時,就應該把這個類比用作一種大比例結構.圍繞這個隱喻來組織設計,并把它吸收到統一語言中.System Metaphor應該能促進系統的交流,又能指導系統的開發.它可以增加系統不同部分之間的一致性,甚至可以跨越不同的有界上下文.但所有隱喻都不是完全精確的,因此應不斷檢查隱喻是否過度或不恰當,當發現它起到妨礙作用時,要隨時準備放棄它.

Responsibility Layer

如果每個對象的職責都是手工分配的,將沒有統一的指導原則和一致性,也無法把領域作為一個整體來處理.為了保持大模型的一致,有必要在職責分配上實施一定的結構化控制.

因此,注意觀察模型中的概念依賴性,以及領域中不同部分的變化頻率和變化原因.如果在領域中發現了自然的層次結構,就把它們轉換為主要的抽象職責.這些職責應該描述了系統的高級目的和設計.對模型進行重構,使得每個領域對象 聚合和模型的職責都清晰地位于一個職責層當中.

Knowledge Level

如果在一個應用程序中,實體的角色和它們之間的關系在不同的情況下有很大變化,那么復雜性會顯著增加.在這種情況下,無論是一般的模型還是高度定制的模型,都無法滿足用戶的需求.為了兼顧各種不同的情形,對象需要引用其他的類型,或者需要具備一些在不同情況下包括不同使用方式的屬性.具有相同數據和行為的類可能會大量增加,而這些類的唯一作用只是為了滿足不同的組裝規則.

因此,創建一組不同的對象,用它們來描述和約束基本模型的結構和行為.把這些對象分為兩個"級別",一個是非常具體的級別,另一個級別則提供了一些可供用戶或超級用戶定制的規則和知識.

Pluggable Component

當很多應用程序需要進行互操作時,如果所有應用程序都基于相同的一些抽象,但它們是獨立設計的,那么在多個有界上下文之間的轉換會限制它們的集成.各個團隊之間如果不能緊密地協作,就無法形成一個 Shared Kernel.重復和分裂將會增加開發和安裝的成本,而且互操作會變得很難實現.

因此,從接口和交互中提煉出一個Abstract Core,并創建一個框架,這個框架要允許這些接口的各種不同實現被自由替換.同樣,無論是什么應用程序.只要它嚴格地通過Abstract Core的接口進行操作,那么就可以允許它使用這些組件.

寫在最后

領域驅動設計03.png

實踐是檢驗真理的唯一標準.再好的理論只有用起來才有價值,等到熟練了,就可以嘗試著去突破作者畫的圈圈.

看山是山,看水是水;

看山不是山,看水不是水;

看山還是山,看水還是水。

---某個和尚

參考

關于作者

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,406評論 6 538
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,034評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,413評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,449評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,165評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,559評論 1 325
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,606評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,781評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,327評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,084評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,278評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,849評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,495評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,927評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,172評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,010評論 3 396
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,241評論 2 375

推薦閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,692評論 25 708
  • 1. 什么是領域(Domain) 我們所做的軟件系統的目的都是來解決一系列問題,例如做一個電商系統來在線銷售自己...
    butterfly100閱讀 5,420評論 2 27
  • 走的久了,一個人的力氣只夠自己前行 所有的堅韌與頑強都是與生活打斗的結果這些裝備和武器只是為了避免被生活的掩埋的很...
    嘉溫閱讀 317評論 8 14
  • 只是,步行回家的路上,無意闖入斑駁陸離的你的影中。抬頭,卻尋不到你完整的樣子。 望著這一地的豐盛,內心被這巧妙的畫...
    微笑的貝殼兒閱讀 167評論 0 2
  • 往事在水中浸泡 看秋水無痕 沉靜 無語 看秋葉飄落 輕松安靜 我的心瞬間融入 被俘虜 緩慢而美好 這種感覺一定跟生...
    美食美客閱讀 261評論 1 1