天天看點

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

目錄

        不一緻的模型

        什麼是界限上下文?

        有界模型

       統一語言精練

       界限上下文的作用域

     界限上下文與子域的對比

      子域

      界限上下文

      子域和有界上下文之間的互相作用

      邊界

       實體邊界   

        所有權邊界                    

      現實生活中的界限上下文

      語義域

      科學

      買一個冰箱

      總結

        正如您在前一章中看到的,為了確定項目的成功,開發一種統一(通用)語言是至關重要的,項目的所有涉衆(從軟體工程師到領域專家)都會用它來更高效的交流。該語言應該反映出領域專家對業務領域内部工作和基本原則的思維模式。

        因為我們的目标是使用通用語言來驅動軟體設計決策,是以語言定義必須是清晰和一緻的。它應該沒有歧義、沒有隐含的假設和無關的細節。然而,在公司組織結構上,不同組織領域專家的心智模型本身可能是不一緻的。不同的領域專家可以使用同一業務領域的不同模型。讓我們看一個例子。

        不一緻的模型

        我們以電話營銷公司為例。該公司的營銷部門通過線上廣告創造商機。它的銷售部門負責招攬潛在客戶購買它的産品或服務,這一過程如下圖所示。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

示例業務域:電話營銷公司題

        對這些領域專家的語言含義進行研究可以發現一個特殊的現象。“線索”一詞在市場和銷售部門有不同的含義:

         市場營銷部門:

        對于市場營銷人員來說,線索表示有人對某一産品感興趣。收到潛在客戶的聯系方式的事件被認為是一個線索。

        銷售部門:

        在銷售部門中,線索代表是潛在客戶,潛在客戶是一個更為複雜的實體。它代表了銷售過程的整個生命周期。這不僅僅是一個事件,而是一個長期運作的過程。

        在這家電話營銷公司的案例中,我們如何制定一種統一語言?

        一方面,我們知道統一語言必須是一緻的——每個術語都應該有一個意思。另一方面,我們知道統一語言必須反映領域專家的心理模型。

        在這種情況下,市場營銷部的領域專家和銷售部門的領域專家對“線索”的了解就不一緻了。在人與人之間的普通交流中,這種模糊性并不會帶來太大的挑戰。事實上,來自不同部門的人員之間的溝通可能更具挑戰性,但人們很容易從交流的上下文推斷出确切的含義。

        然而,在軟體中表示這樣一個業務領域的發散模型是比較困難的。源代碼不能很好地處理模糊性。如果我們将銷售部門的複雜模型引入到市場營銷部門中,它将畫蛇添足——會給營銷人員增加更多他們不需要關注的細節和行為。但如果我們試圖根據營銷部門的了解簡化銷售部門的模型,它将無法滿足銷售子域的需求,因為它對于銷售過程的管理和優化來說太簡單了。在第一種情況下,我們會有一個設計過度的解決方案,而在第二種情況下,我們會有一個設計不足的解決方案。

        那我們如何解決這個兩難的問題呢?

        這個問題的傳統解決方案是設計一個單一的模型,可以用于各種各樣的問題。這樣的模型會出現跨越整個辦公室牆壁的巨大實體關系圖(erd)。類似下圖:

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

企業範圍的實體關系圖

        俗話說:“樣樣通,樣樣不精”。這樣的模型被認為适用于一切,但最終卻毫無效果。無論您做什麼,您總是要面對複雜性:過濾無關細節的複雜性、找到您真正需要的内容的複雜性,以及最重要的是保持資料處于一緻狀态的複雜性。

        另一種解決方案是在有問題的術語前面加上上下文的定義:“營銷線索”和“銷售線索”。這将會在代碼中實作這兩個模型。然而,這種方法有兩個主要缺點。首先,它誘發了認知負荷。什麼時候應該使用哪種模型?沖突模型的實作越接近,就越容易出錯。其次,模型的實作不會與統一語言一緻。沒有人會在對話中使用字首。人們不需要這些額外的資訊,他們可以依賴場景上下文進行對話,也不會影響他們的了解。

        讓我們轉向處理此類場景的領域驅動設計模式:界限上下文模式。

        什麼是界限上下文?

        領域驅動設計的解決方案很簡單:将統一語言劃分為多個更細粒度的語言,然後将每個語言配置設定到可以應用它的顯式上下文:界限上下文。

        在前面的例子中,我們可以确定兩個界限上下文:營銷“marketing ”和銷售“sales”。如下圖所示,lead一詞在兩種界限上下文中都存在。隻要它在每個界限上下文中具有單一的含義,每一種細粒度的通用語言都是一緻的,并遵循領域專家的思維模型。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

通過将統一語言劃分到界限上下文中來解決不一緻的問題

        在某種意義上,術語沖突和隐蔽性内容是任何規模可觀的業務的少不了的問題。使用界限上下文模式,将上下文模組化為業務領域的顯式和不可分割的部分。

        有界模型

        正如我們在前一章所讨論的,模型不是真實世界的副本,而是幫助我們了解複雜系統的構造。它要解決的問題是模型固有的一部分——它的目标範圍。模型不能沒有邊界而存在;它将擴充成為現實世界的複制品,這使得定義模型的邊界-它的界限上下文,成為模組化過程的固有部分。

        讓我們回到地圖作為模型的例子。我們看到每張地圖都有其特定的上下文比如:航空、航海、地形、地鐵等等。地圖隻有在其特定用途的範圍内才正确、有用。就像地鐵地圖對航海導航毫無用處一樣,一個界限上下文中的通用語言可能與另一個界限上下文中的作用域完全無關。界限上下文定義了統一語言及其所代表的模型的适用性。它們允許根據不同的問題域定義不同的模型。換句話說,界限上下文是統一語言的一緻性邊界。語言的術語、原則和業務規則隻在其界限上下文中是一緻的。

       統一語言精練

界限上下文允許我們完成對統一語言的定義。一種統一語言并不“通用”,因為它應該在整個組織中“通用”地使用和應用。一種統一語言并不是通用的。

        相反,一種統一語言隻在其界限上下文的邊界中是通用的。該語言隻專注于描述界限上下文内所包含的模型。由于模型不可能在沒有它應該解決的問題的情況下存在,在沒有明确的适用性上下文的情況下,統一語言無法被定義或使用。

       界限上下文的作用域

        本章開頭的示例示範了業務域的固有邊界。不同的領域專家對同一企業實體持有互相沖突的内心模型。要對業務領域模組化,我們必須劃分模型并為每個細粒度模型定義嚴格的适用性上下文--它的界限上下文。

        統一語言的一緻性隻有助于确定該語言的最寬邊界。它不能再大了,因為那樣就會有不一緻的模型和術語。然而,我們仍然可以将模型進一步分解成更小的界限上下文,如下圖所示

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

更細粒度的界限上下文

         定義統一語言的範圍,它的界限上下文,是一項戰略性的設計決策。邊界可以是寬的,遵循業務領域的固有上下文;也可以是窄的,進一步将業務領域劃分為更小的問題域。

        界限上下文的作用域并不是由它本身決定。模型不一定要大或小。模型必須是有用的。統一語言的邊界越寬,就越難保持一緻。将一種大的通用語言劃分為更小的、更易于管理的問題域可能是有益的,但是追求小的界限上下文也會适得其反。它們越小,設計産生的內建開銷就越大。

        是以,界限上下文的作用域應該取決于特定的問題域本身。有時,使用較寬的邊界會更清晰,而在其他時候,進一步分解它會更有意義。

        從大的界限上下文中提取細粒度的界限上下文的原因,包括組成新的軟體工程團隊或解決系統的一些不應承擔的問題功能和需求;例如,在原有的界限上下文中,有一部分元件需要在不同的開發周期中疊代實作時,需要進一步拆分成小的界限上下文,提取功能的另一個常見原因是能夠獨立于有界上下文,提供給其餘功能擴充它。

        是以,保持您的模型有用,并使界限上下文的作用域與您的業務需求群組織結構保持一緻。要注意的一件事是将一個連貫的功能拆分到多個界限上下文中,這樣的拆分将阻礙每個上下文獨立發展的能力。這時候還會起到另外一個反作用,同一個的業務需求的更改,将影響其他界限上下文,同時做出更改和釋出。

        為了避免這種無效的分解,請使用我們在第一章讨論過的尋找子域的方法:識别出操作相同資料的用例集,并避免将它們分解為多個有界上下文。

     界限上下文與子域的對比

        我們已經知道業務域一般由多個子域組成。到目前為止,在本章中,我們探索了将業務域分解為一組細粒度問題域或界限上下文的概念。起初,分解業務域的兩種方法可能看起來是多餘的。然而,事實并非如此。讓我們來看看為什麼需要這兩種邊界劃分。

      子域

        要了解一個公司的經營戰略,我們必須分析它的業務領域。根據領域驅動的設計方法,分析階段涉及識别不同的子領域(核心、支援和通用)。這就是公司機構如何運作和規劃競争戰略的方式。

        正如您在第一章中學到的,子域類似于一組互相關聯的用例集合。用例由業務域和系統需求定義。作為軟體工程師,我們不定義需求,這是企業業務的責任。相反,我們正在分析業務域以識别子域。

      界限上下文

        另一方面,界限上下文是設計出來的。模型邊界的標明是一個戰略性的設計決策。我們決定如何将業務領域劃分為較小的、可管理的問題領域。

      子域和有界上下文之間的互相作用

        從理論上講,盡管不切實際,但一種模式可以跨越整個商業領域。這種政策适用于小型系統,如圖所示。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

整體界限上下文

 當沖突模型出現時,我們可以遵循領域專家的心智模型,将系統分解成界限上下文,如下圖所示。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

統一語言一緻性驅動劃分的界限上下文

         如果模型仍然很大并且很難維護,我們可以将它們分解成更小的界限上下文;例如,每個子域都有一個界限上下文,如下圖所示。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

與子域邊界對其的界限上下文

         無論哪種方式,這都是一個設計決定。我們将這些邊界設計為解決方案的一部分。在某些場景中,界限上下文和子域之間的一對一關系是完全合理的。然而,在其他情況下,不同的劃分政策可能更适合。關鍵是要記住子域是被發現的,界限上下文是被設計的。子域由業務戰略定義。然而,我們可以設計軟體解決方案和它的界限上下文來處理特定項目的上下文和限制。

        最後,正如您在第一章中了解到的,模型旨在解決特定問題。在某些情況下,同時使用同一概念的多個模型來解決不同的問題可能是有益的。由于不同類型的地圖提供了不同類型的關于我們星球的資訊,使用同一子域的不同模型來解決不同的問題可能是合理的。将設計限制在界限上下文之間的一對一關系會抑制這種靈活性,并迫使我們在其界限上下文中使用子域的單一模型。

      邊界

        正如Ruth Malan所說,架構設計本質上是關于邊界的:

        架構設計就是系統設計。系統設計是一種情境設計,它本質上是關于邊界(裡面有什麼,外面有什麼,跨越了什麼,什麼在内外之間移動),以及關于權衡。它重塑了外在的東西,正如它塑造了内在的東西一樣。

        界限上下文模式是用于定義實體邊界和所有權邊界的領域驅動設計工具。        

       實體邊界   

        界限上下文不僅作為模型邊界,而且作為實作它們的系統的實體邊界。每個界限上下文都應該作為一個單獨的服務/項目,這意味着它的實作、更新和版本控制獨立于其他界限上下文。界限上下文之間清晰的實體邊界允許我們使用最适合其需求的技術棧來實作每個界限上下文。

        正如我們前面所讨論的,界限上下文可以包含多個子域。在這種情況下,界限上下文是一個實體邊界,而它的每個子域是一個邏輯邊界。邏輯邊界在不同的程式設計語言中具有不同的名稱:命名空間(namespace)、子產品(modules)或包(packages)。

        所有權邊界                    

        研究表明,好的籬笆确實能造就好鄰居。在軟體項目中,我們可以利用模型邊界:界限上下文,來實作團隊的和平共處。團隊之間的工作分工是可以使用界限上下文模式做出的另一個戰略決策。界限上下文應該隻由一個團隊實作、更新和維護。沒有兩個團隊可以在相同的界限上下文中工作。這種隔離消除了團隊可能對彼此的模型做出的隐含假設。相反,他們必須定義通信協定,以顯式地內建他們的模型和系統。

        需要注意的是,團隊和界限上下文之間的關系是單向的:一個界限上下文應該隻屬于一個團隊。然而,一個團隊可以擁有多個界限上下文,如下圖所示。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

界限上下文和團隊關系

      現實生活中的界限上下文

        确實,界限上下文不像業務域和子域那麼明顯,但它們确實存在,就像領域專家的心智模型一樣。您隻需要意識到領域專家如何思考不同的業務實體和流程。

        我想通過讨論一些例子來結束這一章,這些例子表明,當我們在軟體中模組化業務領域時,不僅有界限上下文,而且在不同的上下文中使用不同的模型的概念在生活中普遍存在。

      語義域

        可以說,領域驅動設計的界限上下文是基于語義域的詞典編纂概念的。語義域被定義為一個意義區域和用來談論它的詞語。例如,這幾個詞“螢幕”、“端口”和“處理器”在軟體和硬體工程語義域中具有不同的含義。

        不同語義域的一個相當奇特的例子是“番茄”這個詞的意思。

        根據植物學的定義,果實是植物傳播種子的方式。果實應該從植物的花朵中生長出來,并且至少有一顆種子。另一方面,蔬菜是一個總稱,包括植物的所有其他可食用部分:根、莖和葉。根據這個定義,蕃茄是一種水果。

        然而,這個定義在烹饪界幾乎沒有什麼用處。在這種情況下,水果和蔬菜是根據它們的味道來定義的。水果質地柔軟,有酸有甜,可以生吃,而蔬菜質地較硬,味道較淡,通常需要烹調。根據這個定義,蕃茄是一種蔬菜。

        是以,在植物學的限定語境中,番茄是一種水果,而在烹饪界的限定語境中,它是一種蔬菜。但這還不是全部。

        1883年,美國對進口蔬菜征收10%的稅,但不包括水果。根據植物學對番茄的水果定義,向美國進口番茄無需繳納進口稅。為了填補這個漏洞,1893年美國最高法院決定将蕃茄歸類為蔬菜。是以,在有限的稅收背景下,番茄又成了一種蔬菜。

      科學

         正如曆史學家尤瓦爾·諾亞·哈拉裡所說:“科學家們普遍認為,沒有任何理論是百分之百正确的。是以,真正考驗知識的不是真理,而是實用。”     。 換句話說,沒有一種科學理論适用于所有情況。不同的理論适用于不同的環境。 

      買一個冰箱

        最後,讓我們看一個現實生活中界限上下文的更實際的例子。你在下圖中看到了什麼?

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

紙闆兒

         它隻是一塊硬紙闆嗎?不,這是個模型。這是西門子KG86NAI31L冰箱的一種型号。如果你查一下,你可能會說這塊硬紙闆看起來一點也不像那個冰箱。它沒有門,甚至它的顔色也不一樣。雖然這是事實,但這無關緊要。正如我們所讨論的,模型不應該複制真實世界的實體。相反,它應該有一個目的:一個它應該解決的問題。是以,關于紙闆的正确問題是,這個模型解決了什麼問題?

在我們的較高價的電梯大廈裡,我們沒有一個标準的廚房入口。紙闆被精确地切成冰箱寬度和深度的大小。它解決的問題是檢查冰箱是否能通過廚房門。

戰略設計部分:控制核心域的複雜性        不一緻的模型        什麼是界限上下文?     界限上下文與子域的對比      邊界      現實生活中的界限上下文      總結

廚房門口的紙闆模型

         盡管紙闆看起來一點也不像冰箱,但當我們不得不決定是買這個型号還是選擇一個小一點的型号時,它被證明是非常有用的。再說一次,所有模型都是錯誤的,但有些模型是有用的。制作冰箱的3D模型絕對是一個有趣的項目。但它能比硬紙闆更有效地解決問題嗎?沒有。如果紙闆适合,3D模型也會适合,反之亦然。用軟體工程的術語來說,建立一個冰箱的3D模型将是一個籠統的工程。

        但是冰箱的高度呢?如果底座合适,但太高了,無法塞進門口怎麼辦?這樣就可以用膠水把冰箱的3D模型粘在一起了嗎?不。用一個簡單的卷尺來測量門道的高度,這個問題可以更快更容易地解決。在這種情況下,卷尺是什麼?另一個簡單的模型。

        是以,我們最終得到了兩個相同型号的冰箱。用兩個模型,每個模型都針對其特定的任務進行了優化,反映了DDD方法對業務域進行模組化。每個模型都有其嚴格的限定環境:紙闆證明冰箱底座可以通過廚房入口,皮尺證明它不會太高。模型應該省略與手頭任務的無關資訊。此外,如果有多個模型,就沒有必要設計一個複雜的多面手模型,更簡單的模型可以有效地單獨解決每個問題。

      總結

        每當我們在領域專家的心智模型中遇到内在沖突時,我們必須将統一語言分解到多個界限上下文中。統一語言應該在其界限上下文的範圍内保持一緻。但是,跨越多個界限上下文時,相同的術語可能具有不同的含義。

        在發現子域的同時,界限上下文就被設計出來了。将領域劃分為界限上下文是一項戰略設計決策。

        一個界限上下文及統一語言可以由一個團隊實作和維護。沒有兩個團隊可以在同一個界限上下文中共享工作。然而,一個團隊可以處理多個界限上下文。

        界限上下文可以将系統分解為實體拆分:服務、子系統等等。每個界限上下文的生命周期都與其他上下文解耦。每個界限上下文可以獨立于系統的其餘部分發展。然而,界限上下文必須一起工作以形成一個系統。有些更改将無意中影響另一個界限上下文。在下一章中,我們将讨論內建界限上下文的不同模式,這些模式可用于保護它們免受級聯更新的影響。