復用可以說是任何一個軟件企業都不能漠視的課題,因為復用可能對軟件的開發效能產生絕大影響,而開發效能直接影響利潤,甚至生存。
但復用本身將增加當前項目的成本,是一種以當前投入來換取遠期收益的行為。與此同時遠非所有代碼都可以復用,復用本身也有自己內在的一些規律,讓我們來試做一些分析。
從結論上來說,只有滿足下面兩條原則的程序,才可能真正的被復用,否則的話只能采用代碼級別的復用。
第一條原則是,程序本身的職能非常獨立與業務層面基本無關聯,是功能型的模塊(包)。
代碼中的邏輯表述的是一種關聯性,當這種關聯只在確定的方面存在的時候,通常我們可以切割出比較獨立的模塊,而這種模塊可以成為復用的基礎之一。這也就是常說的【閉包】。
這種復用有許多表現形式,但其本質相同。
比如JPEG的庫,XML的庫,比如我們常提到的組件或控件。
在這類復用中扮演關鍵角色的是一組接口,以及這組接口的基本使用規則。
REP(重用發布等價原則),CRP(共同重用原則)中提到的重用都是這類重用。
第二條原則是,程序本身所描述的過程足夠抽象,同具體實現細節可以切的很開。
概念在衍化的過程中其內含的細節會逐漸豐富,但又會共享某些共同的基本特征。很多時候邏輯要處理的是這種根本特征,而非細節。在這個時候,就需要抽象。
好比人可以分為男人和女人,也可以分為老人,青年人和小孩。但因為同屬於人這一范疇,所以不管如何分類,必有共通之處。也正因此,某些針對【人】的規則或者價值標准是可以通用於所有人的,即是可以復用的。比如說法律。大多時候,我們不需要指定分別針對於男人,女人的法律
這種類型的復用不是很好理解,我們用迭代器的例子來進行進一步的說明。
當我們想遍歷一個容器的時候,從【頭到尾的循環】和【逐個遍歷】是屬於任何容器的,而同具體的容器無關。但如何從第一個元素,遍歷到第二個元素則和容器的具體實現有關。把這種和具體實現細節無關的邏輯提取出來的過程,也即抽象的過程。只有能做到這種程度抽象,非獨立的功能性的代碼才可能真正的做到被重用。
《設計模式》這本書有個副標題,叫《可復用面向對象軟件的基礎》。基礎這個詞的意指與上述說明相同。
由第二條原則而產生的復用的形式可以是,設計模式與框架。歷史上的MFC的文檔視圖結構就是一個典型代表。
一個比較典型的是近來很受關注的Map-Reduce的函數式編程方法,據說這種方法在Google被用來支持並行計算。--參見《軟件隨想錄》
假設說某一功能的主要部分已經實現,比如排序。這時候已經實現的部分是既定算法,可能是選擇排序,也可能是插入排序。但對於排序而言,對兩個數值進行比較的部分則依賴於被比較的對象,需要被靈活指定。這也就意味着重用排序的實現,等於實現兩段代碼的對接,實現一部分代碼,但另一部分則由用的人在使用的時候指定。
這種方法可以更好的支持並行計算的原因在於,他可以把實現中的可優化部分分割開來。對於查詢而言,如何遍歷所有數據是可以並行優化的。
如果上述兩條原則都無法滿足,那么為了達到提升效能的目的,就需要做以實現為基礎的代碼級別的復用,即完全不做抽象,直接復用代碼片段---也許這反倒是應用的最為廣泛的復用方法。
很多人恐怕已經習慣了解決某個具體問題前,先到codeproject.com或者codeguru.com上確認一下有沒有參考代碼。如果不論這種方法的諸多缺點,比如:版權問題,引起代碼風格混亂等等,這種方法的現實意義仍是比較巨大。其正面意義可以體現為下面幾個方面:
- 可執行的代碼片段可以清楚的告訴我們類庫API等等的具體用法,進而縮短我們掌握領域知識的時間。在具體項目中使用某種語言,完全從零開始來完成某項工作的機會非常稀少,我們更多的時候要依賴於某些通用的領域知識。而通過幫助文檔來學習類庫等的使用方法效率相對低下,而這種可執行的片段代碼則精准,且具體的描述了類庫等的某一使用方法,使程序員可以更快上手。
- 可執行的代碼片段可以是高質量的。如果我們承認代碼的質量是要持續提高,那么這類代碼片段,無疑的可以擁有比剛剛寫成的代碼更高的質量。因此這類代碼對生產率的貢獻還不僅只與提高編碼速度。
如果真的想在組織中使用這種復用方法的話,一個關鍵點是要控制可執行代碼片段的規模。
--------------------------------------------------------------
理想流 + 軟件 = 《完美軟件開發:方法與邏輯》
理想流 + 人生 = ??
理想流 + 管理 = ??
理想流 = 以概念和邏輯推演本質,追求真理。