本書是Eric Evans對他自己寫的《領域驅動設計-軟體核心複雜性應對之道》的一本字典式的參考書,可用於快速查找《領域驅動設計》中的諸多概念及其簡明解釋。 其它本系列其它文章地址: [譯文]Domain Driven Design Reference(一)—— 前言 [譯文]Domain Driv ...
本書是Eric Evans對他自己寫的《領域驅動設計-軟體核心複雜性應對之道》的一本字典式的參考書,可用於快速查找《領域驅動設計》中的諸多概念及其簡明解釋。
其它本系列其它文章地址:
[譯文]Domain Driven Design Reference(一)—— 前言
[譯文]Domain Driven Design Reference(二)—— 讓模型起作用
[譯文]Domain Driven Design Reference(三)—— 模型驅動設計的構建模塊
[譯文]Domain Driven Design Reference(四)—— 柔性設計
[譯文]Domain Driven Design Reference(五)—— 為戰略設計的上下文映射
綁定上下文
對一個特定模型的定義和適用範圍(通常是一個子系統,或特定團隊的工作)的描述。
上游-下游
兩個組之間的關係是“上游”小組的行為影響“下游”小組的項目成功。但下游的行為並不會顯著影響上游項目。(例如,如果兩個城市沿著同一條河流,上游城市的污染主要影響下游城市。)
上游團隊可以獨立於下游團隊的命運而取得成功。
相互依賴
必須在不同的上下文中交付兩個軟體開發項目以使其中任何一個被認為是成功的情況。(當兩個系統各自依賴另一個系統的信息或功能時,我們通常會儘量避免將看到的項目構建成相互依賴的。 然而,也有一些相互依賴的項目,系統依賴性只向一個方向發展。當依賴系統沒有其它的系統與該系統的集成時,它幾乎沒有任何價值,或許因為這是唯一一個使用它的地方,那麼未能提供依賴系統就會導致兩個項目都失敗。)
自由
一個理想中的軟體開發上下文,在其它上下文中的開發工作是成功或失敗對其自己的交付沒有什麼影響。
上下文映射
為了策劃戰略,我們需要一個現實的,大範圍的模型開發視圖,擴展到我們的項目和我們整合的其他項目。
在沒有全局視圖的情況下,個別限界上下文會遺留下一些問題。其他模型的上下文可能仍然是模糊不清的。
其他團隊的人不會意識到上下文的界限,並且會在不知不覺中做出一些模糊邊緣或使內部連接複雜化的改變。當連接必須在不同的上下文中進行時,它們往往會相互滲透。
即使邊界清晰,與其他上下文的關係也會限制模型的性質或可行的變化速度。這些制約因素需要通過非技術渠道表現出來,有時很難與他們正在影響的設計決策聯繫起來。
因此:
識別項目中正在使用的每個模型並定義它的限界上下文。這包括非面向對象子系統的隱式模型。給每個限界上下文命名,並且使其名稱成為通用語言的一部分。
描述模型之間的聯繫點,列出對任何交互的明確翻譯,突出任何共用、隔離機制和影響程度。
映射現有的領域範圍。稍後再進行轉換。
這張映射圖可以成為實際設計策略的基礎。
在接下來的幾頁中,關係的描述會變得更加具體,在限界上下文之間有一組通用的關係模式。
合作關係*
當兩個上下文中的團隊共同成功或失敗時,通常會出現合作關係。
在相互獨立的上下文中,相互依賴的子系統缺少協作會導致兩個項目的交付失敗。一個系統缺失的一個關鍵特性可能會使另一個系統無法交付。不符合其他子系統開發人員期望的介面可能導致集成失敗。一個相互約定的介面可能會變得過於彆扭,以致於減慢了客戶端系統的開發速度,或者很難實現,從而減慢了服務端子系統的開發速度。失敗帶來了兩個項目的失利。
因此:
如果兩個上下文中的任何一個開發失敗都將導致兩個上下文的交付一起失敗,則在負責這兩個上下文的小組之間建立合作關係。制定協調發展和聯合管理一體化的過程。
團隊必須在其介面的演進上進行協作,以適應這兩個系統的開發需求。應該安排相互依賴的feature,以便它們在同一版本中完成。
大多數情況下,開發人員不需要詳細瞭解其他子系統的模型,但他們必須協調他們的項目計劃。當一個上下文中的開發遇到障礙時,則需要聯合研究這個問題,以找到一種緊急的設計解決方案,而不會過分地損害任何一方。
此外,還需要一個清晰的過程來管理集成。例如,可以定義一個特殊的測試套件,以證明介面符合客戶端系統的期望,它可以作為伺服器系統上持續集成的一部分運行。
共用內核
共用模型和相關代碼的一部分是非常密切的相互依賴關係,它能夠加快設計工作或者破壞這些共用的東西。
當功能集成受到限制時,大型上下文的持續集成的開銷可能會被認為太高。當團隊沒有足夠的技能或組織架構來維持持續集成,或者單個團隊的規模太大而笨拙時,這種情況可能尤為明顯。因此,可以定義獨立的限界上下文,並形成多個團隊。
一旦獨立的、不協調的團隊在密切相關的應用程式上工作,可能會向前推進一段時間,但是他們生產的產品可能不適合在一起。即使是合作伙伴團隊最終也會花費大量精力在翻譯層和改造上,同時重覆這些工作並失去通用語言的好處。
因此:
用明確的邊界指定團隊同意分享的領域模型的一部分子集。保持這個內核儘可能的小。
在這個邊界內,包括模型的子集,代碼的子集,或者與該模型的部分相關聯的資料庫設計。這種顯式共用的內容具有特殊的地位,在未與其他團隊協商的情況下不應改變。
定義一個持續集成過程,以保持內核模型的緊湊性,並與團隊的通用語言保持一致。經常其整合功能系統,雖然比團隊中持續集成的次數要少一些。
客戶/供應商開發
當兩個團隊處於上下游關係時,上游團隊可能獨立於下游團隊的命運而取得成功,下游的需求將以各種各樣的方式得到解決,並帶來廣泛的負面後果。
下游的團隊可能是無助的,受上游優先順序的擺佈。與此同時,上游團隊可能會收到抑制,擔心會破壞下游系統。擁有複雜審批流程的繁瑣的變更請求過程並沒有改善下游團隊的問題。如果下游團隊對變更擁有否決權,上游團隊的自由發展就會停止。
因此:
在兩個團隊之間建立清晰的客戶/供應商關係,意味著將下游優先因素放到上游的規劃中。為下游需求進行談判和預算任務,以便每個人都瞭解承諾和時間表。
敏捷團隊可以在規劃會議中讓下游團隊扮演上游團隊的客戶角色。聯合開發的自動化驗收測試可以驗證來自上游的預期介面。將這些測試添加到上游團隊的測試套件中,作為其持續集成的一部分,將使上游團隊自由地進行更改,而不必擔心下游的副作用。
順從者
當兩個開發團隊有一個上下游關係時,上游沒有動力為下游團隊的需求提供幫助,下游團隊就無能為力了。利他主義可能會促使上游開發者做出承諾,但它們不太可能實現。相信這些好意會導致下游團隊基於無法獲得的特性來制定計劃。下游項目將被推遲,直到團隊最終學會接受上游所提供的東西。針對下游團隊的需求量身定製的介面是不太不可能的。
因此:
通過對上游團隊的模型進行嚴格的遵守,消除了限界上下文之間的轉換的複雜性。儘管這限制了下游設計人員的風格,並且可能不會產生應用程式的理想模型,但是選擇一致性極大地簡化了集成。此外,你將與上游團隊共用一種通用語言。上游在駕駛員的位置上,所以讓他們的交流變得容易是件好事。利他主義可能足以讓他們與你分享信息。
反腐層
當與合作團隊銜接良好設計的限界上下文時,翻譯層可以是簡單的,甚至是優雅的。但是,當控制或通信不足以實現共用內核、合作伙伴或客戶供應商關係時,轉換就變得更加複雜。翻譯層採用了一種更具防禦性的語氣。
一個提供給上游系統的大型介面最終可能完全顛覆下游模型的意圖,從而使其被修改成以一種特別的方式來模仿其他系統的模型。遺留系統的模型通常是很薄弱的(如果不是大泥球的話),即使是明確設計的例外也可能不符合當前項目的需求,這使得遵循上游模型變得不切實際。然而,這種集成對於下游項目可能非常有價值甚至是必需的。
因此:
作為下游客戶端,創建一個隔離層,根據您自己的領域模型,為系統提供上游系統的功能。該層通過其現有的介面與另一個系統進行通信,只需要很少或不需要對其他系統進行修改。在內部,這一層在兩個模型之間需要單向或雙向轉換。
開放主機服務
通常對於每個限界上下文,您將為每個部件定義一個翻譯層,您必須將其與上下文之外的組件集成在一起。在集成是一次性的情況下,為每個外部系統插入翻譯層的這種方法以最小的成本避免了模型的損壞。但是當你發現你的子系統有更高的要求時,你可能需要更靈活的方法。
當一個子系統必須與許多其他的子系統集成時,為每一個子系統定製一個翻譯對象可能會使團隊陷入困境。有越來越多的維護,越來越多的擔心什麼時候會發生變化。
因此:
定義一個協議,將訪問您的子系統作為一組服務。 打開協議,使所有需要與您集成的人都可以使用它。增強和擴展協議以處理新的集成需求,除非一個團隊有特殊的需求。然後,使用一次性翻譯對象來增強該特殊情況的協議,以便共用協議能夠保持簡單和一致。
這將使服務提供者處於上游位置。每個客戶端都在下游,並且通常其中一些客戶端會遵守規定,有些客戶端會建立反腐層。具有開放主機服務的上下文可能與它的客戶端以外的上下文有任何關係。
公共語言
兩個限界上下文模型之間的轉換需要一種通用語言。
直接轉換到現有的領域模型可能不是一個好的解決方案。這些模型可能過於複雜或被分解得很糟糕。也許他們說的是非法的。如果將其中一種用作數據交換語言,它實際上就會被凍結,不能響應新的開發需求。
因此:
使用一種文檔完整的公共語言,可以將必要的領域信息作為一種通用的通信媒介來表達,並根據需要翻譯為該語言。
許多行業以數據交換標準的形式建立了公共語言。項目團隊也開發自己的,在他們的組織內使用。
公共語言通常與開放主機服務相結合。
分而治之
在定義需求方面,我們必須冷酷無情。如果兩組功能之間沒有顯著的關係,它們可以完全相互分離。
整合總是代價很大的,有時候好處很小。
因此:
聲明一個限界上下文,使其與其他上下文完全沒有關聯,允許開發人員在這個小範圍內找到簡單的、專門的解決方案。
大泥球
在我們調查現有的軟體系統時,我們試圖瞭解不同的模型在定義的邊界內是如何被應用的,我們發現部分系統(通常是大型系統),模型是混合的,邊界是不一致的。
在沒有邊界的系統中,試圖描述模型的上下文邊界很容易陷入困境。
定義良好的上下文邊界作為知識選擇和社會力量的結果出現(儘管創建系統的人在當時可能並不總是有意識地意識到這些原因)。當這些因素缺失或消失時,將多個概念系統混合在一起,使得定義和規則變得模棱兩可或相互矛盾。隨著特性的添加,系統是根據附加的邏輯來工作的。依賴關係縱橫交錯。因果關係變得越來越難以追蹤。最終,軟體會凝結成一個大的泥球。
在某些情況下,大球泥實際上是非常實用的(正如Foote和Yoder的原文所描述的那樣),但它幾乎完全阻止了有用模型所需要的敏銳和精確性。
因此:
在整個混亂的周圍畫一個邊界,把它指定為一個大泥球。不要嘗試在此上下文中應用複雜的建模。要警惕這種系統向其他上下文蔓延的趨勢。
(見http://www.laputan.org/mud/mud.html。Brian Foote和Joseph Yoder)
作者:Zachary_Fan
出處:http://www.cnblogs.com/Zachary-Fan/p/DDDReference5.html
如果你想及時得到個人自寫文章的消息推送,歡迎掃描下麵的二維碼~。