架構討論:關於“弦哥”對“粗”與“插”的架構總結及我的“外掛化”觀

道法自然發表於2013-09-16

1 引言

去年6月,“弦哥”在部落格園搞了一個架構分享評獎討論——《.Net專案分層與資料夾結構大全(最佳架子獎,吐槽獎,陰溝翻船獎揭曉)》,並在評獎完了之後,發表了一個總結——《弦哥杯.Net搭架子大賽總結》,弦哥之後還發表了另一篇文章——《對面向介面程式設計、按分層建專案的反思和新的分層結構思路》。這幾篇文章我個人覺得非常的有益,也很有意思。軟體架構已經發展多年了,多層軟體設計一直是主流,在一個解決方案中搞幾十個甚至上百個的專案也不是少數,特別是企業級應用,弦哥的文章給了大家關於架構的分享與交流。在我說的第二篇文章,“弦哥”語言風格堪稱“很黃很暴力”,幽默犀利,甚至諷刺起人來都不帶髒,顯得特有文化,由此也可以看出技術男都很有才且很多是“悶騷型”的,我沒有多少文化,不過,我也覺得我也是有點“悶騷”的。對於“總結”這篇文章,我老是忍不住要去對個位,好像“弦哥”的“粗”與“插”、“道”總和我本人——“道法自然”所推崇的“外掛化”開發方法有所關聯。不過,我這裡不想去反駁弦哥在這片文章的描述,主要是我實在幹不過弦哥,哈哈。在這裡,我想接著弦哥提出的很好的話題進行延展,談一談弦哥的總結及其結論依據和我的觀點。

 

2 弦哥語錄及其點評的獲獎架子

=================以下言論抄自弦哥,產權屬於弦哥本人======================

(1)最佳架子獎:  聖殿騎士!!!

評選理由:

老油條了,沒啥好說的....分層的描述很準確。

特別是WebModel(ViewModel)的理解和描述很到位,避免了搞ViewModel的設計過渡之嫌,如果你有設計ViewModel的話....

可惜缺乏對資料訪問層的描述,不知道會不會陰溝裡翻船...

(2)陰溝翻船獎 Artech

弦哥點評:Artech算是園子裡的大佬,貌似還出了書,不過發的這個架子有點出乎我意料,存在有一些值得商榷的問題:
1.從架子中的命名和大體結構明顯看出是走的DDD,在DDD中資料訪問的具體實現(就是夾子裡的DataAccess)應該是放在基礎設施層(就是夾子裡的Infrastructure),而Artech卻貌似只把Infrastructure作為了"非功能性需求"的Framework去用。並把Infrastructure叫“非業務模組”,顯得有些外行....
2.Products.BusinessComponent業務邏輯層 直接引用了Products.DataAccess,這也是個嚴重的問題,如果DataAccess是沒有介面的,那麼業務邏輯層依賴資料訪問層,在DDD和馬丁大叔的企業架構設計中,是一個反模式!!!,如果DataAccess裡有介面,那麼,DataAccess的介面應該是放在業務邏輯層的,然後通過依賴反轉去用,而DataAccess的具體實現是放在Infrastructure裡的。
3.如果沒有用WCF,那麼我認可可以省略掉DTO,但架子裡上的WCF,還把DTO和PO合二為一,這個我非常不贊同。
4.Products層和Products.BusinessComponent層邊界不清晰,按Artech描述 ,兩個層裡都可以放業務邏輯,但描述的模稜兩塊。而且基本可以看出Products.BusinessEntity又還是失血模型,這個設計完全讓人摸不著頭腦。Products層我猜是有點DDD中Application層的意思,但Artech明顯做的不對。
總之我感覺這個架子,裝的成分比較大,思路十分不清晰,命名很不規範,有失水準。

=================以上言論抄自弦哥,產權屬於弦哥本人======================

 

弦哥的評獎結果,我個人很認可,這兩位技術大佬大家都很熟悉,要是不知道這兩位老大,我覺得都不好意思在部落格園裡面混了。他們的架構都是典型的分層體系結構,他們的架構代表了部落格園技術界的頂尖水平(沒見老趙的分享,我覺得很是遺憾,老趙也是頂尖的技術悶騷男了)。從名字看,這兩個架子好像都是電子商務相關的專案,一個是“HP”商店,另一個是Video商店,看來“電商”這麼火爆是很有道理的。我想這樣的專案也必然是一個團隊來開發的,不同的人負責不同的功能模組。

 

後面,弦哥也寫了一篇總結,這篇總結很好看,“很黃很暴力”,弦哥的文化水平之高與之悶騷可見一斑。下面我抄一些弦哥的原話。

 

=================以下言論抄自弦哥,產權屬於弦哥本人======================

……

複雜的東西是沒有人會喜歡的,這也是理,但不能一概而論 。就像“大道至簡”,也有很多人愛BB,而且BB的很爽,四字一出道袍都TM飄起來了...我們拿國學和西學的對比來說明這個問題:

……

有時候太簡單意味著太粗,看上去很好,但很多複雜場景你根本沒考慮,全在理想狀態下活著。細節決定成敗,細節很繁瑣很討厭,但你無法遮蔽,你也無法給別人遮蔽....還真TM當自己是道長咋地~?

……

“粗”和“插”都是男人喜歡的兩個字眼,但真的萬金油嗎?近些年基於SOA的粗粒度服務思想和麵向構件、外掛的開發平臺在大廠商的搖旗吶喊中大行其道。國內有些農民科學家見狀也按耐不住,紛紛山寨,甚至披上國學的外衣裝神弄鬼。簡單的“插”不是不好,但要看情況,比如嬌小的日本妞,基本問題不大,但電信、銀行、醫療這些大行業系統就如俄羅斯姑娘,你那玩意兒就是牙籤攪水桶,能好使嗎?

=================以上言論抄自弦哥,產權屬於弦哥本人======================

 

弦哥原文更精彩,一定要拜讀!!!在這裡,我們們先來看看兩位大佬的架構。

 

3 從分層引出我推崇的”外掛化架構觀“

部落格園這兩位技術大佬聖殿騎士與Artech採用的分層有點類似,甚至構建了一些介面,用於層間解耦。在這種分層架構下,假設我們要實現3個功能,那麼這三個功能的實現會在上面的不同專案中由不同的程式碼來提供。正如我在《白話外掛框架原理》描述的一樣,這三個功能至少橫跨了表示層、業務層、資料層等層次,這些層次都由不同的專案來實現。

6

下面看看PetShop的Product功能的實現,Petshop的架構如下圖所示,由很多專案組成,各個層次使用至少一個專案來組織程式碼。

7

其中Product功能在Web、BLL、DALFactory、OracleDAL等專案中含有各個層次實現的程式碼。

8

這種基於分層的架構設計,已經是架構的一大進步,但是會有什麼問題呢?我們設想一下,假設這樣的專案是由多個人來開發的那麼:

(1)團隊裡面所有的人,都要下載到這樣的程式碼,你開發一個功能的時候,需要先學習,然後根據架構師知道,跨越不同的專案新增這個功能需要的介面、業務邏輯、資料訪問等程式碼,當然,還有相應的介面;

(2)團隊不同成員開發完成後,都需要提交相應的程式碼,然後大家一起將所作的功能整合起來,這個整合可能會從頭做最後;

(3)實現一個簡單的功能,也必須遵循這樣的架構,從介面、業務邏輯、資料訪問等,甚至介面 + 實現層次,沒有伸縮性;

(4)不同成員的程式碼可能交織在一起,出了問題甚至還不知道到底是誰幹的;

(5)有一部分層次,可能存在每一個人都會修改同一個檔案的程式碼,比如主介面,這時候程式碼的整合、版本控制、合併就更加麻煩了;

(6)如果讓一個新人來開發功能,你有沒有覺得入門很難,感覺整個解決方案很複雜?

(7)後期維護呢,你怎麼知道層間這些程式碼的依賴關係,你更改了會影響到其它功能,其它層次嗎?

(8)當我們只需要開發一個功能的時候,為什麼需要下載所有的程式碼?為什麼每個人都有所有程式碼的訪問許可權?

(9)如果一個功能在每一個層間,考慮瞭解耦,還大量使用了介面,這對除錯、程式碼定位,不更麻煩了嗎?(這點,弦哥在後面的一片文章也描述到了:《對面向介面程式設計、按分層建專案的反思和新的分層結構思路》)。

 

以上這些問題,估計弦哥也發現了,他在後面也特意發表了這篇文章《對面向介面程式設計、按分層建專案的反思和新的分層結構思路》,我對裡面所描述的思路非常的贊同。弦哥考慮以後一個模組就一個資料夾,裡面包含這個模組所有的東西(FYI:我所提倡的外掛化其實與之非常吻合,:),如果你用OSGi.NET外掛框架開發MVC應用,那將與以下的解決方案几乎類似了,甚至更簡潔),另外,也不整那麼多的介面,因為沒有意義。

弦哥對自己新架構的評價如下:

“整個視野非常乾淨,你可以集中精力幹你自己的事了!

接下來我們看看新框架整體的結構,只有三個專案!!!”

 

好了,下面我想來談談我的“外掛化架構觀“。

 

上面我已經提到了分層及其存在的一些問題,這樣的問題隨著專案越發複雜,其問題就越發明顯。我本人從2006年開始就在思索,對於一個稍微大點、負責的專案,該如何更好的把一幫人協作起來,讓他們來一起又快又簡單的實現一個專案。2006年我們有一個專案,9個人來參與,需要幹1年,從需求分析到功能實現、測試與維護,把這麼多人組織起來用這麼長的時間,有什麼好方法?如果用傳統的分層,那就需要把所有人的工作都混在一起,我非常厭倦這種不同的人將程式碼寫在一塊,需要不停整合不停交付,不停交付,不停測試,對我來說,一想到後面這種協作方式,我煩透了!

 

我覺得更好的方法是,每一個人都可以只關注直接的功能實現,每一個人都可以獨立的來進行開發,每一個人可以採用更合適的架構,每一個人都可以保持簡單!!也就是說,如果有一套方法,使得每一個人可以直接切入到自己需要實現的需求,那麼這可能是最簡單省事的,他不用關心介面、不用關心其他人開發方式、不用關心通用功能、不用管整合、不用遵循一堆介面,在我的功能裡面,怎麼簡單就怎麼來,N層?不,如果簡單的話,我用一層就實現,不行就兩層、三層,什麼面向介面、什麼IoC,通通說不,因為沒有必要,在這個功能實現裡面,不需要考慮太多擴充套件,不需要考慮太多複用,一切按照需要的來做,不用遵守一堆的約束。總而言之,我對現有的方式已經煩透了,因為我特別懶,我就想簡單快速的實現,然後能快快的漲工資,快快的拿到專案獎金!!

 

下面,我們來看一下,如果使用外掛化以後,假設還是實現3個功能,那麼此時,整個系統就變成由一對外掛組成的應用了。

9

每一個外掛均獨立實現,它在自己的外掛專案裡面實現了介面、業務邏輯和資料訪問,在開發測試過程中,只需要自己的專案。可以根據需要來進行分層,視角就非常的清晰了。

10

如果組織得更好,不同的外掛可以放到不同的解決方案中,比如如下解決方案是由程式猿A開發的功能。

14

如下解決方案是由程式猿B開發的功能。

16

這兩個程式猿開發完成後,可以直接組裝在一起就變成如下的軟體了。

11

 

4 外掛化與分層的簡單對比

從上面的文字,估計你已經能夠知道二者的區別了,我這裡簡單用功能A、B、C的實現來說說二者區別:

(1)在分層,一個功能,比如功能A,在實現中,需要同時跨越多個專案;在外掛化,一個功能在一個外掛專案中實現,一個外掛專案裡面直接包含了相關的所有程式碼;

(2)在分層,所有人都需要下載到複雜的程式碼;在外掛化,每一個人只需要下載自己實現的那一部分程式碼,非常的簡單與清晰;

(3)在分層,大家的程式碼都放在一起,需要不停的整合;在外掛化,每一個人的程式碼都與另一個人的程式碼互相隔離,互不相干;

(4)在分層,每次釋出都需要進行合併整合,可能需要更改程式碼;在外掛化,整合幾乎可以在幾秒內完成,大家獨立開發、測試、釋出,只需要將每一個人釋出的專案拷貝到外掛目錄就整合好了;

(5)在分層,每一個人都需要遵循層次劃分方法,不管功能簡單與複雜,都需要整那麼多的層次;在外掛化,每一個功能可以按照複雜度來處理,什麼N層、面向介面、IoC,我們可以說不,可以用1層、2層或者3層。

 

從這些文字你可以看出了,外掛化擁有很強的吸引力,但是,為什麼我們很難在實際專案中來使用外掛化呢?下面,我想針對這個問題做個描述——那就是關於外掛化的誤區。

 

5 外掛化誤用及我認為理想的外掛化框架

使我們開發協作過程保持簡單是我不停的思索更好方法來協作開發的原因。外掛化(或者模組化)的架構是目前最好的選擇了。不過,一開始,我是自己根據自己的理論來設計外掛框架的,當自己設計外掛框架的時候,我總是逃脫不了傳統的外掛化方法,那就是整個外掛介面,外掛實現就必須使用這個介面,如果有什麼很多功能是,甚至這個介面需要不停改變,這是外掛也需要不停的適應。這種擁有過多約束的外掛化框架在一定程度改善了分層架構的缺陷,但是卻帶來了下面的問題:(1)介面的定義影響系統的適應性;(2)外掛框架帶來了額外的約束,使得其他人在開發時需要不停與外掛框架API打交道。這讓其他人痛苦不堪。我想,關於外掛化的方法,很多人也估計有碰到這樣的問題,並且深有同感。

 

那麼,有什麼更好的方法可以既改善分層的缺陷,又能避免上述”外掛化“問題嗎?我的觀點是,外掛化思想是很好的架構,如果你使用外掛化並碰到上述的兩個問題,那麼一定是誤用了外掛化了。下面我來介紹一下外掛化的誤用及我的外掛化架構思想。

 

縱觀目前國內外,好像在.NET界還很少有成熟的外掛框架解決方案(當然,我們的OSGi.NET外掛框架除外,這框架是完全免費開放的,商用也不限制,只是苦於我們現在需要掙錢,暫時無法完全開源,請諒解,:),需要的同學可以從 http://www.iopenworks.com/ 這個網站下載)。很多人也特別痛恨各類框架,這些框架並沒有很好的解決我們面臨的問題,卻帶來更多的約束、學習成本和維護成本。這讓我們對框架有很多負面的想法,特別當我們只是一個小程式設計師時,我們更關注的是如何快速來實現功能,我們可能理解不了框架設計者和架構師的所謂框架。傳統的外掛框架都基本擺脫不了以下的”行規“,因為很多書本和理論也是這麼寫的,這些”行規“突出了:

(1)外掛框架是高深的技術,比如”熱插拔“,這種觀點強調的是技術本身,這項技術有多麼先進,有多麼強的可擴充套件性等;

(2)外掛框架基本都與一些介面繫結起來,要使用外掛框架就需要學習如何使用介面,要接受這套介面風格樣式,當然這也為外掛框架的複雜性帶來了影響,使設計外掛框架時需要來考慮各種各樣的介面;

(3)外掛框架本身實現了一堆功能,通過API說明書,來學會使用它們,並進行呼叫;

(4)外掛框架在開發維護過程中,由於帶來了很強的侵略性,使我們的外掛需要嚴重依賴於框架本身,這既帶來了複雜性,也隨著外掛框架的不穩定性帶來更多負面的影響;

(5)外掛框架設計的合理與否,關係到其他人是否可以接受並使用。

 

現在,我們再來看看那弦哥提出的”粗“與”插“的觀點,可能也是由這些問題引起的,我們再來回顧一下弦哥精彩言論。

 

=================以下言論抄自弦哥,產權屬於弦哥本人======================

“粗”和“插”都是男人喜歡的兩個字眼,但真的萬金油嗎?近些年基於SOA的粗粒度服務思想和麵向構件、外掛的開發平臺在大廠商的搖旗吶喊中大行其道。國內有些農民科學家見狀也按耐不住,紛紛山寨,甚至披上國學的外衣裝神弄鬼。簡單的“插”不是不好,但要看情況,比如嬌小的日本妞,基本問題不大,但電信、銀行、醫療這些大行業系統就如俄羅斯姑娘,你那玩意兒就是牙籤攪水桶,能好使嗎?

=================以上言論抄自弦哥,產權屬於弦哥本人======================

 

起初我很難理解為什麼弦哥會覺得電信、醫療等大行業系統,採用外掛化無法滿足,並覺得”插“太細了,這些”大姑娘“沒有辦法被很好的滿足。因為,從我的角度,外掛化(或者模組化)最初就是在複雜領域中應用的,你看主流的IDE(Eclipse使用OSGi外掛化規範構建、Visual Studio使用MAF/MEF框架構建、SharpDevelop使用SD核心、MonoDevelop使用Mono.Addins外掛核心)等很多複雜軟體,基本都是使用外掛化構建的,我真不認為外掛化無法滿足這些行業”大姑娘“。看來,阻礙我們接受外掛化架構方法,是因為傳統的”行規“引起的,我們學習到的”外掛化“太過於強調技術本身,並且設計的初衷可能是為了追求”熱插拔很酷“這一說,從而讓弦哥和我們們這樣的碼農的厭煩。

 

那麼,談到這,我不得不描述一下我的外掛化觀。

(1)外掛化不是複雜高深的技術,不是為了強調技術先進性,要解決的是如何實現隔離的模組化開發,使每一個人都獨立、簡單、並行;

(2)外掛化必須要保持簡單,我們只是想獲取到模組化的優勢,不是為了整個什麼高深的技術,因此,需要很快的就學會如何來開發;

(3)外掛化必須沒有侵入性,開發外掛時,我們不需要與外掛框架打交道,不需要了解外掛框架的技術原理和細節,不需要掌握外掛框架API,我們可以使用傳統的開發方式來快快的開發一個外掛,實現我們的功能;

(4)外掛框架不應該與介面繫結一起,也就是說,外掛框架核心必須保持簡單,只需要提供外掛的隔離與組裝、外掛通訊和擴充套件,不應該附帶實現一個介面。外掛框架附帶介面實現,是傳統的方法,但是這也給我們帶來了強制的約束,是我們在開發設計中都必須遵循,很煩;

(5)外掛框架可以適用任何應用,這樣,我們可以在所有的應用型別中使用統一的規範,減少成本。

 

如果用簡單的一句話,我想說的是理想的外掛化框架應該使我們少加班多掙錢,稍微技術一點的說法應該是:

外掛框架只是實現了我們要的模組化思想,解決了分層架構下的團隊協作缺陷,使每一個功能的實現更加的獨立,但不要附帶任何約束。凡是過多約束的外掛框架都不會被我們這幫懶惰的程式猿接受。

 

本文就到此結束了,希望大家能夠熱烈的參與架構討論,分享自己的架構心得、對外掛化架構的考慮,後面可以請弦哥再用很犀利的語言為我們評獎,當然,我也建議弦哥再舉辦一次這樣的大賽。這樣在部落格園Dudu的帶領下,我們可以早日有一個更加優越的方法,使得我們能夠成為真正的IT白領,能夠真正進入”嫁人就嫁程式猿“的理想社會,實現”程式猿崛起“!:)

 

附:外掛化應用系統分享。

我們來看一下一個外掛化應用系統,這是一個大型公建能耗採集分析平臺。

image

系統架構如下所示,這是一個分散式系統。

image

Web分析平臺專案結構如下所示,共16個外掛,9個是新定義,其餘為複用,另外新定義的資料模型外掛在其它程式中共享。這裡有7個應用外掛,每一個外掛都獨立實現一部分功能,由不同的開發人員來獨立實現,開發中不需要關心介面、資料庫訪問、許可權等通用功能,這些由歷史專案積累下來,直接重用。

image

image

GPRS通訊伺服器專案如下所示,12個外掛,2個是新定義,其餘為複用;資料模型等外掛與Web平臺共享。

image

image

配置管理工具專案如下所示。11個外掛,2個是新定義,其餘為複用;資料模型等外掛與Web平臺共享。

image

image

資料上報與接收系統專案如下所示。5個外掛,1個是新定義,其餘為複用;資料模型等外掛與Web平臺共享。

image

系統使用外掛倉庫來實現外掛釋出、管理、複用、組裝、升級。

image

開發過程中,實現了“DevOps”。

image

整合測試部署時,只需要簡單通過下載安裝或者直接下載升級即可。

23

下載安裝組裝後,就是如下的效果了,它很快就實現兩個開發人員功能的整合了。

11

應用外掛化開發成果如下:

•通過大量複用減少開發成本超過50%

•由4個程式構成,由5個人開發,歷時1.5個月,已完成工作量超過70%

•系統間有大量可複用外掛

•穩定整合與釋出

•開發習慣一致,井井有條

相關文章