`
lua
  • 浏览: 74563 次
  • 性别: Icon_minigender_1
  • 来自: 大连
文章分类
社区版块
存档分类
最新评论

開放原始碼的回收與再利用

阅读更多

開放原始碼的回收與再利用

前文提到對Google 時代的程式員來說,能夠善用開放原始碼的資源,對程式撰寫的工作能夠在速度上起很大的作用。我覺得不妨就把這項活動稱為「開放原始碼的回收與再利用」吧。在這之前,得先界定一下reuse (重複使用)與recycle (回收)的差異。開放原始碼的專案很多,尤其對Java 社群的人來說,對於Jakarta Apache 上的專案相信都不陌生。這些專案在介面甚至架構的設計多半都很完善,不僅容易使用,也容易擴充。在使用這類型的專案時,往往不需要碰觸到原始碼就可以達成目的。但我們在網路上透過Google 搜尋散落於世界各地的原始碼時,所找到的程式,多半未盡人意,需要施以回收再加工的作業,才能夠進一步加以利用。

 

再 生利用和重新建立,需要的是不同的技能。就好比對工匠而言,重頭開始製作一張木頭椅子,與回收一張既有的木頭茶几,然後將這張茶几重新修整,並且添加新的 材料,而成為一張具有新面貌的椅子,需要的技巧雖有重覆,但也有諸多不同之處。如何盡可能的利用既有的資源,施以最小幅度的心力,達成相同的目的,就成了 這門技巧的藝術。

 

我前些日子需要一段程式,能夠將MP3 的音樂檔案放到iPod 上,並進一步能夠透過iPod 播放這些音樂檔案。在這個過程中,自覺使用到一些回收利用的技巧,所以試著整理如下。

 

在網路上搜尋可用的原始碼,並選擇最適合的

 

透過Google 輸入正確的關鍵字,通常可以很容易找到相關的原始碼。但是如何從眾多的符合結果中,挑選最適合的一個做為自己著手的標的呢?我覺得有下列的標準:

 

l          選擇執行平台相符者:最好該原始碼能於自己的目標平台上編譯並執行,最常遇到的情況是,能夠找到LinuxFreeBSD 上的原始碼,但目標平台卻是Win32

 

l          選擇程式語言相符者:最好該原始碼所用的程式語言,與自己要使用的程式語言是一致的。

 

l          選擇版權宣告合適者:不同的開放原始碼專案,具有不同的版權宣告。要應用在你自己的專案中,就必須留意其版權是否能為你所接受。

 

l          選 擇範圍接近者:不同的開放原始碼專案其規模不盡相同,也許不同的專案其內容都有可堪利用的部份,但倘若其原始規模過大,在回收時可能需要花費更多的心力以 了解其原始碼內容,也可能需要花費更多的心力去做拆解與整理。如果所選擇的專案其範圍和自己要應用的範圍相距不遠時,常常可以省去不少力氣。

 

l          選擇使用者眾者:倘若該專案的使用者數量夠多的話,通常代表它已經經過相當多人的測試,品質上通常也會比較好。

 

l          選擇相依性低的:有些專案會依賴其他專案的產出(例如程式庫),倘若使用此類的專案,那麼你自己專案對其他專案的相依性就會提高。這並不是一件好事,因為這代表你得含入許多其實你並不需要的東西,而在分發(distribute )你的軟體時,其體積也會龐大許多。

 

依據上述的標準,通常很難找到十全十美、盡如己意的專案。在此時就必須進行取捨,畢竟魚與熊掌不可得兼,要吃什麼就得自己決定。決定了之後,我們就可以逕行下載這可稱為「基礎專案」的原始碼與說明文件-如果有的話。

 

了解程式架構,拆解出自己所需的部份

 

儘 管在選擇做為基礎的專案時,已經盡量的選擇範圍接近自己所需的專案。但無論如何,基礎專案仍然有可能多出不少內容。此時你需要的就是閱讀追蹤其原始碼,試 著加以了解。如何進行追蹤以在最短的時間內了解一個專案的架構及內容,是另一個技巧,與本文無關,暫且不表。了解程式架構後,就可以進一步判斷那些部份是 自己所需的。通常可以用原始碼檔案(.c.h.cpp.java.cs )做單位,來第一步過濾出自己希望保留的部份。在這邊先不論所保留下來的原始碼是否能夠編譯,總之是要建立一個主體出來。

 

訂定不同的階段,從最小的里程碑開始

 

接著要開始訂定不同的階段。由於我們手上的程式碼極有可能連編譯都無法成功,更別論執行正確了。所以,應該要訂定幾個不同階段的目標,並且從最小的里程碑開始出發。以synciPod 的程式為例,我訂下了三個階段的目標:(1 )正確的剖析其索引資料檔(2 )正確的寫入其索引資料庫(3 )正確的將音樂檔案寫至iPod 儲存設備中。而最重要的關鍵就是讓第一個里程碑能夠達到。因為達到第一個里程碑具有十分重要的象徵性意義,它代表著你能夠正確的編譯而且執行了,只要能夠達到第一個里程碑,之後的問題幾乎都能輕易迎刃而解。

 

做細部拆解,先求能編譯,再求正確執行

 

在開放原始碼的回收與再利用活動中,最難的是就是讓拆解下來的原始碼成功的編譯。因為拆解出來的原始碼常常會缺東缺西的,有時需要其他header 檔 中的定義或巨集,有時還會需要其他未被拆解出來之原始碼中的部份函式,為了成功的編譯,你需要再回到基礎專案中,把所需的部份拆解出來。這個時候所做的拆 解動作,就是更細部的拆解,因為在這個時候的拆解並不會直接把整個原始碼檔案移至回收專案中,而是在回收專案中建立新的原始碼檔案,僅移動在基礎專案中所 需的部份,例如缺少的定義、巨集、或是函式。所以在這個階段,會反覆的看到許許多多的編譯錯誤,而你的處理方式,便是逐一解決各個編譯上的錯誤。總是重新 撰寫程式的程式員其三大美德之一是沒有耐心,但對從事環保回收工作的程式員來說,需要的反而是耐心耐心加耐心。

 

暫時忽略非第一個里程碑的內容

 

有許多編譯錯誤是第一個里程碑後才會需要的,此時適時的將它們註解掉,以求通過編譯檢查是一個很好的手段。而這剩下的部份,在通過第一個里程碑後,解決其編譯錯誤的方案,也會在處理第一個里程碑的過程中產生。此時再取消對它們的註解,就可以套用這些解決方案。

 

適度的斬斷關聯性,尋找適當的替代品

 

有時編譯的錯誤是來自於缺少某個函式或類別,而如果要加入這個函式,必須引入一大堆東西時,就必須考慮適度的斬斷和該函式的關聯性。例如我在做iPodsync 程式時,有一個struct 中的成員是一個GList 的指標。而GList 這個型別定義於Glib 中,當我進一步下載GLib 的原始碼,並且將入GList.hGList.c 放入回收專案中時,發現這兩個檔案尚且依賴GLib 中其他組成。在這種情況下,可以判斷其相依性實在太高,所以決定另找替代品。

 

尋找替代品可以採取兩個途徑。一個是自己撰寫,而另一個就是再找現成的開放原始碼。只要保持介面與作用一致,運用起來就不致於有所困難。以我的例子,基礎專案中還有另一個類別,如GList 一樣,提供linked list 的功能,很輕易的就把GList 給替換掉。至於為什麼我的基礎專案中會有兩個提供linked list 功能的類別呢?這就是許多開放原始碼專案的特性-混亂。我選定的基礎專案自己也是hack 自其他的原始碼專案而來的,它甚至還充斥著多種不同的命名慣例。

 

透過尋找適當的替代品並加以替換後,可望有效的降低許多的編譯錯誤。

 

整理介面,去除不必要的元素

 

基 礎專案中的函式或類別,也許因為和專案中其他函式或類別保有相依性,或者因為它本身的目標就和你的目標不盡相同,所以這些函式或類別的介面長相就會和你所 需的不同。由於我們只從基礎專案中取出我們所需的部份,所以通常介面中的元素會較我們所需的為多。也因為我們少拿了不少東西,所以有許多編譯錯誤會來自於 這個部份。你需要做的就是去除一些不必要的元素,並且重新整理這些介面的長相。

 

經過上述的努力,將所有編譯錯誤都消除後,就可以得到第一個可執行的版本。那麼,就執行它吧。很少會運氣好到第一次執行就正確的,針對不正確的結果,請採取除錯相關措施,這應當是程式員共通的基本功夫了。

 

做好心理建設,面對混亂

 

有很多程式員都有一個習慣,就是拿到別人的程式後,要把所有的排版、命名慣例都調整成自己慣用的才甘心。在回收時,如果你堅持這麼做,可能會累死。請先做好心理建設,讓自己能夠面對自己覺得混亂的程式碼,視眼前之混亂如無物。之後有空閒時間,再套用refactoring 的技巧,逐步的改善回收程式的結構。

 

跨出成功的第一步


只要能成功的達成第一個里程碑,依照著相同的方法,就可以逐步的達成其餘的里程碑。而且下一個應當是愈來愈簡單達成。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics