做Java開(kāi)發(fā)這一年,這些事兒
從去年到現(xiàn)在,從.NET轉(zhuǎn)向Java開(kāi)發(fā)(只是因?yàn)轫?xiàng)目原因,絕對(duì)與平臺(tái)好壞沒(méi)有關(guān)系)差不多有一年的時(shí)間了。通過(guò)這一年時(shí)間也有些感觸,想從幾個(gè)面比較一下這兩個(gè)平臺(tái)。希望能做到客觀公正。
語(yǔ)言
我原來(lái)是使用C#語(yǔ)言的,和現(xiàn)在的Java語(yǔ)言相比,現(xiàn)在的Java語(yǔ)言語(yǔ)法就停留在C# 2.0這個(gè)年代。語(yǔ)法結(jié)構(gòu)都非常傳統(tǒng),中規(guī)中矩。很突出的一點(diǎn)是,因?yàn)槿鄙賹?duì)閉包的支持,有些用C#很容易做到的,用Java需要寫(xiě)很多廢話(huà)代碼。
前幾天InfoQ上發(fā)表了一篇英國(guó)衛(wèi)報(bào)逐步采用Scala替換Java的文章里一句話(huà)用的很好:看Java的代碼很容易讓你只見(jiàn)樹(shù)木,不見(jiàn)森林。因?yàn)闉榱藢?shí)現(xiàn)某個(gè)功能,你需要太多的支撐代碼,而實(shí)現(xiàn)功能的關(guān)鍵代碼卻迷失了。
舉個(gè)例子:我需要一個(gè)排好序的用戶(hù)列表,排序的依據(jù)是用戶(hù)名字。很簡(jiǎn)單的需求對(duì)不。自然的代碼肯定是這樣的:
- IList users = …
- users.OrderBy(user => user.Name);
而如果用Java實(shí)現(xiàn)同樣的功能你可能要這樣寫(xiě):
- List users = …
- Collections.sort(users,new Comparator() {
- public int compare(User left, User right) {
- return left.getName().compareTo(right.getName());
- }
- });
***:沒(méi)有擴(kuò)展方法的支持,只有借助靜態(tài)的輔助類(lèi)
第二:沒(méi)有閉包的支持,非要寫(xiě)個(gè)難看的匿名類(lèi)
其實(shí)我們只需要一個(gè)OrderBy,一看就明白,但現(xiàn)在多了這么多“無(wú)用”的代碼,反而核心的價(jià)值(order by)卻顯得不那么重要了。這還是一個(gè)很簡(jiǎn)單的例子,在實(shí)際的項(xiàng)目中你會(huì)為此付出更多的代價(jià),你要寫(xiě)出一堆味同嚼蠟的代碼才能實(shí)現(xiàn)你想要的那個(gè)功能,而那個(gè)功能其實(shí)是很顯而易見(jiàn)。
所以在語(yǔ)言層面,Java沒(méi)有任何亮點(diǎn),只覺(jué)得羅里羅嗦。
關(guān)于語(yǔ)言層面的比較,老趙寫(xiě)過(guò)很多,而且非常精彩,建議去欣賞一下。
不過(guò)Java也有那么很少幾個(gè)有點(diǎn)意思的小東西:比如靜態(tài)導(dǎo)入(腦袋提醒,這東西很早就在VB里出現(xiàn)了)、以及Java對(duì)Annotation的特殊支持讓我們可以做一個(gè)更有意思的事情。
概念滿(mǎn)天飛
做Java以來(lái),讓我感觸最深的是在Java世界里概念滿(mǎn)天飛。ORM,IOC,AOP,這幾個(gè)在.NET的世界里也有,但沒(méi)見(jiàn)過(guò)這么濃的,但是如果你做Java應(yīng)用,你不熟悉這幾個(gè)你都不好意思出去跟人打招呼,所以除了學(xué)習(xí)Java本身外還有一大堆開(kāi)源框架等著你研究。
還有什么View Model,Presentation Model,Validator,BRO(Business Rule Object),BPO(Business Process Object),BDD。關(guān)鍵是不僅是概念上存在這樣的名詞,它還大量的出現(xiàn)在代碼里。代碼里將概念描述得***,還規(guī)規(guī)矩矩?;蛟S我土老帽了,我開(kāi)發(fā).NET三年有余,從來(lái)沒(méi)整這些玩意兒。但是我一點(diǎn)也不懷疑我的代碼難以閱讀,難以維護(hù)。
配置文件,你能再多一點(diǎn)么
我超級(jí)厭惡Spring的配置文件(雖然你說(shuō)這只是個(gè)框架,但貌似Java社區(qū)有這個(gè)趨向)。雖然Spring現(xiàn)在也增加了注解(Annotation)的支持,但是還有那么一些知道的和不知道的原因,項(xiàng)目中存在大量的配置文件。而且為了“模塊性”,一個(gè)小小的配置文件又包含有幾個(gè)配置文件。有配置controller的,有配置DAO的,有配置service的。額,還有那該死的Hibernate的hbm文件。我想,系統(tǒng)的復(fù)雜性就是這么一點(diǎn)一點(diǎn)的堆積而來(lái)的。
ASP.NET的配置文件一度也有變得更臃腫的趨勢(shì),但***還是大大瘦身(.NET 4.0里默認(rèn)的web.config很小了)。而且Attribute在.NET的***個(gè)版本就出現(xiàn)了,很多可配置的東西都提供了Attribute的API和XML的API,所以沒(méi)有歷史遺留包袱。
開(kāi)源,這個(gè)我喜歡
Java里的開(kāi)源軟件遠(yuǎn)遠(yuǎn)超過(guò).NET的(這可能跟微軟有一定的關(guān)系吧)。如果你想完成一項(xiàng)工作,總會(huì)有一個(gè)開(kāi)源軟件適合你。比如我們要做一個(gè)定時(shí)調(diào)度的任務(wù),馬上就有Quartz跑到了你的視野,你只需實(shí)現(xiàn)幾個(gè)接口,然后在配置文件里配置一下(又是該死的配置文件),又比如你苦于在Java里沒(méi)法像C#里那樣用Lambda,馬上有個(gè)跟你一樣想法的人開(kāi)發(fā)了一個(gè)lambda4j(Java人有個(gè)說(shuō)法是:語(yǔ)言不足類(lèi)庫(kù)來(lái)補(bǔ),不過(guò)Java這個(gè)語(yǔ)言太不足了,所以有的時(shí)候類(lèi)庫(kù)補(bǔ)也補(bǔ)不好)。你可以在琳瑯滿(mǎn)目的開(kāi)源框架和開(kāi)源類(lèi)庫(kù)里尋找一個(gè)最合適的,然后打開(kāi)這個(gè)潘多拉魔盒。最主要的是她還是開(kāi)放的,你不僅可以學(xué)習(xí)其代碼思想,如果你發(fā)現(xiàn)有問(wèn)題你甚至可以提交代碼,那種成就感我倒是在開(kāi)發(fā).NET時(shí)沒(méi)有感覺(jué)到。比如你要開(kāi)發(fā)高性能服務(wù)器,在.NET里還沒(méi)見(jiàn)過(guò)這類(lèi)的開(kāi)源項(xiàng)目,可Java里你可以學(xué)習(xí)Netty,可以學(xué)習(xí)Mina,你甚至可以根據(jù)自己具體的業(yè)務(wù)場(chǎng)景,對(duì)這些開(kāi)源軟件進(jìn)行適當(dāng)?shù)男薷?。?dāng)然,你可以說(shuō)思想是一樣的,這倒是不錯(cuò)。但因?yàn)镮O模型在Java里和.NET里并不一樣,所以還是有很多不同的(當(dāng)然我覺(jué)得.NET的異步IO更容易使用,Java的NIO那是什么狗屎一樣的API啊)。
IDE
搞開(kāi)發(fā)的肯定離不開(kāi)IDE。.NET里的IDE當(dāng)之無(wú)愧的是Visual Studio了。不過(guò)我卻覺(jué)得Visual Studio這幾年已經(jīng)離開(kāi)發(fā)人員越來(lái)越遠(yuǎn)了,好像他要搞什么全生命周期的軟件開(kāi)發(fā)工具。所以不但臃腫,而且對(duì)開(kāi)發(fā)人員并不是很友好(當(dāng)然,她的可視化設(shè)計(jì)器是***的,但我不覺(jué)得可視化設(shè)計(jì)器是什么開(kāi)發(fā)人員的“利器”)。舉兩個(gè)例子:VS里大量使用組合快捷鍵。這樣不僅使得快捷鍵過(guò)長(zhǎng),難以記憶,而且還好難使用啊,你必須按兩次,而且時(shí)間不能間隔太長(zhǎng)。還有VS的重構(gòu)功能,太弱了。
在Java里有各種各樣的IDE,有免費(fèi)的,有收費(fèi)的。我很喜歡的一個(gè)就是Intellij Idea。Idea給我的印象就是,她真的是在關(guān)注開(kāi)發(fā)人員(寫(xiě)代碼的)這個(gè)角色。所有的快捷鍵都很簡(jiǎn)單,好用好記。比如,大部分東西在Idea里可以使用Alt+Enter這個(gè)***快捷鍵解決(這個(gè)快捷鍵是上下文感知的,在不同上下文中它知道要干什么)。
再就是Idea對(duì)重構(gòu)的支持,如果你熟練之后,做一項(xiàng)大的重構(gòu)你都無(wú)需手動(dòng)的去修改什么代碼,直接依靠IDE的支持就可以完成,這在安全的重構(gòu)里是很重要的一點(diǎn),手動(dòng)的去修改代碼重構(gòu)如果在測(cè)試不完備的情況下風(fēng)險(xiǎn)是非常高的。
當(dāng)然VS也有很多非常好用的插件,可以提高開(kāi)發(fā)效率。比如大名鼎鼎的Resharper就來(lái)自于Intellij Idea同一個(gè)公司,由這個(gè)插件你可以看到Idea是如何關(guān)注寫(xiě)代碼的人的效率。
JVM vs CLR
一般的,Java跑在JVM上,C#跑在CLR上。從技術(shù)實(shí)現(xiàn)上他們兩平分秋色,各有各的優(yōu)點(diǎn),我們不能評(píng)價(jià)他們的好壞。只能說(shuō)可能JVM在XXX上勝過(guò)CLR,CLR在XXX上勝過(guò)JVM。而且JVM和CLR有居多相似之處,大多數(shù)東西都可以在對(duì)方找到相應(yīng)的東西。
那么她們就無(wú)法比較了么?不是,經(jīng)過(guò)一年的學(xué)習(xí)我表示我更喜歡JVM一點(diǎn)。
JVM(在這里只假設(shè)是Oracle/Sun Hotspot JVM)暴露了眾多的配置參數(shù)給開(kāi)發(fā)人員。你可以通過(guò)這些參數(shù)間接地控制JVM的運(yùn)行。就比如GC吧,JVM里有各種參數(shù)來(lái)控制各個(gè)代的大小,還可以通過(guò)參數(shù)讓JVM采用什么樣的垃圾收集策略。因?yàn)椴煌?lèi)型的應(yīng)用:比如桌面的、服務(wù)器端得、內(nèi)存小的等等不同類(lèi)型的應(yīng)用適合不同的垃圾收集策略。而CLR在垃圾收集上只給開(kāi)發(fā)人員提供了Workstation(是否是concurrent GC,.net 4.0是background GC)/Server等很少的控制(不過(guò)也幾乎很少用到)。當(dāng)然,如果你想***化控制CLR你就只有自己Host CLR,然后調(diào)用Host API進(jìn)行控制,但是那樣難度高很多。
我很愿意承認(rèn)CLR是自適應(yīng)的,她能自動(dòng)的智能的識(shí)別出你的需求,然后自動(dòng)的進(jìn)行調(diào)整。不過(guò)我在這里主要想到的是,微軟在這里扮演著保姆的角色。在你很小的時(shí)候,保姆能夠在一定程度上保護(hù)你,免你受到傷害。但是你不能永遠(yuǎn)生活在保姆的懷抱里,如果你想變得更強(qiáng)大你需要自己獨(dú)自一人出去看看。
注:這一節(jié)不是比較JVM和CLR,因?yàn)槲覜](méi)有那個(gè)能力。只是想從JVM和CLR所表現(xiàn)出來(lái)的差異來(lái)看看一些“看不見(jiàn)的東西”。
開(kāi)發(fā)人員
上面主要談了技術(shù)層面的東西?,F(xiàn)在說(shuō)說(shuō)軟件開(kāi)發(fā)中的人。
我現(xiàn)在所在的公司面試有個(gè)特點(diǎn):會(huì)讓面試者做一份家庭作業(yè),然后讓公司同事Code Review。在這一年里我看了很多Java的代碼,也看了很多C#代碼。但是我傷心的發(fā)現(xiàn):
1、雖然Java的也有爛代碼,但是Java代碼大多更注意代碼的美感。大家都非常注意選擇方法名,變量名,類(lèi)名等。也非常愿意寫(xiě)一些小的,容易理解的方法,小的目的明確的類(lèi)。可我親愛(ài)的.NET同行們,大多在這方面很隨意。一個(gè)方法200行不算長(zhǎng),甚至一個(gè)功能就放到一個(gè)方法里實(shí)現(xiàn)了。我看呀看呀,都看不到盡頭。更別說(shuō)類(lèi)職責(zé)單一了。
2、測(cè)試 Java同學(xué)的代碼大多有測(cè)試,雖然有的測(cè)試不怎么好,但最起碼有那么幾個(gè)測(cè)測(cè)核心功能。但是.NET代碼呢?很難見(jiàn)到幾個(gè)有測(cè)試的(難道這是因?yàn)閂S很晚才加入對(duì)Unit Test的支持有關(guān)?)。我不是說(shuō)一定要有測(cè)試,我只是描述一下這么個(gè)現(xiàn)象。
3、你也太隨意了。我見(jiàn)到有那么幾份.NET代碼,我知道你創(chuàng)建了一個(gè)WinForm的項(xiàng)目,然后你卻不把VS自動(dòng)生成的那幾個(gè)Form1.cs,Form1.resx給刪掉。
4、構(gòu)建 從構(gòu)建這個(gè)層面就更顯出問(wèn)題了,Java同學(xué)提交的代碼大多有構(gòu)建的腳本,無(wú)論是Ant還是Maven,所以你只需要敲一個(gè)命令行,馬上可以看見(jiàn)人家的結(jié)果。而.NET同學(xué)的基本上都是sln文件。這一點(diǎn)不是說(shuō)誰(shuí)好誰(shuí)壞的,因?yàn)槲抑白?NET也從來(lái)沒(méi)有自動(dòng)構(gòu)建腳本,我只想說(shuō)兩個(gè)社區(qū)有些不同。
后記
我在這里并不是貶低某個(gè)社區(qū)的開(kāi)發(fā)人員,也不想扯進(jìn)任何平臺(tái)的紛爭(zhēng)。因?yàn)檫@只是我看到的現(xiàn)象,還有很多是我沒(méi)看到的,而且這也嚴(yán)重的受到我周?chē)碌挠绊?,所以難免以偏概全。
如果有不足地方請(qǐng)不吝指教。
原文鏈接:http://www.cnblogs.com/yuyijq/archive/2011/06/28/2091803.html
【編輯推薦】