星期一, 4月 26, 2004

Immutable Object and Test-Driven Development

今天又有新發現!原本是想寫一個 number range 的 parser, 例如 使用者輸入 "128~130,140" 時,parser 會回傳 128,129,130,140 四個數字。直覺的寫法就是寫個 parser 的工具:

NumberRangeParser parser = new NumberRangeParser() ;
List results = parser.parse("128~130,140");

後來想說直接將 "128~130,140" 直接轉成 SQL: (foo between 128 and 130) or ( foo = 140)
啊咧?怎麼好像又要多做一個工,而且還要多寫一個 converter。那API 不就變的很醜,而且很囉嗦..... 不過似乎沒什麼選擇,還是寫吧。嘿!來試試 Test-Driven Development,先寫個 test 再來寫 code。

......怪怪,這樣不好,嗯.... 這樣改比較好.... 喔,這邊可以寫成這樣....

經過一連串的 design refactoring ( code 還沒寫 ) ,最後 API 有了驚人的轉變:

NumberRange numberRange = new NumberRange("128~130,140") ;
List numbers = numberRange.toNumberList();
String SQL = numberRange.toSQL(String foo);


Whoa ! A range of numbers become an immutable Object !

在原本的設計裡 parser 只是一個 tools 而已,這就像是寫 procedure code 的 subroutine 一樣,原本的寫法就算是全寫成 static 照樣可以運作。新的寫法則完全是物件的思維,那一串的 number range 整個變成物件,然後可以轉換成各種格式。而且以後在每個 class 之間使用時,都是直接傳 NumberRange ,而不是用 number 的 List 來傳遞,不僅僅防呆,而且界面的彈性更好!最後這個 class 是設計成 immutable 的,換句話說,這個 class test 完後,就永遠不會再錯啦!WOW!而且這個 class 感覺好像 String class 喔,心中突然覺得很爽,自己也能寫出類似大師的程式!

現在還不清楚這是不是 test-first 帶來的好處。嘿嘿!明天再來試試!