偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

限界上下文—邏輯邊界or物理邊界?

開(kāi)發(fā) 開(kāi)發(fā)工具
本文將徹底對(duì)限界上下文做一個(gè)全方位的解剖,包括解讀限界上下文的定義、價(jià)值,了解限界上下文的三種邊界,并提出如何識(shí)別限界上下文的方法。

邊界通過(guò)限界上下文來(lái)確定,這在領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)中具有非凡的意義。對(duì)應(yīng)于通用語(yǔ)言,限界上下文是語(yǔ)言的邊界,對(duì)于領(lǐng)域模型,限界上下文是模型的邊界,二者對(duì)應(yīng)于問(wèn)題空間(Problem Space)的界定。對(duì)于系統(tǒng)的架構(gòu),限界上下文還確定了應(yīng)用邊界和技術(shù)邊界,進(jìn)而幫助我們確定整個(gè)系統(tǒng)及各個(gè)限界上下文的解決方案。可以說(shuō),限界上下文是連接問(wèn)題空間與解決方案空間的重要橋梁。

那么,限界上下文所界定的邊界,究竟是邏輯邊界,還是物理邊界?這并沒(méi)有定論,需得依據(jù)不同場(chǎng)景而做出不同的決策。

邏輯邊界

根據(jù)業(yè)務(wù)對(duì)領(lǐng)域進(jìn)行邏輯分解時(shí),分與合是兩個(gè)矛盾而又統(tǒng)一的概念。合是目標(biāo),分是降低復(fù)雜度的一種手段。分實(shí)則是為了更好的合。通過(guò)業(yè)務(wù)分解,每個(gè)分解出來(lái)的限界上下文規(guī)模就變得更小,因而更容易理解和把控。由于這種分解是從業(yè)務(wù)相關(guān)性來(lái)考慮的,使得領(lǐng)域可以更加細(xì)分,業(yè)務(wù)分析師或者領(lǐng)域?qū)<揖涂梢灾灰笳莆崭蛹?xì)分的專精領(lǐng)域。

從系統(tǒng)的代碼模型(Code Model)看,所謂邏輯邊界有兩種表現(xiàn)形式。以Java為例,歸納如下:

  • 命名空間級(jí)別:邏輯邊界僅僅通過(guò)命名空間進(jìn)行界定,但是所有的限界上下文其實(shí)都處于同一個(gè)模塊中,編譯后都屬于同一個(gè)Jar包。
  • 模塊級(jí)別:在命名空間上是邏輯分離的,而不同限界上下文則屬于同一個(gè)項(xiàng)目的不同模塊,編譯后會(huì)生成各自的Jar包。若限界上下文之間存在依賴,則在運(yùn)行時(shí),這些Jar會(huì)被同時(shí)加載到同一個(gè)Java虛擬機(jī)中。這里所謂的“模塊”,在Java代碼中也可以創(chuàng)建為Jigsaw的module。

將限定上下文的邊界視為邏輯邊界是最常見(jiàn)也是最簡(jiǎn)單的一種形式。一方面邏輯的分離可以保證系統(tǒng)代碼的清晰結(jié)構(gòu),另一方面它也使得限界上下文之間的協(xié)作變得更加容易,更加高效。在物理上,限界上下文彼此之間的通信其實(shí)是無(wú)縫集成的,要重用的領(lǐng)域模型都可以直接訪問(wèn),并對(duì)模型類進(jìn)行實(shí)例化。如下是國(guó)際報(bào)稅系統(tǒng)的邏輯邊界(Java):

國(guó)際報(bào)稅系統(tǒng)的邏輯邊界(Java)

然而,正所謂越容易重用,就越容易產(chǎn)生耦合。編寫代碼時(shí),我們需要謹(jǐn)守這條無(wú)形的邏輯邊界,時(shí)刻注意不要逾界,并確定限界上下文各自對(duì)外公開(kāi)的接口,避免對(duì)具體的實(shí)現(xiàn)產(chǎn)生依賴。

采用邏輯邊界劃分限界上下文的系統(tǒng)架構(gòu)是單塊(Monolithic)架構(gòu),所有的限界上下文都部署在同一個(gè)進(jìn)程中,因此不能針對(duì)某一個(gè)限界上下文進(jìn)行水平伸縮。需要對(duì)限界上下文的實(shí)現(xiàn)進(jìn)行替換或升級(jí)時(shí),會(huì)影響到整個(gè)系統(tǒng)。即使我們守住了邏輯邊界,這種耦合仍然存在,導(dǎo)致各個(gè)限界上下文的開(kāi)發(fā)互相影響,團(tuán)隊(duì)之間的協(xié)調(diào)成本也隨之而增加。

物理邊界

邏輯邊界的壞,正是物理邊界的好;反過(guò)來(lái),物理邊界的壞,同樣是邏輯邊界的好。當(dāng)我們將限界上下文的邊界定義為物理邊界時(shí),每個(gè)限界上下文就變成了一個(gè)個(gè)細(xì)粒度的微服務(wù)。

這里,我們需要針對(duì)Eric Evans提出的“限界上下文”概念做進(jìn)一步澄清:限界上下文究竟是僅僅針對(duì)領(lǐng)域模型的邊界劃分,還是對(duì)整個(gè)架構(gòu)(包括基礎(chǔ)設(shè)施層以及需要使用的外部資源)垂直方向的劃分?正如前面對(duì)Eric Evans觀點(diǎn)的引用,他在《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》一書中明確地指出:“根據(jù)團(tuán)隊(duì)的組織、軟件系統(tǒng)的各個(gè)部分的用法以及物理表現(xiàn)(代碼和數(shù)據(jù)庫(kù)模式等)來(lái)設(shè)置模型的邊界。”顯然,限界上下文不僅僅作用于領(lǐng)域?qū)雍蛻?yīng)用層。它是架構(gòu)設(shè)計(jì)而非僅僅是領(lǐng)域設(shè)計(jì)的關(guān)鍵因素。

倘若我們將限界上下文的邊界視為物理邊界,則可以保證邊界內(nèi)的服務(wù)、基礎(chǔ)設(shè)施乃至于存儲(chǔ)資源、中間件等其他外部資源的完整性,最終形成自治的服務(wù)。限界上下文之間僅僅通過(guò)限定的方式以限定的通信協(xié)議和數(shù)據(jù)格式進(jìn)行通信,除此之外,彼此沒(méi)有任何共享,這種架構(gòu)被稱之為零共享架構(gòu)。這種架構(gòu)的表現(xiàn)形式為:每個(gè)限界上下文都有自己的代碼庫(kù)、數(shù)據(jù)存儲(chǔ)以及開(kāi)發(fā)團(tuán)隊(duì),每個(gè)限界上下文選擇的技術(shù)棧和語(yǔ)言平臺(tái)也可以不同。當(dāng)每個(gè)限界上下文都被物理隔離時(shí),一個(gè)限界上下文的開(kāi)發(fā)人員就不能調(diào)用另一個(gè)限界上下文的方法,或者將數(shù)據(jù)存儲(chǔ)在共享結(jié)構(gòu)中了,這可以避免因?yàn)楣蚕韼?lái)的耦合。下圖為危機(jī)分析系統(tǒng)的架構(gòu):

危機(jī)分析系統(tǒng)的架構(gòu)

物理分隔開(kāi)的限界上下文變得小而專,使得我們可以很好地安排遵循2PTs規(guī)則的小團(tuán)隊(duì)去治理它。然而,這種架構(gòu)的復(fù)雜度也不可低估。限界上下文之間的通信是跨進(jìn)程的,我們需要考慮通信的健壯性。數(shù)據(jù)庫(kù)是完全分離的,當(dāng)需要關(guān)聯(lián)之間的數(shù)據(jù)時(shí),需得跨限界上下文去訪問(wèn),無(wú)法享受數(shù)據(jù)庫(kù)自身提供的關(guān)聯(lián)福利。由于每個(gè)限界上下文都是分布式的,如何保證數(shù)據(jù)的一致性也是一件棘手的問(wèn)題。當(dāng)整個(gè)系統(tǒng)都被分解成一個(gè)個(gè)可以獨(dú)立部署的限界上下文時(shí),運(yùn)維與監(jiān)控的復(fù)雜度也隨之而劇增。

數(shù)據(jù)庫(kù)共享

在邏輯邊界和物理邊界中間,還存在一種折中的手段。在考慮限界上下文劃分時(shí),分開(kāi)考慮代碼模型與數(shù)據(jù)庫(kù)模型,就可能出現(xiàn)在代碼上分離,而在數(shù)據(jù)庫(kù)層面卻存在數(shù)據(jù)共享的形式,即多個(gè)限界上下文共享同一個(gè)數(shù)據(jù)庫(kù)。

因?yàn)闆](méi)有分庫(kù),在數(shù)據(jù)庫(kù)層面就可以更好地保證事務(wù)的ACID。這或許是該方案最有說(shuō)服力的證據(jù),但也可以視為是對(duì)“一致性”約束的妥協(xié)。

數(shù)據(jù)庫(kù)共享的問(wèn)題在于數(shù)據(jù)庫(kù)的變化方向與業(yè)務(wù)的變化方向會(huì)不一致。這種不一致性體現(xiàn)在兩個(gè)方面:

  • 耦合:雖然業(yè)務(wù)上限界上下文之間是解耦的,但是在數(shù)據(jù)庫(kù)層面依然存在強(qiáng)耦合關(guān)系
  • 水平伸縮:部署在應(yīng)用服務(wù)器的應(yīng)用服務(wù)可以根據(jù)限界上下文的邊界單獨(dú)進(jìn)行水平伸縮,但是在數(shù)據(jù)庫(kù)層面卻無(wú)法做到

根據(jù)Netflix團(tuán)隊(duì)提出的微服務(wù)架構(gòu)***實(shí)踐,其中一個(gè)最重要特征就是“每個(gè)微服務(wù)的數(shù)據(jù)單獨(dú)存儲(chǔ)”。但是服務(wù)的分離并不絕對(duì)代表數(shù)據(jù)應(yīng)該分離。數(shù)據(jù)庫(kù)的樣式(Schema)與領(lǐng)域模型未必存在一對(duì)一的映射關(guān)系。在對(duì)數(shù)據(jù)進(jìn)行分庫(kù)設(shè)計(jì)時(shí),如果僅僅站在業(yè)務(wù)邊界的角度去思考,可能會(huì)因?yàn)榉謳?kù)的粒度太小,導(dǎo)致不必要的跨庫(kù)關(guān)聯(lián)。因此,我們可以將“數(shù)據(jù)庫(kù)共享”模式視為一種過(guò)渡方案,不要在一開(kāi)始設(shè)計(jì)微服務(wù)的時(shí)候,就直接將數(shù)據(jù)徹底分開(kāi),而是采用演進(jìn)式的設(shè)計(jì)。

為了便于在演進(jìn)設(shè)計(jì)中將分表重構(gòu)為分庫(kù),從一開(kāi)始要注意避免在兩個(gè)表之間建立外鍵約束關(guān)系。某些關(guān)系型數(shù)據(jù)庫(kù)可能通過(guò)這種約束關(guān)系提供級(jí)聯(lián)更新與刪除的功能,這種功能反過(guò)來(lái)會(huì)影響代碼的實(shí)現(xiàn)。一旦因?yàn)榉謳?kù)而去掉表之間的外鍵約束關(guān)系,需要修改的代碼太多,會(huì)導(dǎo)致演進(jìn)的成本太高,甚至可能因?yàn)槟撤N疏漏帶來(lái)隱藏的Bug。

沒(méi)有外鍵約束關(guān)系可能在當(dāng)前增加了開(kāi)發(fā)成本,卻為未來(lái)的演進(jìn)打開(kāi)了方便之門。例如,在針對(duì)某手機(jī)品牌開(kāi)發(fā)的輿情分析系統(tǒng)中,危機(jī)查詢服務(wù)提供對(duì)識(shí)別出來(lái)的危機(jī)的查詢,需要通過(guò)userId獲得危機(jī)處理人、危機(jī)匯報(bào)人的詳細(xì)信息。左圖為演進(jìn)前直接通過(guò)數(shù)據(jù)庫(kù)查詢的方式,右圖則切斷了這種數(shù)據(jù)庫(kù)耦合,改為服務(wù)調(diào)用的方式:

服務(wù)調(diào)用的方式

倘若架構(gòu)被設(shè)計(jì)為數(shù)據(jù)庫(kù)共享,且兩個(gè)服務(wù)需要操作同一張數(shù)據(jù)表(這張表被稱之為“共享表”),則傳遞了一個(gè)信號(hào),即我們的設(shè)計(jì)可能出現(xiàn)了錯(cuò)誤:

  • 遺漏了一個(gè)限界上下文,共享表對(duì)應(yīng)的是一個(gè)被重用的服務(wù):買家在查詢商品時(shí),商品服務(wù)會(huì)查詢價(jià)格表中的當(dāng)前價(jià)格,而在提交訂單時(shí),訂單服務(wù)也會(huì)查詢價(jià)格表中的價(jià)格,計(jì)算當(dāng)前的訂單總額;共享價(jià)格數(shù)據(jù)的原因是我們遺漏了價(jià)格上下文,通過(guò)引入價(jià)格服務(wù)就可以解除這種不必要的數(shù)據(jù)共享。
  • 職責(zé)分配出現(xiàn)了問(wèn)題,操作共享表的職責(zé)應(yīng)該分配給已有的服務(wù):輿情服務(wù)與危機(jī)服務(wù)都需要從郵件模板表中獲取模板數(shù)據(jù),然后再調(diào)用郵件服務(wù)組合模板的內(nèi)容發(fā)送郵件;實(shí)際上從郵件模板表獲取模板數(shù)據(jù)的職責(zé)應(yīng)該分配給已有的郵件服務(wù)。
  • 共享表對(duì)應(yīng)兩個(gè)限界上下文的不同概念:倉(cāng)儲(chǔ)上下文與訂單上下文都需要訪問(wèn)共享的產(chǎn)品表,但實(shí)際上這兩個(gè)上下文需要的產(chǎn)品信息是完全不同的,應(yīng)該按照限界上下文的邊界分開(kāi)為產(chǎn)品建表。

為什么會(huì)出現(xiàn)這三種錯(cuò)誤的設(shè)計(jì)?根本原因還是在于我們沒(méi)有通過(guò)業(yè)務(wù)建模,而是在數(shù)據(jù)庫(kù)中隱式地進(jìn)行建模,因而在代碼中沒(méi)有體現(xiàn)正確的領(lǐng)域模型,從而導(dǎo)致了數(shù)據(jù)庫(kù)層面的耦合或共享。

【本文為51CTO專欄作者“張逸”原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)聯(lián)系原作者】

戳這里,看該作者更多好文

責(zé)任編輯:趙寧寧 來(lái)源: 51CTO專欄
相關(guān)推薦

2021-05-09 21:50:48

項(xiàng)目實(shí)踐上下文

2025-10-27 09:38:26

2017-05-11 14:00:02

Flask請(qǐng)求上下文應(yīng)用上下文

2012-12-31 10:01:34

SELinuxSELinux安全

2022-09-14 13:13:51

JavaScript上下文

2022-09-15 08:01:14

繼承基礎(chǔ)設(shè)施基礎(chǔ)服務(wù)

2025-07-09 08:55:39

2023-07-11 10:02:23

2024-09-30 14:10:00

2022-10-28 16:24:33

Context上下文鴻蒙

2025-03-18 08:14:05

2020-07-24 10:00:00

JavaScript執(zhí)行上下文前端

2021-07-26 07:47:36

Cpu上下文進(jìn)程

2025-06-06 08:00:00

上下文管理器Python開(kāi)發(fā)

2025-10-13 08:00:00

2022-07-05 08:09:26

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)

2019-05-06 14:36:48

CPULinux寄存器

2010-02-25 17:04:54

WCF實(shí)例上下文

2012-07-30 16:29:40

架構(gòu)架構(gòu)模式.NET

2022-04-24 15:37:26

LinuxCPU
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)