《做Java開發這一年》---看.net 和 Java的對比
從去年到現在,從.NET轉向Java開發(只是因為專案原因,絕對與平臺好壞沒有關係)差不多有一年的時間了。通過這一年時間也有些感觸,想從幾個面比較一下這兩個平臺。希望能做到客觀公正。
語言
我原來是使用C#語言的,和現在的Java語言相比,現在的Java語言語法就停留在C# 2.0這個年代。語法結構都非常傳統,中規中矩。很突出的一點是,因為缺少對閉包的支援,有些用C#很容易做到的,用Java需要寫很多廢話程式碼。
前幾天InfoQ上發表了一篇英國衛報逐步採用Scala替換Java的文章裡一句話用的很好:看Java的程式碼很容易讓你只見樹木,不見森林。因為為了實現某個功能,你需要太多的支撐程式碼,而實現功能的關鍵程式碼卻迷失了。
舉個例子:我需要一個排好序的使用者列表,排序的依據是使用者名稱字。很簡單的需求對不。自然的程式碼肯定是這樣的:
IList<User> users = …
users.OrderBy(user => user.Name);
而如果用Java實現同樣的功能你可能要這樣寫:
List<User> users = …
Collections.sort(users,new Comparator<User>() {
public int compare(User left, User right) {
return left.getName().compareTo(right.getName());
}
});
第一:沒有擴充套件方法的支援,只有藉助靜態的輔助類
第二:沒有閉包的支援,非要寫個難看的匿名類
其實我們只需要一個OrderBy,一看就明白,但現在多了這麼多“無用”的程式碼,反而核心的價值(order by)卻顯得不那麼重要了。這還是一個很簡單的例子,在實際的專案中你會為此付出更多的代價,你要寫出一堆味同嚼蠟的程式碼才能實現你想要的那個功能,而那個功能其實是很顯而易見。
所以在語言層面,Java沒有任何亮點,只覺得羅裡羅嗦。
關於語言層面的比較,老趙寫過很多,而且非常精彩,建議去欣賞一下。
不過Java也有那麼很少幾個有點意思的小東西:比如靜態匯入(腦袋提醒,這東西很早就在VB裡出現了)、以及Java對Annotation的特殊支援讓我們可以做一個更有意思的事情。
概念滿天飛
做Java以來,讓我感觸最深的是在Java世界裡概念滿天飛。ORM,IOC,AOP,這幾個在.NET的世界裡也有,但沒見過這麼濃的,但是如果你做Java應用,你不熟悉這幾個你都不好意思出去跟人打招呼,所以除了學習Java本身外還有一大堆開源框架等著你研究。
還有什麼View Model,Presentation Model,Validator,BRO(Business Rule Object),BPO(Business Process Object),BDD。關鍵是不僅是概念上存在這樣的名詞,它還大量的出現在程式碼裡。程式碼裡將概念描述得淋漓盡致,還規規矩矩。或許我土老帽了,我開發.NET三年有餘,從來沒整這些玩意兒。但是我一點也不懷疑我的程式碼難以閱讀,難以維護。
配置檔案,你能再多一點麼
我超級厭惡Spring的配置檔案(雖然你說這只是個框架,但貌似Java社群有這個趨向)。雖然Spring現在也增加了註解(Annotation)的支援,但是還有那麼一些知道的和不知道的原因,專案中存在大量的配置檔案。而且為了“模組性”,一個小小的配置檔案又包含有幾個配置檔案。有配置controller的,有配置DAO的,有配置service的。額,還有那該死的Hibernate的hbm檔案。我想,系統的複雜性就是這麼一點一點的堆積而來的。
ASP.NET的配置檔案一度也有變得更臃腫的趨勢,但最後還是大大瘦身(.NET 4.0裡預設的web.config很小了)。而且Attribute在.NET的第一個版本就出現了,很多可配置的東西都提供了Attribute的API和XML的API,所以沒有歷史遺留包袱。
開源,這個我喜歡
Java裡的開源軟體遠遠超過.NET的(這可能跟微軟有一定的關係吧)。如果你想完成一項工作,總會有一個開源軟體適合你。比如我們要做一個定時排程的任務,馬上就有Quartz跑到了你的視野,你只需實現幾個介面,然後在配置檔案裡配置一下(又是該死的配置檔案),又比如你苦於在Java裡沒法像C#裡那樣用Lambda,馬上有個跟你一樣想法的人開發了一個lambda4j(Java人有個說法是:語言不足類庫來補,不過Java這個語言太不足了,所以有的時候類庫補也補不好)。你可以在琳琅滿目的開源框架和開源類庫裡尋找一個最合適的,然後開啟這個潘多拉魔盒。最主要的是她還是開放的,你不僅可以學習其程式碼思想,如果你發現有問題你甚至可以提交程式碼,那種成就感我倒是在開發.NET時沒有感覺到。比如你要開發高效能伺服器,在.NET裡還沒見過這類的開源專案,可Java裡你可以學習Netty,可以學習Mina,你甚至可以根據自己具體的業務場景,對這些開源軟體進行適當的修改。當然,你可以說思想是一樣的,這倒是不錯。但因為IO模型在Java裡和.NET裡並不一樣,所以還是有很多不同的(當然我覺得.NET的非同步IO更容易使用,Java的NIO那是什麼狗屎一樣的API啊)。
IDE
搞開發的肯定離不開IDE。.NET裡的IDE當之無愧的是Visual Studio了。不過我卻覺得Visual Studio這幾年已經離開發人員越來越遠了,好像他要搞什麼全生命週期的軟體開發工具。所以不但臃腫,而且對開發人員並不是很友好(當然,她的視覺化設計器是無與倫比的,但我不覺得視覺化設計器是什麼開發人員的“利器”)。舉兩個例子:VS裡大量使用組合快捷鍵。這樣不僅使得快捷鍵過長,難以記憶,而且還好難使用啊,你必須按兩次,而且時間不能間隔太長。還有VS的重構功能,太弱了。
在Java裡有各種各樣的IDE,有免費的,有收費的。我很喜歡的一個就是Intellij Idea。Idea給我的印象就是,她真的是在關注開發人員(寫程式碼的)這個角色。所有的快捷鍵都很簡單,好用好記。比如,大部分東西在Idea裡可以使用Alt+Enter這個萬能快捷鍵解決(這個快捷鍵是上下文感知的,在不同上下文中它知道要幹什麼)。
再就是Idea對重構的支援,如果你熟練之後,做一項大的重構你都無需手動的去修改什麼程式碼,直接依靠IDE的支援就可以完成,這在安全的重構裡是很重要的一點,手動的去修改程式碼重構如果在測試不完備的情況下風險是非常高的。
當然VS也有很多非常好用的外掛,可以提高開發效率。比如大名鼎鼎的Resharper就來自於Intellij Idea同一個公司,由這個外掛你可以看到Idea是如何關注寫程式碼的人的效率。
JVM vs CLR
一般的,Java跑在JVM上,C#跑在CLR上。從技術實現上他們兩平分秋色,各有各的優點,我們不能評價他們的好壞。只能說可能JVM在XXX上勝過CLR,CLR在XXX上勝過JVM。而且JVM和CLR有居多相似之處,大多數東西都可以在對方找到相應的東西。
那麼她們就無法比較了麼?不是,經過一年的學習我表示我更喜歡JVM一點。
JVM(在這裡只假設是Oracle/Sun Hotspot JVM)暴露了眾多的配置引數給開發人員。你可以通過這些引數間接地控制JVM的執行。就比如GC吧,JVM裡有各種引數來控制各個代的大小,還可以通過引數讓JVM採用什麼樣的垃圾收集策略。因為不同型別的應用:比如桌面的、伺服器端得、記憶體小的等等不同型別的應用適合不同的垃圾收集策略。而CLR在垃圾收集上只給開發人員提供了Workstation(是否是concurrent GC,.net 4.0是background GC)/Server等很少的控制(不過也幾乎很少用到)。當然,如果你想最大化控制CLR你就只有自己Host CLR,然後呼叫Host API進行控制,但是那樣難度高很多。
我很願意承認CLR是自適應的,她能自動的智慧的識別出你的需求,然後自動的進行調整。不過我在這裡主要想到的是,微軟在這裡扮演著保姆的角色。在你很小的時候,保姆能夠在一定程度上保護你,免你受到傷害。但是你不能永遠生活在保姆的懷抱裡,如果你想變得更強大你需要自己獨自一人出去看看。
注:這一節不是比較JVM和CLR,因為我沒有那個能力。只是想從JVM和CLR所表現出來的差異來看看一些“看不見的東西”。
開發人員
上面主要談了技術層面的東西。現在說說軟體開發中的人。
我現在所在的公司面試有個特點:會讓面試者做一份家庭作業,然後讓公司同事Code Review。在這一年裡我看了很多Java的程式碼,也看了很多C#程式碼。但是我傷心的發現:
1、雖然Java的也有爛程式碼,但是Java程式碼大多更注意程式碼的美感。大家都非常注意選擇方法名,變數名,類名等。也非常願意寫一些小的,容易理解的方法,小的目的明確的類。可我親愛的.NET同行們,大多在這方面很隨意。一個方法200行不算長,甚至一個功能就放到一個方法裡實現了。我看呀看呀,都看不到盡頭。更別說類職責單一了。
2、測試 Java同學的程式碼大多有測試,雖然有的測試不怎麼好,但最起碼有那麼幾個測測核心功能。但是.NET程式碼呢?很難見到幾個有測試的(難道這是因為VS很晚才加入對Unit Test的支援有關?)。我不是說一定要有測試,我只是描述一下這麼個現象。
3、你也太隨意了。我見到有那麼幾份.NET程式碼,我知道你建立了一個WinForm的專案,然後你卻不把VS自動生成的那幾個Form1.cs,Form1.resx給刪掉。
4、構建 從構建這個層面就更顯出問題了,Java同學提交的程式碼大多有構建的指令碼,無論是Ant還是Maven,所以你只需要敲一個命令列,馬上可以看見人家的結果。而.NET同學的基本上都是sln檔案。這一點不是說誰好誰壞的,因為我之前做.NET也從來沒有自動構建指令碼,我只想說兩個社群有些不同。
後記
我在這裡並不是貶低某個社群的開發人員,也不想扯進任何平臺的紛爭。因為這只是我看到的現象,還有很多是我沒看到的,而且這也嚴重的受到我周圍同事的影響,所以難免以偏概全。
如果有不足地方請不吝指教。