在本人的前一篇文章《不要把微服務(wù)做成小單體》中,現(xiàn)在很多的微服務(wù)開(kāi)發(fā)團(tuán)隊(duì)在設(shè)計(jì)和實(shí)現(xiàn)微服務(wù)的時(shí)候覺(jué)得只要把原來(lái)的單體拆小,就是微服務(wù)了。但是這不一定是正確的微服務(wù),可能只是一個(gè)拆小的小單體。這篇文章讓我們從這個(gè)話題繼續(xù),先看看為什么拆出來(lái)的是小單體。
設(shè)計(jì)微服務(wù)的路徑依賴?yán)Ь?/h2>
在微服務(wù)架構(gòu)誕生之前,幾乎所有的軟件系統(tǒng)都是采用單體架構(gòu)來(lái)構(gòu)建的,因此大部分軟件開(kāi)發(fā)者喜歡的開(kāi)發(fā)路徑就是單體架構(gòu)模式。在這樣的背景下,根據(jù)經(jīng)濟(jì)學(xué)和心理學(xué)的路徑依賴法則,當(dāng)這些開(kāi)發(fā)者基于新的技術(shù)想要把原來(lái)的大單體拆分成多個(gè)部分時(shí),就必然會(huì)習(xí)慣性地采用自己最擅長(zhǎng)的單體架構(gòu)來(lái)設(shè)計(jì)每個(gè)部分。

路徑依賴法則:是指人類(lèi)社會(huì)中的技術(shù)演進(jìn)或制度變遷均有類(lèi)似于物理學(xué)中的慣性,即一旦進(jìn)入某一路徑(無(wú)論是“好”還是“壞”)就可能對(duì)這種路徑產(chǎn)生依賴。一旦人們做了某種選擇,就好比走上了一條不歸之路,慣性的力量會(huì)使這一選擇不斷自我強(qiáng)化,并讓你輕易走不出去。第一個(gè)使“路徑依賴”理論聲名遠(yuǎn)播的是道格拉斯·諾斯,由于用“路徑依賴”理論成功地闡釋了經(jīng)濟(jì)制度的演進(jìn),道格拉斯·諾斯于1993年獲得諾貝爾經(jīng)濟(jì)學(xué)獎(jiǎng)。
“路徑依賴”理論被總結(jié)出來(lái)之后,人們把它廣泛應(yīng)用在選擇和習(xí)慣的各個(gè)方面。在一定程度上,人們的一切選擇都會(huì)受到路徑依賴的可怕影響,人們過(guò)去做出的選擇決定了他們現(xiàn)在可能的選擇,人們關(guān)于習(xí)慣的一切理論都可以用“路徑依賴”來(lái)解釋。
在現(xiàn)實(shí)中我們經(jīng)??吹竭@個(gè)法則隨處都會(huì)發(fā)生,微信剛出來(lái)的時(shí)候很多人說(shuō)這不就是手機(jī)上的QQ嗎,朋友圈剛出來(lái)的時(shí)候他們又會(huì)說(shuō)這不就是抄襲微博嗎。很多時(shí)候當(dāng)你興致沖沖給朋友介紹一個(gè)新的東東時(shí),朋友一句話就能讓你萬(wàn)念俱灰:這不就是XXX嗎?之所以這樣,是因?yàn)槿祟?lèi)在接觸到新知識(shí)新概念的時(shí)候,都會(huì)下意識(shí)的使用以前知道的概念進(jìn)行套用,這樣的思維方式是人類(lèi)從小到大學(xué)習(xí)新事物的時(shí)候使用的模式,它已經(jīng)固化成我們大腦操作系統(tǒng)的一部分了。
理解了這個(gè)法則,我們就可以很容易的明白,已經(jīng)在單體架構(gòu)下開(kāi)發(fā)了多年的軟件工程師,當(dāng)被要求要使用微服務(wù)架構(gòu)來(lái)進(jìn)行設(shè)計(jì)和開(kāi)發(fā)的時(shí)候,本能的反應(yīng)方式肯定是:這不就是把原來(lái)的單體做小了嗎?但是這樣做出來(lái)的“微服務(wù)”真的能夠給我們帶來(lái)微服務(wù)架構(gòu)的那些好處嗎?真的能提高一個(gè)企業(yè)的數(shù)字化響應(yīng)力嗎?
不斷變化的軟件需求和經(jīng)常被視為效率低下的軟件開(kāi)發(fā)一直都是這個(gè)行業(yè)里最難解決的頑疾,從瀑布到敏捷,都是在嘗試找到一個(gè)解決這個(gè)頑疾的方法,領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)(Domain Driven Design)也是其中一個(gè)藥方,而且隨著十多年的不斷實(shí)踐,我們發(fā)現(xiàn)這個(gè)藥方有它自己的獨(dú)特之處,下面我們先來(lái)介紹一下這個(gè)藥方。
DDD簡(jiǎn)史

領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)這個(gè)概念出現(xiàn)在2003年,那個(gè)時(shí)候的軟件還處在從CS到BS轉(zhuǎn)換的時(shí)期,敏捷宣言也才發(fā)表2年。但是Eric Evans做為在企業(yè)級(jí)應(yīng)用工作多年的技術(shù)顧問(wèn),敏銳的發(fā)現(xiàn)了在軟件開(kāi)發(fā)業(yè)界內(nèi)(尤其是企業(yè)級(jí)應(yīng)用)開(kāi)始涌現(xiàn)的一股思潮,他把這股思潮成為領(lǐng)域驅(qū)動(dòng)設(shè)計(jì),同時(shí)還出版了一本書(shū),在書(shū)中分享了自己在設(shè)計(jì)軟件項(xiàng)目時(shí)采用的建模方法,并為設(shè)計(jì)決策者提供了一個(gè)框架。
但是從那以后DDD并沒(méi)有和敏捷一樣變得更加流行,如果要問(wèn)原因,我覺(jué)得一方面是這套方法里面有很多的新名詞新概念,比如說(shuō)聚合,限界上下文,值對(duì)象等等,要理解這些抽象概念本身就比較困難,所以學(xué)習(xí)和應(yīng)用DDD的曲線是非常陡峭的。另一方面,做為當(dāng)時(shí)唯一的“官方教材”《領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)》,閱讀這本書(shū)是一個(gè)非常痛苦的過(guò)程,在內(nèi)容組織上經(jīng)常會(huì)出現(xiàn)跳躍,所以很多人都是剛讀了幾頁(yè)就放下了。
雖然入門(mén)門(mén)檻有些高,但是對(duì)于喜歡智力挑戰(zhàn)的軟件工程師們來(lái)說(shuō),這就是一個(gè)難度稍為有一點(diǎn)高的玩具,所以在小范圍群體內(nèi),逐漸有一批人開(kāi)始能夠掌控這個(gè)玩具,并且可以用它來(lái)指導(dǎo)設(shè)計(jì)能夠控制業(yè)務(wù)復(fù)雜性的軟件應(yīng)用出來(lái)了。雖然那時(shí)候大部分的軟件應(yīng)用都是單體的,但是使用DDD依然可以設(shè)計(jì)出來(lái)容易維護(hù)而且快速響應(yīng)需求變化的單體應(yīng)用出來(lái)。

到了2013年,隨著各種分布式的基礎(chǔ)設(shè)施逐漸成熟,而SOA架構(gòu)應(yīng)用在實(shí)踐中又不是那么順利,Martin Fowler和James Lewis把當(dāng)時(shí)出現(xiàn)的一種新型分布式架構(gòu)風(fēng)潮總結(jié)成微服務(wù)架構(gòu)。然后微服務(wù)這股風(fēng)就呼呼的吹了起來(lái),這時(shí)候軟件工程師們發(fā)現(xiàn)一個(gè)問(wèn)題,就是雖然指導(dǎo)微服務(wù)架構(gòu)的應(yīng)用具有什么特征,但是如何把原來(lái)的大單體拆分成微服務(wù)是完全不知道怎么做了。然后熟悉DDD方法的工程師發(fā)現(xiàn),由于DDD可以有效的從業(yè)務(wù)視角對(duì)軟件系統(tǒng)進(jìn)行拆解,并且DDD特別契合微服務(wù)的一個(gè)特征:圍繞業(yè)務(wù)能力構(gòu)建。所以用DDD拆分出來(lái)的微服務(wù)是比較合理的而且能夠?qū)崿F(xiàn)高內(nèi)聚低耦合,這樣接著微服務(wù)DDD迎來(lái)了它的第二春。
下面讓我們站在軟件工程這個(gè)大視角看看DDD究竟是在做什么。
DDD思辨
從計(jì)算機(jī)發(fā)明以來(lái),人類(lèi)用過(guò)表達(dá)世界變化的詞有:電子化,信息化,數(shù)字化。這些詞里面都有一個(gè)“化”字,代表著轉(zhuǎn)變,而這些轉(zhuǎn)變就是人類(lèi)在逐漸的把原來(lái)在物理世界中的一個(gè)個(gè)概念一個(gè)個(gè)工作,遷移到虛擬的計(jì)算機(jī)世界。但是在轉(zhuǎn)變的過(guò)程中,由于兩個(gè)世界的底層邏輯以及底層語(yǔ)言不一致,就必須要有一個(gè)翻譯和設(shè)計(jì)的過(guò)程。這個(gè)翻譯過(guò)程從軟件誕生的第一天起就天然存在,而由于有了這個(gè)翻譯過(guò)程,業(yè)務(wù)和開(kāi)發(fā)之間才總是想兩個(gè)對(duì)立的階級(jí)一樣,覺(jué)得對(duì)方是難以溝通的。

于是乎有些軟件工程界的大牛就開(kāi)始思考,能不能有一種方式來(lái)減輕這個(gè)翻譯過(guò)程呢。然后就發(fā)明了面向?qū)ο笳Z(yǔ)言,開(kāi)始嘗試讓計(jì)算機(jī)世界有物理世界的對(duì)象概念。面向?qū)ο筮€不夠,這就有了DDD,DDD定義了一些基本概念,然后嘗試讓業(yè)務(wù)和開(kāi)發(fā)都能夠理解這些概念名詞,然后讓領(lǐng)域?qū)<沂褂眠@些概念名詞來(lái)描述業(yè)務(wù),而由于使用了規(guī)定的概念名詞,開(kāi)發(fā)就可以很好的理解領(lǐng)域業(yè)務(wù),并能夠按照領(lǐng)域業(yè)務(wù)設(shè)計(jì)的方式進(jìn)行軟件實(shí)現(xiàn)。這就是DDD的初衷:讓業(yè)務(wù)架構(gòu)綁定系統(tǒng)架構(gòu)。

后來(lái)發(fā)現(xiàn)這個(gè)方法不僅僅可以做好翻譯,還可以幫助業(yè)務(wù)劃分領(lǐng)域邊界,可以明確哪個(gè)領(lǐng)域是自己的核心價(jià)值所在,以后應(yīng)該重點(diǎn)發(fā)展哪個(gè)領(lǐng)域。甚至可以作為組織進(jìn)行戰(zhàn)略規(guī)劃的參考。而能夠做到這點(diǎn),其實(shí)背后的原因是物理世界和虛擬世界的融合。
舉個(gè)例子,比如說(shuō)在物理世界中要買(mǎi)一個(gè)商品,在沒(méi)有商品的時(shí)候我需要一個(gè)賬本來(lái)記錄有進(jìn)了哪些商品,每一個(gè)訂單買(mǎi)了多少商品,買(mǎi)一個(gè)商品賺了多少錢(qián)。這些工作在計(jì)算機(jī)世界里面也應(yīng)該要有商品,賬本,訂單,訂單明細(xì)這些概念,而且當(dāng)我說(shuō)賣(mài)出商品需要能夠從賬本中扣除庫(kù)存的時(shí)候。在計(jì)算機(jī)世界里面,就應(yīng)該是訂單對(duì)象在完成以后會(huì)調(diào)用賬本對(duì)象來(lái)扣減庫(kù)存。通過(guò)這種方式,每一個(gè)業(yè)務(wù)邏輯都可以很容易地找到軟件中對(duì)應(yīng)的對(duì)象來(lái)進(jìn)行實(shí)現(xiàn)。
用DDD走出設(shè)計(jì)微服務(wù)拆分困境
上面介紹了使用DDD可以做到綁定業(yè)務(wù)架構(gòu)和系統(tǒng)架構(gòu),這種綁定對(duì)于微服務(wù)來(lái)說(shuō)有什么關(guān)系呢。所謂的微服務(wù)拆分困難,其實(shí)根本原因是不知道邊界在什么地方。而使用DDD對(duì)業(yè)務(wù)分析的時(shí)候,首先會(huì)使用聚合這個(gè)概念把關(guān)聯(lián)性強(qiáng)的業(yè)務(wù)概念劃分在一個(gè)邊界下,并限定聚合和聚合之間只能通過(guò)聚合根來(lái)訪問(wèn),這是第一層邊界。然后在聚合基礎(chǔ)之上根據(jù)業(yè)務(wù)相關(guān)性,業(yè)務(wù)變化頻率,組織結(jié)構(gòu)等等約束條件來(lái)定義限界上下文,這是第二層邊界。有了這兩層邊界作為約束和限制,微服務(wù)的邊界也就清晰了,拆分微服務(wù)也就不再困難了。

而且基于DDD設(shè)計(jì)的模型中具有邊界的最小原子是聚合,聚合和聚合之間由于只通過(guò)聚合根進(jìn)行關(guān)聯(lián),所以當(dāng)需要把一個(gè)聚合根從一個(gè)限界上下文移動(dòng)到另外一個(gè)限界上下文的時(shí)候,非常低的移動(dòng)成本可以很容易地對(duì)微服務(wù)進(jìn)行重構(gòu),這樣我們就不需要再糾結(jié)應(yīng)不應(yīng)該這樣拆分微服務(wù)?拆出的微服務(wù)太少了以后要再拆分這樣的問(wèn)題了。
所以,經(jīng)過(guò)理論的嚴(yán)密推理和大量實(shí)踐項(xiàng)目的驗(yàn)證,ThoughtWorks認(rèn)為DDD是當(dāng)前軟件工程業(yè)界設(shè)計(jì)微服務(wù)的最佳實(shí)踐。雖然學(xué)習(xí)和使用DDD的成本有點(diǎn)高,但是如果中國(guó)的企業(yè)想再軟件開(kāi)發(fā)這個(gè)能力上從冷兵器時(shí)代進(jìn)入熱兵器時(shí)代,就應(yīng)該嘗試一下DDD了解一下先進(jìn)的軟件工程方法。