上個月寫了一篇關於外掛程式系統的文章,也是我現在一直在做的一個項目。在實現這個基於外掛程式機制的系統過程中有不少自認為有意思的地方。這裡寫出來與大家共用。
在外掛程式系統中,每一個外掛程式都有自己的一些配置資訊,比如說表徵圖資訊、介面顯示資訊等。如果以前做了一個外掛程式,發現另外一個外掛程式和它的功能差不多的時候該怎麼辦呢?可以用設定檔將不同的地方描述出來,也可以在以前的基礎上做一個衍生類別。到底是用配置還是用派生,這個問題就有趣了。
都是變化惹得禍
中國特色的軟體產品就是地區版本多,同樣一件事情每個地方規則都不一樣。比如說做了一個功能,在北京用沒有問題,拿到上海去就不符合要求了。地區特性要求我們的軟體必須要響應變化。
出現變化後的第一個反應就是OO了。有著各式各樣的設計模式來教我們怎樣利用OO的特性來應對變化。
比如說現在需要一個計算個人所得稅的模組。
計算的思路都是一樣的,但由於地區經濟的差異,所以在有些資料上各個地方會略有不同。
按照OO的思想來考慮,我們可以做一個計算的基類,利用模板方法將各地不同的地方做成虛函數。基類中處理具體計算的演算法,衍生類別中處理地區差異,比如說各地的稅收合征額不同。在到具體地區實施時只需要選擇不同的衍生類別就可以了。並且也非常方便擴充。如下面的TaxCalculator1。
同時也有另外一種思路,在TaxCalculator2中沒有什麼虛函數,也不存在衍生類別,不過它啟動並執行時候需要一個設定檔,在設定檔中描述地區差異。
當然,這裡說的是一種非常簡單的情況,在實際的應用中比這個要複雜的多。
就上面分析的來看,似乎用派生和配置兩種方案都可以。如果是OO思想的“崇拜者”很可能覺得第一種方法更好,因為第二種方法不是物件導向的思路。
考慮成本
在項目中遇到這個問題時,是和外掛程式機制聯絡起來的。也就是說外掛程式之間從邏輯上講是“派生”的關係(一個外掛程式為一個DLL檔案)。如果按照類派生的方式來處理,則需要將不同的衍生類別分別編譯成不同的DLL發布出去;如果用設定檔則只需要發布一個DLL檔案另外附加上不同的設定檔。
從外掛程式發布的角度考慮,用設定檔的代價要更小。所以在實際的項目中,採用第二種方式居多。並且在非外掛程式系統中用派生方式實現的模組也盡量考慮用設定檔的方案。
其實在這裡我考慮的最主要的因素是“成本”,分為下面兩個部分。
維護成本
用派生的方式實現,在維護期間需要維護的是代碼;用設定檔的方式實現,在維護期間代碼不需要維護,只需要改變更配置置就可以滿足要求。我們認為維護代碼的成本比維護配置的成本要高。
發布成本
用派生實現,需要發布給使用者多個DLL檔案;用設定檔實現,需要發布給使用者一個DLL檔案,多個設定檔。我們認為發布DLL的成本比發行設定檔的成本要高。
結合上面的成本因素來考慮,用設定檔的成本要低,所以選擇這種方式。
產品是二進位檔案
我們的產品是什嗎?以前很直觀的認為程式員的產品就是代碼。
代碼和設計文檔、計劃文檔一樣都不是最終產品,它們都屬於文檔的範疇。最終產生產品的不是我們程式員,而是編譯器。代碼是一種文檔,編譯後產生的二進位檔案才是產品。
在項目中,我們會考慮從設計文檔到代碼需要的成本,但極少考慮從代碼到二進位需要的成本。原因很簡單,因為從代碼到二進位的過程太廉價了。通常我們不需要考慮編譯過程的成本因素。
由此來看,上面提到的“發布成本”是可以忽略不計的。
動態語言的優勢
關於維護成本這一點,就是仁者見仁,智者見智了。
有的人就喜歡讀代碼:) 所以很難說維護代碼和維護設定檔那一個成本高了。不過有一點沒有爭議,那就是到了使用者那邊,二進位檔案可是沒有辦法改的了。
有些喜歡刨根究底的人就會進一步鑽牛角尖,就像我一樣。
如果用動態語言又會是什麼樣的情況呢?
因為動態語言不需要編譯成二進位檔案,所以它就是一種可以啟動並執行文檔了。可以將我們系統中的設定檔當作動態語言的一種,不過它只能決定簡單的行為。因為設定檔畢竟不支援“封裝”、“繼承”和“多態”。用真的動態語言的話,既可以得到設定檔靈活的優勢,又可以得到程式設計語言強大的功能。
從這點來看,動態語言在這個場合還是非常有用的。