評估開放原始碼程式庫的要素之一,是專案的活躍度,而活躍度的參考指標之一在於,作者是否經常對程式庫進行維護,更具體地說,程式庫提交(commit)的頻率。就我而言,找到一個程式庫時,總是會看一下它最近一次受到提交是什麼時候。

如果開發者手邊有個開放原始碼專案,想讓使用者知道他關心這個專案,該怎麼維持這種活躍度呢?由於手邊也有著dotSCAD/cqMore等開放原始碼專案,我經常在思考這個問題!

臭蟲修正?這不是想找就找得到!持續加點新特性?為了加新特性而加,只會令程式庫失焦,硬寫出來的功能也不見得好用,可能只是增加日後維護的麻煩!

童子軍規則/無情重構

維護程式庫終究要有目標,然而,其實不需要什麼太遠大的目標,我們只要遵循《Clean Code》第一章所提到的童子軍規則(The Boy Scout Rule):「離開營地前,讓營地比使用前更加乾淨。(Always leave the campground cleaner than you found it.)」每次打開專案,我們就試著找個地方整理一下,讓程式碼的品質好上那麼一點點,就可以了。

Bob大叔認為,童子軍規則是個專業主義的象徵,在《The Clean Coder》第一章再度提到這個規則,並且進一步地闡釋「想要證明軟體易於修改,唯一的辦法就是『做些實際的修改』」,這種策略有時被稱為Merciless refactoring。

Merciless有殘酷無情之意,Merciless refactoring也就常翻譯為「無情重構」,這聽來有點嚇人,不過,這裡的merciless比較像是無心、無意,不用有太多情懷,做這類重構不需要設想太多的意思,單純就是離開前讓原始碼乾淨一些。

這是因為重構常給予人需要特定目標、手法,如果沒有足夠的經驗,沒能嗅出程式碼的餿味、沒對專案架構有一定認識,就別輕易動手的感覺;然而所謂的無情重構,希望的是沒經驗的開發者,也能輕易實現,持續、點滴地改進程式碼的品質,從而讓後續的程式碼修改變得簡單。

面對原始碼的童子軍

身為開發者,或多或少可能都學習過一些關於重構訊號、目標與手法的知識,應該知道一些整潔程式碼該有的樣子,但是,我們實行童子軍原則時,不見得每次都是以消除程式碼餿味、增加程式碼整潔為目標。

別的不說,就算是重新命名變數或函式,來增加程式碼的可讀性,其實,也是滿難的一件事不是嗎?畢竟它是程式設計師九大難題之首呢!

開發者只要找一段感興趣的原始碼,看懂它,然後有個修改的簡單理由,就可以了。最好是腦袋中一閃而過的想法,就算只是簡單地調整排版,也無所謂,就算排版只是做一點縮排,或按個換行,也沒問題。只要那些修改動作,是開發者看懂程式碼之後的想法、第一時間想做出的調整,就可以了,而在我們提交程式碼的訊息當中,寫明僅是做個排版,也就可以了。

可別小看縮排!這其實意謂著開發者理解到程式碼中,有個不同或相同的層次。

也別小看換行!這可能意謂著理解到這邊是一個子任務的結束、另一個子任務的開始。

就我個人的經驗而言,往往是在累積了一些程式碼排版的提交之後,而逐漸發現到有些可以抽取或合併的程式碼,或者進行資料結構封裝、架構調整之類重構的可能性。

簡而言之,「童子軍規則」的重點在於,為了在離開前,讓原始碼比使用前更加乾淨,開發者必須先讀通程式碼,就算只是一小段,也有了重新檢視、修改原始碼的機會。

修改的動機也可以是除舊佈新,像是知道了專案環境可以使用某個新語法、新特性、原生函式,可以在閱讀原始碼時,順手更新,移除一些過時的實作或被廢棄的特性等。

當然,如果對重構的訊號、整潔程式碼的樣貌擁有相當的經驗與心得,儘管去運用相關手法,在離開前清理原始碼,也是沒問題的!

面對專案的童子軍

有時讀完一些原始碼後,開發者可能還是沒有想法,這時該怎麼辦?雖然Bob大叔提及的童子軍原則,基本上,是針對程式碼的整潔,不過,施行對象其實可以不限於原始碼本身,也可以是對整個專案品質有助益的整理,例如文件、範例程式碼或測試等。

這令我想到許多開發者不愛寫文件,確實地,寫文件有時枯燥乏味,特別是撰寫API文件,而避免乏味的方式之一是,為API文件加入一些範例程式碼,這是強制從開發者的角度脫離,改從使用者的角度來看待API的方式,以便從實際文件撰寫、範例設計中,察覺API的設計是否合理、易於使用、有無彈性等,如果在設計範例程式碼時覺得麻煩,改進API設計就會是下次促進專案品質的目標之一。

另一方面,撰寫文件、設計範例程式碼,其實就是實行測試的另一種形式,因為在撰寫文件或範例的過程中,我們往往可以發現臭蟲或者效能等問題,這實就有了檢視、修改程式碼的機會。

因為有了文件、範例程式碼,下次在實現童子軍原則時,若真的沒想法,那就補點測試吧!我們可以將先前撰寫的文件、範例作為測試案例的來源,令其成為自動化測試的一部份。

有了文件、範例程式碼與更多的測試作為基礎,開發者面對專案本身的原始碼時,就更有信心去實現童子軍原則,而不用怕修改之後,破壞了什麼!

童子軍原則也可以套用在文件與範例,畢竟它們也是需要維護的對象,因為過時的文件與範例比沒有這些資訊還糟糕,所以,我們如果面對專案本身的原始碼真的沒什麼想法,那就去整理文件與範例,修正一些過時的東西、改幾個字詞、增減一些描述或純潤飾等都好。別忘了!童子軍原則也常被稱為Merciless refactoring,實行時不要設想太多。

童子軍規則的效益

Bob大叔說大多數人對軟體的理解是「修改是危險的」,其實正好相反,為了證明軟體易於修改,就要避免讓程式碼保持不變,只有修改才能發覺不易修改的設計,從而改進設計,讓修改變得容易,這是時時實行童子軍規則的效益之一。

開發者越是不改程式碼,就越來越不敢改,然後新功能只基於這些不想改的程式碼,持續地堆疊上去,有一天就會像Bob大叔說的:「不得不重構時,就會發現程式碼已經僵化了」。

就我的經驗而言,另一個效益是,實現童子軍規則,其實是在時刻閱讀、修改原始碼過程中,維持對專案的熟悉度,而且,效益會在持續累積熟悉度後逐漸呈現並擴大,當專案的品質與自身的熟悉度都到達一定程度,有些過去難以解決的難題,解決的方案可能會突然變得清晰,這時對專案往往會產生全新的目標與想法。

總體而言,我們在維護開放原始碼上若能實行童子軍規則,就可以讓專案維持著一定的提交頻率,而且並非灌水。這表示除了臭蟲修正、新增特性等之外,開發者也關心專案的其他品質,這些都會反映在提交記錄上,顯示出童子軍每次離開營地前的整理提交,都是具有意義的!

專欄作者


熱門新聞

Advertisement