2012年6月26日星期二

程式師的修練場 - 建立自己的Junkcode及測試程式庫

大概很少人聽過junkcode這個字,如果在Google上尋找,首先會連到www.samba.org/junkcode,那是Andrew Tridgell(Samba的原作者)的網站,存放了他的垃圾代碼。

之所以被稱為Junk,那是因為他並未有計劃把這些代碼變成任何項目、也不會提供文件、更加不會保證有任何的改良。

Andrew Tridgell在大概八九年前左右曾來港演說,時歷久遠,當時的內容大多忘記,不過有二點是現在仍記得的,其中一項就是他提到的Junkcode程式庫。(註一)

受到他的影響,之後我也開始了建立自己Junkcode程式庫的習慣,只是沒有像他般公開。

我的Junkcode主要有幾種內容 :
  1. 不同語言的Hello World及語法的實驗。
  2. 不同Library/Framework的試驗
  3. Algorithm驗証
  4. 試作性質的專案
只有空閒時會撰寫, 不一定有明確的計劃,絕不保證日後有用,所以這些都是Junkcode。

因為沒責任,故此寫起上來是挺輕鬆的,除非目的是研究怎樣改良代碼,否則什麼代碼質素、易讀性的考慮都被拋諸腦後。

不過即使是垃圾,難保日後會有用武之地,所以我都有好好地做version control作為保存的手段,只是commit log就有點... 嘿嘿。

最初用CVS管理、後來git面世了,跟著就轉了去git,最後又變成了Bazaar。

像是FrontviewDQuestPenPenDualless這類項目的雛型都是先在名為junkcode的source tree中開始,當漸漸成型後才獨立分離出來,故此你若查看PenPen、Dualless的提交歷史時會發現第一個版本已經包含了許多的檔案,那都是先寫在junkcode裏的。

不過因為太隨意建立專案的關係,source tree變得有點混亂,所以我開始了使用Test Driven的方式管理。

Test Driven式學習

Test Driven Development是近年一個熱門題目,當初學習時的實驗代碼全都是在junkcode裏進行,掌握這方法後不單影響了我的專案管理風格,連Junkcode的寫法也有所變化。

例如説要去學習一門新的語言時,我首先寫的不是Hello World,而是先找一個評價好的Unit Test Framework,然後用這語言寫的第一個程式不會再説Hello,祇會説Pass / fail。

假設有以下的情況,我現在要去學Javascript,找來了一本叫做《Javascript設計模式》的書本,跟著有朋友推介使用QUnit做unit test,花了點時間總算把環境建立起來。

在書本中見到以下的代碼:


var a = [3];
console.log(a.length); // 1
consloe.log(a[0]); //3
 
var a = new Array(3);
console.log(a.length); // 3
consloe.log(typeof a[0]); //undefined


照著書本把代碼打一遍是一種學習的過程,只要查看注解的内容就知道是否正確,若印出預期結果可以加深記憶;失敗則能鍛練除錯的技巧。

而我則喜歡更進一步,把教學用代碼變成測試條件,例如以上代碼會變成:


test("array" , function() {
    var a = [3];
    ok(a.length == 1);
    ok(a[0] == 3);
 
    var a = new Array(3);
    ok(a.length == 3);
    ok(typeof a[0] == undefined);
});


跟著那去browser跑... 噢!第4個測試不能通過!?


ok(typeof a[0] == undefined);


這句不對嗎?

打錯了,原來是這様才對


ok(typeof a[0] == "undefined");


又或者這様也對


ok(a[0] == undefined);


在這轉换過程中不小心做出了超越作者預期的行為而犯錯,測試程式亮起了紅燈,跟著為了回復為綠燈去工作,這就是學習(而且帶了有一點兒TDD味道)

這種學習方法不限於學習語言本身,也可以用來學用不同的Library/framework、設計模式,可以簡單地驗查自己的想法是否正確,順道可以協助掌握寫測試程式的方法,對日後其他的專案開發很有幫助。

總結 

無讑是編程的初心者還是經験豐富的老手,建立自己的junkcode程式庫都有一定的好處,這些積累的作品不一定可以發表,可是……
  1. 或許日後會有機會用到,成為其他專案的一部份
  2. 或許可以在Junkcode中找回以解決過的問題方法,但現在忘了。
  3. 回顧以往寫過的代碼,也是一種樂趣
而且編寫junkcode的負擔很少,因為你不需要向任何人負責。

如果加入VCS及TDD,則還有以下好處:
  1. 練習使用版本控制系統
  2. 掌握各種測試技巧、有助於引入TDD
  3. 更快掌握一門語言、Library/Framework。
    1. 通過Test Driven式的學習,習慣思考不同行為的正確結果
  4. 重新掌握一門語言、Library
    1. 太久沒有使用相關的技術,可以查看過去寫的測試代碼回想起來。  
    2. 如果framework更新了,跑一次測試程式就可以知道有沒有跟過去的認知衝突的地方。

註一: 另一項記憶悠新的内容是關於在開發Samba時,曾經比較過Multi-process、Multi-threading及I/O multiplexing三種多工作業的效能,然後發現I/O multiplexing的效能是最好的,現在非常之熱門的Node.js其實也是應用了相同的原理。

2 則留言:

circle 說...


我也有一堆閒時無聊寫的小 utility/programs
不過大多都是 perl 類的 scripts
都是有些突然的task要做所以寫出來的 script
一般都不過300行, 而且很少documentations, 只有少量comments
不過很多時都沒有重用了
現在主要用途反而是用來參考以前想到的寫法甚至係特定的syntax

大概類似所謂junkcode程式庫吧~ =)

Ben Lau 說...

對啊!

就是這個概念,如果再放回DVCS就可以永久保存了 :)

Creative Commons License
本網誌Ben Lau製作,以共享創意署名-非商業性-相同方式共享 3.0 香港 授權條款釋出。