Java與Node.js的較量--一場史詩之戰(zhàn)
圖片來源:Flickr用戶Tsutomu Takasu拍攝作品
縱觀整個(gè)計(jì)算機(jī)發(fā)展史,1995是瘋狂的一年:這一年Java語言誕生,緊跟其后的是JavaScript。后者雖然含有java二字,實(shí)際和java并不沾親帶故。Java屬于靜態(tài)編程語言,需要編譯;而JavaScript只是一個(gè)簡單的解釋性腳本語言,屬于動態(tài)語言。
如果經(jīng)歷過早期java發(fā)展,我們不難忘記它曾經(jīng)的空前巔峰:鋪天蓋地的推廣,超大規(guī)模的JavaOne會議。很多人都認(rèn)定,這種新型的編程語言必將不惜一切代價(jià)稱霸計(jì)算機(jī)領(lǐng)域。然后這一預(yù)測最終證實(shí)只是部分準(zhǔn)確。而今,安卓應(yīng)用、企業(yè)級服務(wù)器應(yīng)用程序和類似藍(lán)光光盤的嵌入式空間中,java仍然保持著統(tǒng)治地位。 縱使java有著極為廣泛的實(shí)現(xiàn)領(lǐng)域,但桌面應(yīng)用程序和瀏覽器編程卻始終是它的弱點(diǎn)。Java創(chuàng)立的基于html的小應(yīng)用程序,還有基于java的開發(fā)工具,都是開發(fā)人員極力推崇的。但復(fù)雜的場景或?qū)嶋H需求,往往會打破這種固有的組合。值得慶幸的是,早期服務(wù)器端開發(fā)成為了java揚(yáng)眉吐氣的領(lǐng)域。
同時(shí),先前被很多程序員誤解為Java好姐妹的JavaScript也開始在自己擅長的領(lǐng)域一展雄風(fēng)。不得不承認(rèn),曾有一段時(shí)期,HTML和Web大張旗鼓發(fā)展的時(shí)候,JavaScript像一個(gè)小博格人一樣,隨波逐流。但AJAX的出現(xiàn),徹底改變了這一現(xiàn)狀。
接著,Node.js的橫空出世,吸引了業(yè)內(nèi)眾多開發(fā)者的追捧。與Java或其他編程語言相比,基于JavaScript的Node.js平臺在服務(wù)器端的表現(xiàn)更為出色——快!更快!Web端動態(tài)化發(fā)展,對數(shù)據(jù)請求次數(shù)和響應(yīng)速度的要求,Node.js均可以滿足。
放在20年前,這些都是不可想象的。如今等待這對雙J兄弟的是一場硬戰(zhàn),輸贏將決定誰會坐上編程界頭把交椅。一方是在工程應(yīng)用和體系結(jié)構(gòu)領(lǐng)域根基牢固的靜態(tài)編程語言;另一方是更加輕量級簡易化的動態(tài)編程語言。老派編譯性語言Java會堅(jiān)守住自己的陣地嗎?高速靈活的Node.js會為JS清除霸權(quán)道路上的一切障礙嗎?
Java的優(yōu)勢:堅(jiān)如磐石的應(yīng)用基礎(chǔ)
提到這點(diǎn),我放佛都聽到了開發(fā)者魔性的笑聲。是的,Java自身存在著一些小的缺陷和bug,但相對而言,它絕對是編程界的直布羅陀巨巖(haha,乃們能聽出我對其頂禮膜拜的夸贊吧)。Node.js如要達(dá)到這個(gè)境界,估計(jì)還要再努力上幾年。不僅如此,事實(shí)上,當(dāng)初Sun開發(fā)java虛擬機(jī)所做的回歸測試數(shù)量級,JavaScript預(yù)達(dá)到這個(gè)水準(zhǔn),沒個(gè)幾十年根本做不到。 如果你啟動了一個(gè)java虛擬機(jī),那么恭喜你,您獲得了一個(gè)掌控企業(yè)版服務(wù)器的資深管理者20年的經(jīng)驗(yàn)值!如果你毅然決定要是用JavaScript,這將意味著,您可能遇到了一個(gè)脾氣壞難相處的工作伙伴:這家伙時(shí)而能與你友善相處;時(shí)而又要拿出自己那套做人準(zhǔn)則(JS標(biāo)準(zhǔn))bibi,向你發(fā)起被動侵犯性的攻擊。
Node的優(yōu)勢:無處不在的可應(yīng)用性
正是由于Node.js的出現(xiàn),JS終于在網(wǎng)絡(luò)服務(wù)平臺找到自己的歸屬位置。Node采用異步編程達(dá)到處理并發(fā)事件的效果。雖然它的可靠性還有待提高,但其在業(yè)內(nèi)表現(xiàn)已經(jīng)堪稱不俗。傳統(tǒng)的web編程,Java實(shí)現(xiàn)后臺服務(wù),JS完成前端功能;而Node.js可以讓JS一人輕松搞定客服端和服務(wù)器,特別是當(dāng)我們想把邏輯層從服務(wù)器移植到瀏覽器層面時(shí),Node簡直就是熠熠生輝。或者矯情的老板又想讓我們把邏輯層移回服務(wù)端,反反復(fù)復(fù),不管怎么個(gè)玩法,總之Node.js讓代碼移植更加簡化。
Java能贏在何處:更優(yōu)秀的IDE
Eclipse,NetBeans和IntelliJ,集調(diào)試、編譯和服務(wù)為一體,這是Java開發(fā)人員公認(rèn)的三大頂尖IDE。他們發(fā)展至今,潛心專注用戶體驗(yàn),擁有堅(jiān)實(shí)的相關(guān)配套插件。而node.js開發(fā)人員可以在命令行下編寫代碼,或者使用文本編輯器。也有一部分人會選擇Eclipse和Visual Studio,這二者也是支持node開發(fā)的。Node.js在全球范圍內(nèi)掀起的熱浪,勢必會孕育出一些新的工具和資源。比如IBM團(tuán)隊(duì)開發(fā)的Node-Red,它允許用戶通過組合各部件來編寫應(yīng)用程序。然而,這種新的開源IDE,若要達(dá)到Eclipse的水準(zhǔn),尚有一大段距離。再比如前端開發(fā)神器WebStorm,這是jetbrains公司旗下一款JS開發(fā)工具,可支持多命令行開發(fā)。
當(dāng)然,僅從代碼的編輯和簡單開發(fā)功能出發(fā),這些新型的輕量級工具綽綽有余。但,如果你希望在執(zhí)行源代碼時(shí),IDE可以給開發(fā)者更多的指引(好比一場開胸手術(shù)中,手握手術(shù)刀的大夫希望得到更多的協(xié)助),強(qiáng)悍的java開發(fā)平臺可以直接秒殺那些蝦兵蝦將——無處不在的java!
Node能贏在何處:簡化進(jìn)程
諸如Ant和Maven此類復(fù)雜的軟件構(gòu)建工具,對java編程帶來的改變意義非凡。然后,始終存在一個(gè)問題。比如,開發(fā)者在xml中寫出的代碼,其規(guī)范和語法在其他編譯環(huán)境下得不到支持。的確,可以使用嵌套標(biāo)簽來展示分支,但java與xml之間惱人的互轉(zhuǎn)問題,仍不好解決。
Java:遠(yuǎn)程調(diào)試
能夠遠(yuǎn)程監(jiān)控服務(wù)器集群性能,一直是java引以為豪的。JVM本身的一些特點(diǎn),加之性能測試工具的輔助,使得程序可以輕松探測出服務(wù)端瓶頸和失敗。Java堆棧企業(yè)版上可以運(yùn)行極為復(fù)雜尖端的服務(wù)器,而使用這些服務(wù)器的公司可以在遙測過程中獲得最好的用戶體驗(yàn)。上述提到的監(jiān)測調(diào)試功能,發(fā)展至今已相當(dāng)成熟,我們在部署服務(wù)時(shí)會深受其益。
Node.JS:直訪數(shù)據(jù)庫
類似CouchDB這種新型數(shù)據(jù)庫,可以通過編寫JS腳本直接對其進(jìn)行訪問。Node.js和CouchDB語句可以混合使用,不存在互轉(zhuǎn)問題,頭疼的語法差異也可以拋在腦后。
同樣的情況,許多java程序開發(fā)人員在工作中也需要寫一些sql語句,此時(shí)就要使用java編寫的數(shù)據(jù)庫(比如Derby),到這一步你以為就萬事大吉,那么只能說:你想多了!開發(fā)人員寫好的sql語句,需要進(jìn)一步經(jīng)過Derby解析,方可加載在java程序中編譯執(zhí)行。所以,java確實(shí)是一門不錯(cuò)的語言,但其語法無法與sql互轉(zhuǎn),導(dǎo)致開發(fā)團(tuán)隊(duì)需要明確分工:你來寫java,我來寫sql。
Java:豐富的資源庫
javat提供了一套龐大的工具包集合,這些資源在日常開發(fā)中發(fā)揮著極為重要的作用。例如,全文檢索引擎Lucene和計(jì)算機(jī)視覺庫OpenCV,是最典型的兩個(gè)開源項(xiàng)目,他們在一些重要的基礎(chǔ)工程中扮演著中流砥柱的角色。目前也有用javaScript開發(fā)的一些開源共享工具庫,其中也有讓人眼前一亮的函數(shù)和方法,但與Java這套成熟的資源庫相比,這一環(huán)節(jié)java勝出。
Node:JSON
當(dāng)數(shù)據(jù)庫反饋出結(jié)果后,java程序?qū)⑵滢D(zhuǎn)換為一個(gè)個(gè)java對象。這一環(huán)節(jié),開發(fā)人員會采用POLP或者Hibernate等映射框架來處理數(shù)據(jù),期間的配置和轉(zhuǎn)化耗時(shí)是非常大的。最終,java程序才會接受這些java對象。
其實(shí)大部分web服務(wù)端和數(shù)據(jù)庫,返回的數(shù)據(jù)類型是以JSON形式封裝的(這是JS自帶的一種數(shù)據(jù)交換格式)。這種數(shù)據(jù)格式被廣泛應(yīng)用于Java開發(fā)中,那么問題顯而易見嘍,開發(fā)者需要使用眾多JSON解析器或庫函數(shù)來進(jìn)行數(shù)據(jù)的再處理。而JSON是JavaScript原生格式,這意味著在JS中處理JSON數(shù)據(jù)不需要任何特殊的API或工具包,用戶可以簡單粗暴直接使用。
Java:堅(jiān)固的引擎
究竟有多少復(fù)雜組件基礎(chǔ)開發(fā)包是基于java強(qiáng)大的數(shù)學(xué)函數(shù)庫,一百個(gè),一萬個(gè),這個(gè)已經(jīng)很難去量化了。當(dāng)初Sun為研發(fā)java這套實(shí)用工具類,也是消耗了大量的時(shí)間和人力。現(xiàn)在被廣泛使用的有大數(shù)處理BigIntegre,精細(xì)復(fù)雜的IO庫,基于Gregorian和Julian的開源時(shí)間/時(shí)間庫。
在處理簡單任務(wù)方面,JavaScript的表現(xiàn)還算差強(qiáng)人意,但其實(shí)現(xiàn)機(jī)理卻混亂不堪。一個(gè)最常見的例子,JavaScript中定義的函數(shù)方法當(dāng)返回結(jié)果是“無”時(shí),可以有三種表現(xiàn)方式:undefined, NaN,以及 null。那么哪一種結(jié)果是正確的?其實(shí)這三者都是JS語言的數(shù)據(jù)類型,作用是為了保證程序的嚴(yán)謹(jǐn)性和邏輯性。乍一看,這種怪異的語法在程序運(yùn)行中一般是不會出錯(cuò),但與java那些個(gè)高大上的庫函數(shù)一比,又被秒成渣。
Node.JS:速度
node.js速度棒棒嗒,用過的人多說好。數(shù)據(jù)一來一往,就像閃電一般。它不會作死去盲目設(shè)置帶有死鎖風(fēng)險(xiǎn)的單線程;也不存在內(nèi)部自檢環(huán)節(jié),因?yàn)檫@有可能會降低執(zhí)行速度。總而言之,手起鍵落,node已然在執(zhí)行你的代碼了。
當(dāng)然,這種優(yōu)勢下暗藏隱患。代碼盡量要寫的簡單,這樣Node.js可以保你事事順利。一旦某段復(fù)雜的代碼死鎖,整個(gè)服務(wù)會掛掉。可以這樣理解,操作系統(tǒng)開發(fā)人員抓耳撓腮費(fèi)死勁建立起來的系統(tǒng)自保機(jī)制,是可以容忍部分程序錯(cuò)誤的。但Node.js完全瞧不上這套保護(hù)網(wǎng)。這也是node活該的地方。
Java:多線程
執(zhí)行速度快,固然好。但健壯優(yōu)良的代碼,會更勝一籌。這一輪,java贏得無可置疑。
Java框架開發(fā)的web服務(wù)器是多線程的??v使多線程會占用大量時(shí)間和內(nèi)存,但這種內(nèi)耗是值得的。因?yàn)?,一個(gè)線程死鎖,至少還有其他線程扛著;即便一個(gè)線程需要長時(shí)間占用cpu,至少其他線程不會饑餓等待。
以上情形放到Node.js下,結(jié)局慘不忍睹:一個(gè)線程慢下來,所有一切慢下來。所以,Node.js僅適用于單線程。
無數(shù)程序猿揮灑汗與淚,花費(fèi)幾十年心血,致力于建立一個(gè)處理并發(fā)事件的智能操作系統(tǒng)。Node在此點(diǎn)上卻無法與時(shí)具進(jìn),玩起了倒退到上個(gè)世紀(jì)60年代的單線程。
Node:續(xù)航能力
祖輩對我們耳提面命:節(jié)儉是美德,要做不浪費(fèi)不索取的好孩子。看著硅谷那幫傻缺用自己的行為在詮釋“創(chuàng)新”和“顛覆”,我們確實(shí)痛心疾首。但回頭靜心一想,去其糟粕才是一件意義非凡的啊。Java仍可寶刀未老,先輩們撰寫的骨灰級Java老代碼無處不在。誠然,Java也在孜孜不倦提供著新的IO接口,但那些已與時(shí)代脫軌的老接口將何去何從?小型應(yīng)用程序和基礎(chǔ)實(shí)用類也將面臨這種抉擇。
雙贏的局面?混合編程
服務(wù)器姓J(rèn)還是姓J(rèn)S,這個(gè)討論還會持續(xù)很長時(shí)間。有一種中庸的方法,可以避開這些喋喋不休的爭論—Java和JS的混合編程,將Java類轉(zhuǎn)換為與瀏覽器兼容的JS。GWT框架把這事做的就很漂亮,很多知名網(wǎng)站就采用了此方法。
嘿嘿,其實(shí)還有另外一條小路可以走:像Rhino這種使用Java語言編寫的JS的開源實(shí)現(xiàn),程序猿可以直接把Java代碼植入其中。如果你夠牛逼,還可以在當(dāng)前比較火的googleV8引擎上搗鼓這個(gè)事情。
總之,不要打打殺殺,和諧共處是王道!