作者提到Strong Typing、Dynamic Typing的比較,背景知識可以參閱這裡。
Static Typing的優點是給compiler許多資訊,可在編譯期抓出錯誤,比執行時發現來得省時,也方便IDE做Code Completion(ex:列出class下的所有method)和Refactoring。缺點是programmer要打一堆冗長的資訊給compiler,這正是Java的情況。Static/Dynamic Typing都可以具有Strong Typing,像本書作者提倡的Ruby,作者認為它是Dynamic Typing and Strong Typing。Dynamic Typing適合快速開發,讓programmer更能專注在抽象思考,把想法轉為程式碼。比方取出陣列裡的每一元素做些事,Java裡常見的笨重程式如下:
ArrayList list = ...; ... for (i=0; i<list.size(); i++0) { MyNumber n = (MyNumber)list.get(i); int x += n.number; ... }
Java 1.5引入了泛型(generic type),可以省掉中間轉型(cast)那行,但使得宣告可讀性降低,並且不能存兩種以上的型別,比方同時存MyNumber和HisNumber。更大的問題是泛型是語言層級的實踐,不是JVM層級的實踐,破壞許多Java固有的優點。
前面提及Static Typing的優點,是否能在Dynamic Typing裡做補救呢?Code Completion和Refactoring目前仍有難度,但編譯期抓出錯誤的影響較小,作者認為Unit Test才是最重要的,目前Test Driven Development的概念已漸漸普及,有良好的Unit Test,測試成本很低,編譯期抓不出錯誤也無妨。
這裡引用修改書上的例子,以寫費氏數列為例,進一步指出Java笨重之處。
Java Version:
class Fib { public static void main(String args[]) { int x1 = 0; int x2 = 1; int total = 1; for (int i=0; i<10; i++) { System.out.println(total); total = x1 + x2; x1 = x2; x2 = total; } } }
Ruby Version:
x1 = 0 x2 = 1 10.times do puts x2 x1, x2 = x2, x1+x2 end
for loop的index variable有時是不必要的,foreach是不錯的替代方案,但有時不夠直接,不恰當的for loop寫起來有點冗,會降底可讀性( ex:for loop的 i 到底用處為何?)。
簡單的例子容易懂,但突顯的現象可能不夠強,冗長的程式碼降低可讀性和撰寫速度,程式碼的字數不是絕對的指標,但不可忽視它和思維之間的關聯,就像數學總是如此精簡。
Java為了安全性、擴充性、可讀性做了許多規範,像是static typing和exception,浪費太多時間在刀口之外,有時沒必要寫exception,乾脆草草了事:
try { ... } catch (Exception e) { e.printStackTrace(); }
相較於C++,Java做得不錯,但要小心這也許是錯誤前提下的最佳解法,是該換個起跑點了。
延伸閱讀:Omega
從大中那看來的,類似Haskell的language,大中寫了篇介紹Omega的文章:”Switch between static and dynamic type checking”,看不懂但看起來很神。
沒有留言:
張貼留言