關於Java語言的興起,是因為Internet時代的正式開啟。原先Java語言的設計,是為了開發嵌入式系統而發明的。

不過,當WWW開始普及時,Sun以Java語言為基礎,推出了Java Applet,允許網頁設計者可以在網頁上執行程式,甚至是提供更豐富的動畫效果或是和使用者做更進階的互動。這使得許多開發者開始留意Java,甚至加入使用Java的行列。

當然,Java是個通用型的語言,其用途自不局限在小小的Applet之上,之後Sun讓Java在伺服器端大放異彩,這使得Java也成了Web應用程式開發領域的重要角色,尤其是在企業應用系統之上。更有趣的是,即使Java仍然扮演舉足輕重的地位,但是時至今日,已經鮮少在網頁上看到人們使用Java Applet──這個讓Java開始普及化的最重要推手。

當然Java的確具備了先天良好的體質條件,例如它有著和C++系出同門的血統,但試著改善C++的一些問題,而且開放原始碼社群也運作良善,提供了眾多的程式庫及應用程式框架,讓Java開發者都能夠獲得強大的奧援。不過這說明了,每個語言之所以能夠流行、普及,不單只受語言先天本質的影響,和它所推出的時空環境、因緣際會,都會有高度的相關性。

而像Ruby這個程式語言的興起,事實上,幾乎可以說是由RoR(Ruby on Rails)這個Web應用程式框架所帶起的風潮。

當RoR開始流行的時候,正是Web 2.0的概念席捲全世界的網站開發之際。它的一些機制及設計,剛好符合許多新創網站尤其是Web 2.0網站在開發上的需求。而其中最受開發者注意的,自然是RoR開發者所感受到的高生產力,也因此,有許多開發者被其高生產力所吸引,因而開始採用RoR來開發Web應用程式。

從應用程式框架看Java
做為一個主流的程式語言,自然會有不少人拿Java和Ruby/RoR的組合來相提並論。要比較語言的優劣,絕對不是一件簡單的事,但是要比較語言的特性,以及從這些特性可能衍生出來的情況,或許就容易多了。

毫無疑問的,Java在Web應用程式開發上存在一些被開發者所質疑的問題,其中最嚴重的,恐怕就是複雜的應用程式框架。採用Java社群常見的應用程式框架,你可能會使用Struts來提供Web應用程式的MVC基礎架構,同時使用Hibernate來做永續性資料的存取,當然,可能還會再搭配不同的程式庫或應用程式框架來解決不同的問題。Struts和Hibernate這兩個應用程式框架都有其設計理念,而且也足夠強大,但是,它們的問題可能就出在它們因為強大而衍生出來的複雜度。

因此,開發者想要開始開發以Java為基礎的Web應用程式,就必須先克服這些應用程式框架不低的學習曲線。

但這並不是說完備、彈性的應用程式框架不好,而是說,在這種情況下,就會有比較高的學習曲線,需要花更多的時間才能上手。而在某一些應用情境下,這樣的特性會被視為是一種缺點。

Java和Ruby本身的差異
但總的來說,應用程式框架的問題,並不等同於程式語言的問題。只要打造出符合另一種需求的應用程式框架,基於應用程式框架的問題並不難解決。而程式語言本身的特性,才是不容易去改變的。若是拿Java和Ruby相比較,會有什麼特質上的差異呢?

從語言的本質來看,Java是屬於靜態型別的語言,而靜態型別的語言的特色,就是程式中必須明確的宣告物件或變數所屬的型別,並且在程式中基於這個型別來加以運用,而編譯器也才能在編譯期間基於這個型別進行相關的型別檢查。

之所以要宣告型別,是希望藉由程式設計者透過型別的宣告,讓編譯器得以明白程式中每個變數、物件能合法進行的操作,進而避免程式中做了不合適的動作,因而造成了錯誤。例如,某個物件是型別A,程式中卻對它做了型別B才提供的操作,那麼就會引發錯誤。而靜態型別的語言,就是希望透過編譯器明確知道你打算用什麼型別來看待某個變數,讓編譯器在編譯過程中協助你檢查程式碼是否有潛在型別錯用的情況。

靜態語言讓編譯器來協助程式設計者進行合法操作的檢查,這當然是一個優點,但是因為需要讓程式設計者提供和型別相關的資訊,程式語言本身就會多出額外的語法及語言元素,而相對地,設計者在程式中也必須提供這些資訊。可以想見的,這有可能會使得程式碼的長度變長,而且乍看之下,不那麼地簡潔。

相較於Java屬於靜態型別一派,Ruby則分屬相對的動態型別陣營。動態型別語言因為少了型別宣告相關的語法,在語法成本上降低,程式碼也能基於這個原因而變的更為簡短。

有好就有壞,這兩派相爭已經有多年的歷史,至今仍未有定論,可以說是各有擁護者,顯然沒有任何一派有絕對的優勢。動態語言節省了語法成本,帶來了一些好處,但是相形之下,對程式設計者的技巧及自律的要求就變高了。因為少了編譯器的協助,型別或介面錯用的情況,就必須倚賴程式設計者自行避免。

少了編譯時期靜態的檢查,光是在撰寫程式的時候打錯變數裡的字(typo),就有可能造成災難。因為這樣的錯誤,沒有辦法在編譯時期被檢查出來,只能等到執行期間程式真的執行到出錯的地方,才有辦法察覺。

認識動態型別語言的缺點
常常我們可以發現,某件事物的一面是優點、另一面就是缺點。動態型別語言省去型別語法所造成的額外負擔,一方面帶來好處,另一方面對應的壞處就是程式設計者必須自行負責可能潛在的型別、介面錯用。

近來測試驅動式的開發方法大行其道,對於動態型別語言,測試驅動式的開發方法是可以彌補型別檢查的問題。因為,倘若測試案例的覆蓋率有足夠的水準,那麼在執行測試案例時,便有很高的機會可以偵測出型別錯用的程式碼,藉以彌補動態型別語言的這個問題。

不過,除此之外,動態型別語言還有一些問題。例如,因為程式碼在操作物件時不知型別資訊,那麼光是倚靠靜態的程式碼分析,也無法得知程式碼所操作的型別為何,對於一些整合開發環境(IDE)來說,也就無法取得型別資訊。

事實上,讓整合開發環境得到型別資訊、進行更多靜態的程式碼分析,可以為程式設計者提供相當多的協助。例如,許多IDE都會提供所謂的自動補齊功能(autocompletion),自動幫程式設計者補上待填的程式碼,加快程式設計者撰寫程式碼的速度。又例如,IDE所提供的自動重構功能,也都需要倚靠這些靜態的資訊才能進行。對於動態型別的語法,IDE能提供的幫助有限,只能靠程式設計者自身的努力。

除此之外,動態型別語言裡的「動態」,基本上,並非全然不付代價就可以得到,它所付出的重要代價,就是效率。當Ruby因為RoR開始風行起來的時候,開發者最關心的還是效率議題。

有趣的是,當Java初問世之時,效率也是時常被質疑的重點之一,而現在很少人著墨在這個議題之上了。關於Java和Ruby的對照討論,讓我們下回再繼續來完成。

專欄作者

熱門新聞

Advertisement