早期我在設(shè)計(jì)系統(tǒng)的時(shí)候,尚沒有聽過Microkernel設(shè)計(jì)模式折柠。那時(shí)候我就在想讳苦,如何才能設(shè)計(jì)出來一個(gè)“長青系統(tǒng)”带膜。它能夠最大程度的順應(yīng)系統(tǒng)的演化,具有極強(qiáng)的擴(kuò)展性医吊,極好的模塊化钱慢。
直到前幾天讀《面向模式的軟件架構(gòu)》的時(shí)候,讀到了Microkernel設(shè)計(jì)模式卿堂,才恍然發(fā)現(xiàn)我之前設(shè)計(jì)系統(tǒng)采取的一些措施和手段束莫,實(shí)際上就是使用了Microkernel設(shè)計(jì)模式。不過到底缺乏理論支持草描,那些系統(tǒng)看上去并不夠精致览绿。
背景與問題
Microkernel設(shè)計(jì)模式,其背景原書中寫的是:
使用依賴于相同核心功能的編程接口開發(fā)多個(gè)應(yīng)用程序
不過對于我這種側(cè)重業(yè)務(wù)的開發(fā)而言穗慕,它可以被描述為:
使用依賴于相同核心功能的編程接口接入多個(gè)業(yè)務(wù)
在我所涉及的需求饿敲,大多數(shù)都是具有良好的通用性——因?yàn)槲宜诘牟块T,涉及的類目實(shí)在過多逛绵。很多需求都不能僅為當(dāng)前類目開發(fā)怀各,而要充分考慮到其余的類目倔韭。此外就是,我主要負(fù)責(zé)的一款商業(yè)產(chǎn)品瓢对,它類似于一個(gè)平臺寿酌,允許各個(gè)業(yè)務(wù)方開發(fā)各色功能接入這個(gè)平臺。這些功能可以被組合成不同的產(chǎn)品硕蛹,執(zhí)行不同的售賣策略醇疼。尤其特殊的是,有很多功能也是我們開發(fā)的法焰。于是我們既扮演了一個(gè)平臺方的角色秧荆,又扮演了一個(gè)業(yè)務(wù)方的角色。
不論是哪種情況埃仪,都要求必須能夠適應(yīng)業(yè)務(wù)的不斷發(fā)展乙濒。
解決方案
早期我思考的一個(gè)解決方案就是,保持系統(tǒng)的核心盡量與業(yè)務(wù)特征剝離贵试。有時(shí)候我會把這個(gè)稱為“業(yè)務(wù)無關(guān)內(nèi)核”琉兜。這其實(shí)是我從哲學(xué)上收獲的一個(gè)啟發(fā)。哲學(xué)上講“內(nèi)涵越小毙玻,外延越大”豌蟋,而“內(nèi)涵越大,外延越小”桑滩。對于一個(gè)系統(tǒng)來說梧疲,要想適應(yīng)不同的業(yè)務(wù),也就是要具有很強(qiáng)大的“外延”运准,那么就必須保持“內(nèi)涵”小幌氮。
我們可以這樣想:如果一個(gè)內(nèi)核具有極強(qiáng)的業(yè)務(wù)特征,那么每次接入一個(gè)新的業(yè)務(wù)的時(shí)候胁澳,這個(gè)內(nèi)核都要修改该互,以納入這個(gè)業(yè)務(wù)的特征。如果我們可以預(yù)見到所有要接入的業(yè)務(wù)的特征韭畸,那么宇智,我們就可以讓內(nèi)核具有所有這業(yè)務(wù)的特征。但是很顯然的是胰丁,我們并不能做到這一點(diǎn)随橘。很多時(shí)候,在設(shè)計(jì)系統(tǒng)的初期锦庸,是基本不可能預(yù)見到會接入什么樣的業(yè)務(wù)的机蔗。所以這條思路是不行的。
可行的是,讓內(nèi)核不具有任何的業(yè)務(wù)特征萝嘁。如果一個(gè)內(nèi)核不具有任何的業(yè)務(wù)特征梆掸,那么它就可以接入各種業(yè)務(wù)特征。所以其實(shí)質(zhì)而言牙言,所謂Micorkenel沥潭,我的理解是:
微內(nèi)核中實(shí)現(xiàn)必不可少的功能,但是這些功能應(yīng)該與具體業(yè)務(wù)特征無關(guān)嬉挡,而僅僅與接入各種業(yè)務(wù)的方式有關(guān)。
也可以從《Unix編程藝術(shù)》中的“提供機(jī)制汇恤,而不是策略”來理解Microkernel庞钢。我認(rèn)為,Microkenel設(shè)計(jì)模式中的內(nèi)核就是提供機(jī)制因谎,剩余的策略都是圍繞內(nèi)核來構(gòu)建基括,但是并不是屬于內(nèi)核的一部分。于是所有的接入業(yè)務(wù)财岔,包括其內(nèi)部實(shí)現(xiàn)风皿,都只是一種策略。
機(jī)制是一種更加高層次的抽象匠璧,因此也越穩(wěn)定桐款。
在內(nèi)核設(shè)計(jì)了這種機(jī)制后,我們自己也可以作為一個(gè)業(yè)務(wù)方夷恍,利用這種機(jī)制實(shí)現(xiàn)自己的策略魔眨。我們的實(shí)現(xiàn)和別的業(yè)務(wù)方在抽象層次上是平等的。不過可以利用一些內(nèi)核所不暴露給第三方的特殊接口酿雪,實(shí)現(xiàn)一些比較特殊的功能遏暴。這樣就可以引入了Microkernel設(shè)計(jì)模式里面的兩個(gè)其他角色:
- 內(nèi)部服務(wù)器(internal server):擴(kuò)展了內(nèi)核提供的功能,是一個(gè)提供額外功能的獨(dú)立組件指黎。微內(nèi)核通過服務(wù)請求調(diào)用內(nèi)部服務(wù)器的功能朋凉,因此內(nèi)部服務(wù)器可以封裝一些與底層硬件或軟件系統(tǒng)相關(guān)的細(xì)節(jié);
- 外部服務(wù)器(external server):是使用微內(nèi)核實(shí)現(xiàn)其底層應(yīng)用領(lǐng)域視圖的組件醋安。視圖是抽象層杂彭,建立在微內(nèi)核提供的不可分割的服務(wù)的基礎(chǔ)上。不同外部服務(wù)器為特定應(yīng)用領(lǐng)域?qū)崿F(xiàn)了不同的策略茬故;
這是一種針對不同平臺的說法盖灸。就側(cè)重業(yè)務(wù)而言,并且依據(jù)我個(gè)人的理解為磺芭,它應(yīng)該被表述為:
- 內(nèi)部服務(wù)器:擴(kuò)展了內(nèi)核提供的功能赁炎,是一個(gè)提供額外功能的獨(dú)立組件。該組件由維護(hù)內(nèi)核的團(tuán)隊(duì)維護(hù),可以利用未被暴露出去的“特權(quán)”服務(wù)實(shí)現(xiàn)某些特性徙垫,以支持客戶端調(diào)用讥裤;
- 外部服務(wù)器:是利用微內(nèi)核實(shí)現(xiàn)的與業(yè)務(wù)相關(guān)的服務(wù)∫霰ǎ可以被客戶端直接調(diào)用己英;
注意的是,無論是內(nèi)部服務(wù)器還是外部服務(wù)器吴旋,都是一個(gè)獨(dú)立的組件损肛,并且應(yīng)該支持可插拔∪偕可插拔意味著治拿,內(nèi)外部服務(wù)器是可以隨時(shí)增加,減少或者替換的笆焰。這是滿足擴(kuò)展性的一個(gè)核心要求劫谅。
微內(nèi)核還可以增加一個(gè)適配層。但是這個(gè)適配層是可選的嚷掠。對于簡單的應(yīng)用來說捏检,加上一個(gè)適配層可能過于復(fù)雜,太重了不皆。但是如果需要避免客戶端對內(nèi)外部服務(wù)器的直接依賴贯城,那么就需要加上這個(gè)適配層∨Γ或者說冤狡,希望對客戶端暴露一個(gè)統(tǒng)一的api,那么也需要加上這個(gè)適配層项棠。但是直接依賴于內(nèi)外部服務(wù)器悲雳,對于大多數(shù)應(yīng)用來說,應(yīng)該不會出現(xiàn)太大的問題香追。
于是我們現(xiàn)在可以得到整個(gè)系統(tǒng)的劃分了:
就圖而言合瓢,越是往中心,其變化就越少透典,就越穩(wěn)定晴楔;越是往外邊,就越貼近業(yè)務(wù)峭咒,知道最外面的真的業(yè)務(wù)——客戶端税弃。
例子
我想用我在可配置前端頁面的解決方案里面的例子來作為一個(gè)說明:
我在那里要設(shè)計(jì)的是一個(gè)可配置的頁面,它基本上遵循了Microkernel的設(shè)計(jì)模式(雖然我設(shè)計(jì)的時(shí)候并沒有系統(tǒng)的學(xué)習(xí)Microkernel設(shè)計(jì)模式的理論)凑队。我在文中提及的一點(diǎn)是则果,因?yàn)槲覠o法預(yù)料到將來頁面會有多少組件,會有多少預(yù)定義的動(dòng)作。所以我設(shè)計(jì)了一個(gè)小巧而精致的內(nèi)核西壮,內(nèi)核里面沒有定義任何組件遗增,它提供的是通信模塊,事件模塊款青,Module模塊和model模塊做修。這些模塊的實(shí)現(xiàn)里面并不含有任何與業(yè)務(wù)相關(guān)的信息。所以可以將其稱為一個(gè)業(yè)務(wù)無關(guān)的核心抡草。
于此同時(shí)饰及,我預(yù)定義了一大批的組件,如輸入框康震,復(fù)選框旋炒;還預(yù)定義了部分事件。這部分預(yù)定義的組件組成的預(yù)定義Module签杈,其實(shí)就是充當(dāng)了內(nèi)部服務(wù)器的角色。所不同的是鼎兽,這些組件并沒有用到什么“特權(quán)服務(wù)”答姥,它使用的接口與暴露給自定義組件的接口是一致的。
同樣道理谚咬,第三方module就是充當(dāng)了一個(gè)外部服務(wù)器的角色鹦付。注意的是,這個(gè)例子里面我并沒使用一個(gè)適配層择卦。
后記
這只能算是我對于Microkernel的一個(gè)簡單理解敲长。其實(shí)我描述的Microkernel與書中提及的有挺大的差異。一者是我理解可能有偏差秉继,另外一個(gè)可能是我在將這個(gè)設(shè)計(jì)模式與具體業(yè)務(wù)結(jié)合起來的時(shí)候祈噪,其中更改了一些概念。讀者應(yīng)該注意區(qū)分尚辑。