2008年3月13日星期四

軟體的病態性肥胖

文 / 蔡學鏞

根據行政院衛生署的定義,BMI(身體質量指數)大於24是過重,大於27是肥胖,而大於35者稱為病態性肥胖。如果我們也為軟體定義出一套BMI標準,那麼我相信,放眼望去,幾乎全都是五花肉的癡肥軟體。而我們都知道,『肥胖不等於健壯』,這句話同時適用於人體和軟體。

看看幾個主要平台。.NET在短短的幾年之間,在父母親餵食生長激素、猛喝高蛋白飲品、施打類固醇的情況下,很快地長成龐然大物,以六歲的稚齡擁有六十歲的大肚腩,就連美人遲暮的高齡Java都比.NET輕巧許多。即將粉墨登上舞台的Adobe AIR平台,以Java和.NET為戒,正努力地要減肥到10MB以內,但是好像必須先砍掉下半身才能達到,如果不砍掉,估計會達到10~15MB,幾乎是當初宣稱的理想體重(5~9MB)的兩倍。Adobe AIR一出生就這樣,以後還得了呀!.NET、Java、AIR可以合組平台小象隊。噸位最大的.NET當仁不讓是隊長囉!

再看看幾個常用的軟體,鏞週刊的鏞青天評價是:PDF Reader胖胖,JBuilder胖胖胖,Visual Studio胖胖胖胖,MS Office System胖胖胖胖胖。不過話說回來,當周遭都是胖子的時候,就不會有人覺得自己胖,所以可能這些軟體都覺得自己『還OK呀』。

軟體的肥胖是代謝症候群的象徵,已經成為「軟體的十大死因」之一,有相當多併發症。肥胖的軟體(我簡稱為肥軟),吃掉你的CPU計算能力,吃掉你的網路頻寬、記憶體、磁碟空間,且肥軟容易潛藏bug。當軟體胖到一個程度,安裝、使用、維護可能都會出問題。

總之,肥軟既吃垮你又拖累你,能擺脫它就盡量一腳把它踢開,而且也要小心不要讓自家生出的孩子是肥軟,成為別人一腳踢開的對象。

為何軟體會病態性地肥胖?把脈之後,從它的經絡脈像顯示,有下面的原因。當然,知道病灶並不代表就有解藥;就算有解藥,也不代表健保有給付,所以你可能吃不起。世界上有許多事是無解的,這個時候你只能眼睜睜地看著肥軟一暝大一吋地腫起來而束手無策。

【舊的生產力觀念】
造成肥軟的首要原因,就是舊的生產力觀念。評估工程師的生產力,最簡單的方式就是「你今天寫了幾行程式」(Source Lines of Code,SLOC)。如果我是寫程式的工程師,我的工作重點會是多寫出幾行程式碼,而不是想辦法做出精簡且高效率的程式。在軟體公司能用其他更有效的方法評估生產力之前,這樣的思維相當普遍。而在一家很大的軟體公司內,裡面這麼多軟體開發的人力,如果每個人都有這種重量不重質的觀念,寫出來的軟體很快就會體積暴增,大而無當。

更何況現在的軟體開發往往「Time To Market」是第一優先,其他(效率、體積、安全、穩定)都先被拋諸腦後(所以大家才普遍認為1.0版的軟體不能用)。開會時老闆只會問:哪些功能做出來了?不會問:現在體積多大了?因為體積不受重視,所以爆肥是普遍的現象。程式碼吃撐了,哪有不肥的道理?

【使用龐大的框架】
惡搞卡通南方四賤客(South Park)的Eric Cartman時常掛在嘴邊『我不胖,我只是骨架大』(I am not fat, I am big boned)。這句話用來形容許多肥軟,相當恰當。如果你的軟體使用龐大的框架(framework),而此框架並非標準地被預先建置在所有的平台上,那麼你的軟體就必須攜帶此框架,導致此框架的體積也就算到你的軟體上。有了龐大的骨架,就算沒長多少肉,依然是體積可觀的巨人一枚。

我們公司之前開發過一個工具軟體,因為C與Win32的工程師不容易招聘到,最後只好將就著用C#和.NET開發。因為不是所有的電腦上都有安裝.NET框架,所以我們必須把.NET框架包進我們的軟體中。我們將.NET框架中用不到的DLL移除,試圖讓軟體體積小一些,最後包出來的軟體還是超過10MB,其中我們自己的程式可能佔用不到十分之一的體積,其他都是被.NET框架佔用。我估計,同樣的程式用C和Win32改寫,只需要數百KB。

【為了彈性而疊床架屋】
關於疊床架屋,最明顯的例子是J2EE。為了要跨越軟硬體平台、應用伺服器、資料庫伺服器,達到美好的彈性,J2EE已經疊床架屋到令人匪夷所思的地步。一件小事情都可以搞到很浩大。如果你仔細讀過J2EE的手冊,你可能會和我有一樣的感想:『我只是想開發一個Web系統,有必要依循J2EE的方針嗎?』

J2EE可不是特例,這種疊床架屋的現象,在IT技術中到處可見。這麼做當然有優點,也有缺點,就看使用者對於優點的重視是否超過對於缺點的忍受。不過,這種為了彈性而導致的肥大技術,還真的是只有Fortune雜誌排名500大的公司才頂得住它的重量而不會被壓垮。

我們得好好思考:「疊床架屋」真的是賦予軟體「彈性」的唯一道路嗎?我們能在保有彈性的同時,摒除這些違章建築嗎?

【為了提高相容性】
有些套裝軟體由於使用族群太廣,所以必須考量各種人的各種需求,因此提高相容性,一直是這類軟體的重點之一。他們的作法例如:可以開啟二十年前的廢棄檔案格式,可以開啟競爭對手不斷推出的新格式,可以支援古代的各種電腦周邊設備、奇特的鍵盤配置,提供失能人士的無障礙操作介面(Accessibility)。

提高相容性來滿足大家的需求,似乎很可取,但是軟體複雜度和體積暴增也因此不可避免。相容性是一種令人又愛又恨的東西。關於這一點,還是要考慮到80/20法則。太離譜的相容性支援,可以做成插件(plug-in),不要直接整合進系統中,這樣可能會好一點。

【舊的設計不好,不能拿掉,只會加上新的】
很多時候,當我們發現我們開發出來的軟體設計上有問題時,程式碼已經盤根錯節,無法修改(從這個角度來看,「彈性」很重要),或者修改會造成既有使用者不相容的困擾。例如,許多程式語言原本不支援Unicode,為了要支援Unicode,又不想全面修改String型別(因為既有的開發者會反彈),於是會提供新的Unicode型別。

為了徹底解決這類問題,語言設計者往往會推出大升級版本的分支(主要版本號碼提升一個數字),例如D 2.0、Python 3.0、REBOL 3.0都是這樣的分支,新的分支和舊的分支並行前進,新版本分支大翻修,甚至從零開始,而舊版本分支繼續進行bug修正的維護升級。

【連鎖相依】
由於Open Source與免費程式庫盛行,現在許多軟體開發都會大量使用外部套件,以提升開發速度,避免重新發明輪子。但是這麼做的一個不好的副作用是連鎖相依:嫁進家門的不光是你老婆,還包括她的一群遠房親戚,食指浩繁,讓你吃不消。

例如:你只有使用套件A,但是套件A有使用到套件B和C,而套件B與C又用到其它套件。一連串下來,你需要的套件數量大增,你的軟體體積自然也大增。你要知道,這些套件都設計得相當泛用,畢竟不是專為你設計的,所以每個都不小,包含了一大堆你用不到的程式碼。

【物件導向】
有些國家的人民普遍肥胖,有些國家的人民則普遍偏瘦,這和他們的身處的飲食環境有關。在軟體開發界,只要採用OO飲食法,很少有瘦的。(但我還是有看過極少的特例)。OO程式執行時,記憶體耗費更是可觀。物件導向程式很難減肥成功,這似乎已經是基因的問題了。為何採用物件導向技術的軟體,有很高的比例都是肥軟?這個問題相當值得思考。

【XML】
除了思念之外,XML也是一種很玄的東西,因為它如影隨形,到哪裡都看得到。用它標示文字資料,甚至用它標示原本是binary的資料,甚至用它標示不是資料(例如程式)也開始流行起來,設定檔(configuration)更是幾乎全面XML化。XML確實是有一些優點沒錯,但是它的缺點也不少,其中最嚴重的一個或許就是:它讓資料量不必要地暴增。

【攜帶各種編碼表與字型】
有的程式為了避免任何閃失,會自行攜帶各種編碼轉換表和一些字型,Java虛擬機器就是這樣的例子。編碼表和字型的檔案都是很大的。

【Software on Diet】
多年前的一部得獎紀錄片「Super Size Me」,裡面實際記錄一個人天天吃速食,一個月後整個人爆肥,且健康檢查的各種指標都出問題。這部片讓許多肥胖人士看了之後,心生警惕。

身處軟體界的我們,也應該注意Super Size Me的問題。軟體要如何減肥:多吃粗糙的食物(例如Win32),少用精緻的食物(例如.NET);多攝取DSL,少攝取OO;時時刻刻注意局部發胖;少用XML與程式碼產生器;相容性的部分用轉檔解決,轉檔的部分做成軟體服務,或下載套件;多攝取「綠色」,少攝取「肥肉」,以鼓勵廠商生產綠色軟體(你可以上網查一下綠色軟體的定義)。

看了上面這些建議,你可能覺得這也太不容易做到,甚至不切實際。嘿!哪個營養師開出來的減肥計畫會讓你說「這很簡單,我做得到」?本來就是增胖容易,減肥難呀!當然,很多時候,開發時程與成本…等考量比軟體體積更重要,所以,你可能會兩手一攤,說:「胖!就給它胖吧!」其實這也是無可奈何的事呀!

但「胖」倒也不是一無是處,胖似乎已經成了軟體界普遍的審美觀,就像唐朝的女人一樣,胖才是美。尤其是許多顧客有「不重則不威」的觀念,買了我們的軟體之後,拿到好幾片滿滿的光碟,安裝需要耗費一整個下午,顧客會覺得這個軟體很有價值。如果只給他一個不到1 MB的檔案,顧客還會抗議說,這小玩意兒不值這價錢。賣軟體終究還是逃脫不了秤斤論兩的命運呀!