有些人問我,在現有的語言裡面,有什麼好的推薦?我說:「Java。」他們很驚訝:「什麼?Java!」 所以我現在來解釋一下。
Java超越了所有咒罵它的「動態語言」
也許是因為年輕人的逆反心理,人們都不把自己的入門語言當一回事。很早的時候,電腦系的學生用Scheme或Pascal入門,現在大部分學校都用Java。這也許就是為什麼很多人恨Java,瞧不起用Java的人。提到Java,感覺就像是爺爺那輩用的東西。他們說,Java老氣,龐大,複雜,臃腫。
某些Python程式設計師,在論壇裡跟初學者講解Python有什麼好,其中一個原因竟然是:「因為Python不是Java!」他們喜歡這樣宣傳:「看Python多簡單清晰啊,都不需要寫類型…」 對於Java的無緣無故的恨,盲目的否認,導致了他們看不到Java很重要的優點,以至於迷失自己的方向。雖然氣勢上佔上風,然而其實Python作為一個程式語言,是完全無法和Java抗衡的。
在效能上,Python比Java慢幾十倍。由於缺乏靜態型別等重要設施,Python程式碼有bug很不容易察覺,察覺了也不容易debug,所以Python無法用來建構大規模的,複雜的系統。你或許發現某些startup公司的主要程式碼是Python寫的,然而這些公司的軟體,品質其實相當的低。在成熟的公司裡,Python最多只用來寫工具性質的東西,或是小型的,不會影響系統可靠性的腳本。
靜態類型的缺乏,也導致了Python不可能有很好的IDE支持,你不能完全可靠地重構(refactor)Python程式碼。 PyCharm對於早期的Python程式設計環境,是一個很大的改進,然而理論決定了,它不可能完全可靠地達到「變數換名」等基本的refactor操作。
在設計上,Python,Ruby比起Java,其實複雜很多。缺少了很多重要的特性,有毛病的「強大特性」倒是多了一堆。由於盲目的推崇所謂“正宗的面向對象”方式,所謂“late-binding”,這些語言裡面有太多可以“重載”語義的地方,不管什麼都可以被重定義,這導致代碼具有很大的不確定性和複雜性。 Python和Ruby程式碼很容易被濫用,不容易理解,容易寫得很亂,容易出問題。
很多JavaScript程式設計師也盲目地鄙視Java,而其實JavaScript比Python和Ruby還要差。不但具有它們的所有缺點,而且缺乏很多必要的,方便的特性,例如基本的class定義都沒有。 JavaScript的各種“WEB框架”,層出不窮,似乎一直在推陳出新,而其實呢,全都是在黑暗裡瞎蒙亂撞。 JavaScript的社群以幼稚著稱。你常發現一些非常基本的常識,被JavaScript「專家」們當成了不起的發現似的,在大會上宣講。我看不出來JavaScript社群開那些會議,到底有什麼意義,彷彿只是為了拉關係找工作。
Java的「繼承人」沒能超越它
最近一段時間,很多人熱衷於Scala,Clojure,Go等新興的語言,他們以為這些是比Java更現代,更先進的語言,以為它們最終會取代Java。然而這些狂熱分子們逐漸發現,Scala,Clojure和Go其實並沒有解決它們聲稱能解決的問題,反而帶來了它們自己的毛病。這些毛病很多是Java沒有的。
關於Go,我已經評論過很多了,有興趣的人可以看這裡。總之,Go是民科加自大狂的產物,這裡我就不多說它了。
我認識一些人,開頭很推崇Scala,彷彿什麼救星似的。我建議他們別去折騰了,老實實用Java。沒聽我的,結果到後來,成天都在罵Scala的各種毛病。但是沒辦法啊,專案上了賊船,只好繼續用下去。我不喜歡進行人身攻擊,然而我發現一個語言的好壞,往往取決於它的設計者的水平,人品,和動機。很多時候我看人的直覺是異常的準,以至於依據對語言設計者的第一印象,我就能預測到這個語言將來會怎麼發展。在這裡,我想談談對Scala和Clojure的設計者的看法。
Scala的設計者Martin Odersky,雖然在程序語言領域有所建樹,發表了不少看似高深的學術論文( 其實很多是扯淡的),然而他對於語言的“設計”,其實並不是特別在行。所以我很驚訝的發現,有些非常基本的東西,Scala都會搞錯。由於Odersky是大學教授,名聲在外,很多人想找他拿個PhD,所以東拉西扯的,喜歡往Scala裡面加入一些不明不白,有潛在問題的“特性”,其目的就是發paper,混畢業。這導致Scala過度繁複,加入的特性很多後來被證明沒有太大用處,反而帶來了問題。學生把程式碼實作加入Scala的編譯器,畢業就走人不管了,所以Scala編譯器裡,就留下一堆堆的歷史遺留垃圾和bug。
再來說一下Clojure。當Clojure最初「橫空面世」的時候,有些人熱血沸騰地向我推薦。於是我看了一下它的設計者Rich Hickey做的宣傳講座影片。當時我對他一知半解拍胸脯的本事,印象非常的深刻。 Rich Hickey真的是半路出家,連CS學位都沒有。但他那種氣勢,彷彿其他的語言設計者什麼都不懂,只有他看到了真理似的。不過也只有這樣的人,才能創造出「宗教」吧? Clojure大力宣傳的「特性」(什麼lazy啊,pure啊,transactional memory啊),都是從別的語言道聽途說抄過來,卻又沒能深刻理解其精髓。有些“函數式語言”的特性,本來就是有問題的,卻不問青紅皂白,為了“主義正確”,抄過來。所以最後你發現這語言是掛著羊頭賣狗肉,說得頭頭是道,用起來怎麼就那麼蹩腳。
Clojure的社區,一直忙著從Scheme和Racket的社區抄襲思想,卻又想標榜是自己的發明。例如Typed Clojure,就是原封不動抄襲Typed Racket。有些一模一樣的基本概念,在Scheme裡面都幾十年了,恁是要改個不一樣的名字,免得你們發現那是Scheme先有的。甚至有人把SICP,The Little Schemer等名著裡的程式碼,全都用Clojure改寫一遍,結果完全失去了原作的簡單性和精華性。最後你發現,Clojure裡面好的地方,全都是Scheme已經有的,Clojure裡面新的特性,幾乎全都有問題。我參加過一些Clojure的meetup,可是後來發現,裡面竟是各種喊著大口號的初學者,各種趾高氣昂的民科,愚昧之至。
盲目推崇Scala和Clojure的人們,很多最後都發現,這些語言裡面的“新特性”,幾乎都有毛病。它們裡面最重要、最有用的特性,其實早就已經在Java裡了。有些人跟我說:「你看,Java做不了這件事情!」 後來經我分析,發現他們在潛意識裡早已死板的認定,非得用某種最新最酷的語言特性,才能達到目的。 Java沒有這些特性,他們就以為Java做不了,非得用另外的語言。其實,如果你換一個角度來看問題,不要鑽牛角尖,專注於解決問題,而不是去追求最新最酷的“寫法”,你就能用Java解決它,而且解決得乾淨利落。
如果現在要做一個系統,真的寧可用Java,也不要浪費時間去折騰什麼Scala或Clojure。錯誤的人設計了錯誤的語言,拿出來浪費大家的時間。
Java沒有特別討厭的地方
Java也許缺少一些方便的特性,然而長久以來用Java進行教學,用Java工作,用Java開發PySonar,RubySonar,Yin語言,… 我發現Java其實並不像很多人傳說的那麼可惡。我發現自己想要的95%以上的功能,在Java裡面都能找到比較直接的用法。剩下的5%,用稍微笨一點的辦法,一樣可以解決問題。
很多人討厭Java,其實是因為早期的GoF Design Patterns,試圖提出千篇一律的模板,給程式帶來了不必要的複雜性。然而Java語言本身,其實跟Design Patterns並不是等價的。 Java的設計者跟Design Pattern的設計者,完全是不同的人。你完全可以使用Java寫出非常簡單的程式碼,而不使用Design Patterns。
Java有優良的IDE支援
我平常都用IntelliJ來寫Java程式碼。我發現IntelliJ裡面,有一些非常好的設計想法。其中許多功能,其實超越了所有的文字編輯器(Emacs,VIM…)。 IntelliJ讓Java如虎添翼,開發起來感覺是在飛一樣。
用IntelliJ的時候,你不需要為「給變數取名字」之類的事情焦慮。因為IntelliJ有非常強大且友善的refactor功能,你可以非常迅速的換掉變數的名字。所以在第一次創造變數的時候,你不需要花心思去取一個完美的名字。用一個還算湊合的名字,把程式碼很快寫出來,實驗成功。然後再回來去看代碼,把名字換成更適合的就可以。
IntelliJ還可以進行非常迅速的結構變換,這讓你就像藝術家在構造一個雕塑作品。最開頭我可以大刀闊斧,把程式碼劈成大致的形狀,然後再把它仔細推敲,揉捏成更好,更容易理解,更具魅力的形狀。
結論
程式設計使用什麼工具是重要的,然而工具終究不如自己的技術重要。很多人花了太多時間,折騰各種新的語言,希望它們會奇蹟一般的改善代碼質量,結果最後什麼都沒做出來。選擇語言最重要的條件,應該是「夠好用」就可以,因為專案的成功最終是靠人,而不是靠語言。