JavaSE官方團(tuán)隊(duì)成員為何“拋棄”Java蜻底,成JavaScript和Node死忠?

我是前 Sun 公司 Java SE 團(tuán)隊(duì)的一名成員聘鳞,在工作了 10 多年之后——2009 年 1 月——也就是在甲骨文收購 Sun 公司之前,我離開了公司要拂,然后迷上了 Node.js抠璃。

我對 Node.js 的癡迷到了怎樣的程度?自 2010 年以來脱惰,我撰寫了大量有關(guān) Node.js 編程的文章搏嗡,出版了四本與 Node.js 開發(fā)有關(guān)的書籍,以及與 Node.js 編程有關(guān)的其他書籍和眾多教程拉一。

在 Sun 公司工作期間采盒,我相信 Java 就是一切。我在 JavaONE 上發(fā)表演講蔚润,共同開發(fā)了 java.awt.Robot 類磅氨,組織 Mustang 回歸競賽(Java 1.6 版本的漏洞發(fā)現(xiàn)競賽),協(xié)助推出了“Java 發(fā)行許可”嫡纠,這在后來的 OpenJDK 項(xiàng)目啟動過程中起到了一定的作用烦租。我在 java.net(這個網(wǎng)站現(xiàn)已解散)上每周寫一到兩篇博文延赌,討論 Java 生態(tài)系統(tǒng)中所發(fā)生的主要事件,并堅(jiān)持了 6 年叉橱。這些博文的主要主題是關(guān)于“保衛(wèi)”Java挫以,因?yàn)榭傆腥嗽陬A(yù)言 Java 的“死期”。

在這篇文章中窃祝,我將會解釋我這個 Java 死忠是如何變成一個 Node.js 和 JavaScript 死忠的掐松。

但其實(shí)我并沒有完全脫離 Java。在過去的三年中粪小,我編寫了大量 Java/Spring/Hibernate 代碼大磺。但兩年的 Spring 編碼經(jīng)歷讓我明白了一個道理:隱藏復(fù)雜性并不會帶來簡單性,它只會產(chǎn)生更多的復(fù)雜性糕再。


歡迎工作一到五年的Java工程師朋友們加入Java技術(shù)交流:611481448

群內(nèi)提供免費(fèi)的Java架構(gòu)學(xué)習(xí)資料(里面有高可用量没、高并發(fā)、高性能及分布式突想、Jvm性能調(diào)優(yōu)殴蹄、Spring源碼,MyBatis猾担,Netty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多個知識點(diǎn)的架構(gòu)資料)合理利用自己每一分每一秒的時間來學(xué)習(xí)提升自己袭灯,不要再用"沒有時間“來掩飾自己思想上的懶惰!趁年輕绑嘹,使勁拼稽荧,給未來的自己一個交代!

Java 是負(fù)擔(dān)工腋,Node.js 充滿了樂趣

有些工具是設(shè)計(jì)師花費(fèi)數(shù)年磨礪和精煉的結(jié)果姨丈。他們嘗試不同的想法,去掉不必要的屬性擅腰,最終得到一個只帶有恰到好處屬性的工具蟋恬。這些工具的簡潔性甚至達(dá)到讓人感到驚艷的程度,但 Java 顯然不屬于這一類趁冈。

Spring 是一個非常流行的用于開發(fā) Java Web 應(yīng)用程序的框架歼争。Spring(特別是 Spring Boot)的核心目的是成為一個易于使用的預(yù)配置的 Java EE 棧。Spring 程序員不需要直接接觸 Servlet渗勘、數(shù)據(jù)持久化沐绒、應(yīng)用程序服務(wù)器就可以獲得一個完整的系統(tǒng)。Spring 框架負(fù)責(zé)處理所有這些細(xì)節(jié)旺坠,你只需要把精力放在業(yè)務(wù)編碼上乔遮。例如,JPA Repository 類為“findUserByFirstName”方法合成數(shù)據(jù)庫查詢——你不需要編寫任何查詢代碼取刃,只需按照特定方式給方法命名申眼,并添加到 Repository 中即可瞒津,Spring 將負(fù)責(zé)處理其余的部分。

這原本是一個偉大的故事括尸,一種很好的體驗(yàn)巷蚪,但其實(shí)并不然。

當(dāng)你遇到 Hibernate 的 PersistentObjectException 時濒翻,你知道是哪里出了問題嗎屁柏?你可能花了幾天時間才找到問題所在,導(dǎo)致這個異常的原因是發(fā)給 REST 端點(diǎn)的 JSON 消息里帶有 ID 字段有送。Hibernate 想要自己控制 ID 值淌喻,所以拋出了這個令人感到困惑的異常∪刚看裸删,這就是過度簡化所帶來的惡果。除了這個阵赠,還有其他成千上萬個同樣令人感到困惑的異常涯塔。在 Spring 棧中,一個子系統(tǒng)套著另一個子系統(tǒng)清蚀,它們坐等你犯錯匕荸,然后再拋出應(yīng)用程序崩潰異常來懲罰你。

然后枷邪,你會看到滿屏的堆棧跟蹤信息榛搔,里面滿是這樣那樣的抽象方法。面對這種級別的抽象东揣,顯然需要更多的邏輯才能找到你想要的內(nèi)容践惑。如此多的堆棧跟蹤信息不一定是不好的,但它也是在提醒我們:這在內(nèi)存和性能方面的開銷究竟有多大嘶卧?

而零代碼的“findUserByFirstName”方法又是如何被執(zhí)行的童本?Spring 框架必須解析方法名稱,猜測程序員的意圖脸候,構(gòu)造類似抽象語法樹的東西,生成一些 SQL 語句……那么完成這個過程需要多少開銷绑蔫?

在反反復(fù)復(fù)經(jīng)歷這樣的過程之后运沦,在花了大量時間學(xué)習(xí)你本不該學(xué)習(xí)的東西之后,你可能會得出相同的結(jié)論:隱藏復(fù)雜性并不會帶來簡單性配深,它只會產(chǎn)生更多的復(fù)雜性携添。

Node.js 是清流

Spring 和 Java EE 非常復(fù)雜,而 Node.js 卻是一股清流篓叶。首先是 Ryan Dahl 在核心 Node.js 平臺上所應(yīng)用的設(shè)計(jì)美學(xué)烈掠。他追求別樣的東西羞秤,花了數(shù)年時間磨練和改進(jìn)了一系列核心的 Node.js 設(shè)計(jì)理想,最終得到一個輕量級的單線程系統(tǒng)左敌。它巧妙地利用了 JavaScript 匿名函數(shù)進(jìn)行異步回調(diào)瘾蛋,成為一個實(shí)現(xiàn)了異步機(jī)制的運(yùn)行時庫。

然后是 JavaScript 語言本身矫限。JavaScript 程序員似乎更喜歡無樣板的代碼哺哼,這樣他們的意圖才能發(fā)揮作用。

我們可以通過實(shí)現(xiàn)監(jiān)聽器的例子來說明 Java 和 JavaScript 之間的差別叼风。在 Java 中取董,監(jiān)聽器需要實(shí)現(xiàn)抽象接口,還需要指定很多啰七八嗦的細(xì)節(jié)无宿。程序員的意圖的這些繁瑣的樣板中漸漸淹沒茵汰。

而在 JavaScript 中,可以使用最簡單的匿名函數(shù)——閉包孽鸡。你不需要實(shí)現(xiàn)什么抽象接口蹂午,只需要編寫所需的代碼,沒有多余的樣板梭灿。

大多數(shù)編程語言都試圖掩蓋程序員的意圖画侣,這讓理解代碼變得更加困難。

但在 Node.js 中有一點(diǎn)需要注意:回調(diào)地獄堡妒。

沒有完美的解決方案

在 JavaScript 中配乱,我們一直難以解決兩個與異步相關(guān)的問題。一個是 Node.js 中被稱為“回調(diào)地獄”的東西皮迟。我們很容易就掉入深層嵌套回調(diào)函數(shù)的陷阱搬泥,每個嵌套都會使代碼復(fù)雜化,讓錯誤和結(jié)果的處理變得更加困難伏尼。但 JavaScript 語言并沒有為程序員提供正確表達(dá)異步執(zhí)行的方式忿檩。

于是,出現(xiàn)了一些第三方庫爆阶,它們承諾可以簡化異步執(zhí)行燥透。這是另一個通過隱藏復(fù)雜性帶來更多復(fù)雜性的例子。

constasync=require(‘a(chǎn)sync’);constfs =require(‘fs’);constcat =function(filez, fini){async.eachSeries(filez,function(filenm, next){ fs.readFile(filenm, ‘utf8’,function(err, data){if(err)returnnext(err); process.stdout.write(data, ‘utf8’,function(err){if(err) next(err);elsenext(); }); }); },function(err){if(err) fini(err);elsefini(); });};cat(process.argv.slice(2),function(err){if(err)console.error(err.stack);});

這是個模仿 Unix cat 命令的例子辨图。async 庫非常適合用于簡化異步執(zhí)行順序班套,但同時也引入了一堆模板代碼,從而模糊了程序員的意圖故河。

這里實(shí)際上包含了一個循環(huán)吱韭,只是沒有使用循環(huán)語句和自然的循環(huán)結(jié)構(gòu)。此外鱼的,錯誤和結(jié)果的處理邏輯被放在了回調(diào)函數(shù)內(nèi)理盆。在 Node.js 采用 ES 2015 和 ES 2016 之前痘煤,我們只能做到這些。

Node.js 10.x 中猿规,等價的代碼是這樣的:

constfs =require(‘fs’).promises;asyncfunctioncat(filenmz){for(varfilenmoffilenmz) {letdata =awaitfs.readFile(filenm, ‘utf8’);awaitnewPromise((resolve, reject) =>{ process.stdout.write(data, ‘utf8’, (err) => {if(err) reject(err);elseresolve(); }); }); }}cat(process.argv.slice(2)).catch(err=>{console.error(err.stack); });

這段代碼使用 async/await 函數(shù)重寫了之前的邏輯衷快。雖然異步邏輯是一樣的,但這次使用了普通的循環(huán)結(jié)構(gòu)坎拐。錯誤和結(jié)果的處理也顯得很自然烦磁。這樣的代碼更容易閱讀,也更容易編碼哼勇,程序員的意圖也更容易被理解都伪。

唯一的瑕疵是 process.stdout.write 沒有提供 Promise 接口,因此用在異步函數(shù)中時需要丟 Promise 進(jìn)行包裝积担。

回調(diào)地獄問題并不是通過隱藏復(fù)雜性才得以解決的陨晶。相反,是語言和范式的演變解決了這個問題帝璧。通過使用 async 函數(shù)先誉,我們的代碼變得更加美觀。

通過明確定義的類型和接口提升清晰度

當(dāng)我還是 Java 的死忠時的烁,我堅(jiān)信嚴(yán)格的類型檢查對開發(fā)大型的應(yīng)用程序來說是有百利而無一害的褐耳。那個時候,微服務(wù)的概念還沒有出現(xiàn)渴庆,也沒有 Docker铃芦,人們開發(fā)的都是單體應(yīng)用。因?yàn)?Java 具有嚴(yán)格的類型檢查襟雷,所以 Java 編譯器可以幫你避免很多錯誤——也就是說可以防止你編譯錯誤的代碼刃滓。

相比之下,JavaScript 的類型是松散耸弄。程序員不確定他們收到的對象是什么類型咧虎,那么程序員怎么知道該怎么處理這個對象?

但是计呈,Java 的嚴(yán)格類型檢查同樣導(dǎo)致了大量樣板代碼砰诵。程序員經(jīng)常需要進(jìn)行類型轉(zhuǎn)換,或以其他方式確保一切都準(zhǔn)確無誤捌显。程序員需要花很時間確保類型是準(zhǔn)確的茁彭,所以使用更多的樣板代碼,希望通過及早捕獲和修復(fù)錯誤來節(jié)省時間苇瓣。

程序員不得不使用復(fù)雜的大型 IDE,僅僅使用簡單的編輯器是不行的偿乖。IDE 為 Java 程序員提供了一些下拉列表击罪,用于顯示類的可用字段哲嘲、描述方法的參數(shù),幫助他們構(gòu)建新的類和進(jìn)行重構(gòu)媳禁。

然后眠副,你還得使用 Maven……

在 JavaScript 中,不需要聲明變量的類型竣稽,所以通常不需要進(jìn)行類型轉(zhuǎn)換囱怕。因此,代碼更易于閱讀毫别,但可能會出現(xiàn)未編譯錯誤娃弓。

這一點(diǎn)會讓你更喜歡 Java 還是痛恨 Java,取決于你自己岛宦。十年前台丛,我認(rèn)為 Java 的類型系統(tǒng)值得我們花費(fèi)額外的時間,因?yàn)檫@樣可以獲得更多的確定性砾肺。但在今天挽霉,我認(rèn)為代價太大了,使用 JavaScript 會要簡單得多变汪。

使用易于測試的小模塊來掃除 bug

Node.js 鼓勵程序員將程序劃分為小單元侠坎,也就是模塊。模塊雖小裙盾,卻能從一定程度上解決剛剛提到的問題实胸。

一個模塊應(yīng)該具備以下特點(diǎn):

自包含——將相關(guān)代碼打包到一個單元中;

強(qiáng)壯的邊界——模塊內(nèi)部的代碼可以防止外部代碼入侵闷煤;

顯式導(dǎo)出——默認(rèn)情況下童芹,代碼和模塊中的數(shù)據(jù)不會導(dǎo)出,只將選定的函數(shù)和數(shù)據(jù)暴露給外部鲤拿;

顯式導(dǎo)入——聲明它們依賴哪些模塊假褪;

可能是獨(dú)立的——可以將模塊公開發(fā)布到 npm 存儲庫或其他私有存儲庫,方便在應(yīng)用程序之間共享近顷;

易于理解——更少的代碼意味著更容易理解模塊的用途生音;

易于測試——小模塊可以輕松進(jìn)行單元測試。

所有這些特點(diǎn)組合在一起窒升,讓 Node.js 模塊更容易測試缀遍,并具有明確定義的范圍。

人們對 JavaScript 的恐懼源自它缺乏嚴(yán)格的類型檢查饱须,所以可能很容易導(dǎo)致錯誤域醇。但在具有清晰邊界的模塊中,受影響代碼被限于模塊內(nèi)部。所以譬挚,大多數(shù)問題被安全地隱藏在模塊的邊界內(nèi)锅铅。

松散類型問題的另一個解決方案是進(jìn)行更多的測試。

你必須將節(jié)省下來的一部分時間(因?yàn)榫帉?JavaScript 代碼更容易)用在測試上减宣。你的測試用例必須捕獲編譯器可能捕獲的錯誤盐须。

對于那些想要在 JavaScript 中使用靜態(tài)檢查類型的人,可以考慮使用 TypeScript漆腌。我沒有使用 TypeScript贼邓,但聽說它很不錯。它與 JavaScript 兼容闷尿,同時提供了有用的類型檢查和其他特性塑径。

但我們的重點(diǎn)是 Node.js 和 JavaScript。

包管理

一想起 Maven 我就頭大悠砚。據(jù)說一個人要么愛它晓勇,要么鄙視它,沒有第三種選擇灌旧。

問題是绑咱,Java 生態(tài)系統(tǒng)中并沒有一個核心的包管理系統(tǒng)。Maven 和 Gradle 其實(shí)也很不錯枢泰,但它們并不像 Node.js 的包管理系統(tǒng)那樣有用描融、可用和強(qiáng)大。

在 Node.js 世界中衡蚂,有兩個優(yōu)秀的包管理系統(tǒng)窿克,首先是 npm 和 npm 存儲庫。

有了 npm毛甲,我們就相當(dāng)于有了一個很好的模式用來描述包依賴性年叮。依賴關(guān)系可以是嚴(yán)格的(指定具體的版本),或者使用通配符表示最新版本玻募。Node.js 社區(qū)已經(jīng)向 npm 存儲庫發(fā)布了數(shù)十萬個包只损。

不僅僅是 Node.js 工程師,前端工程師也可以使用 npm 存儲庫七咧。以前他們使用 Bower跃惫,現(xiàn)在 Bower 已被棄用,他們現(xiàn)在可以在 npm 存儲庫中找到所有可用的前端 JavaScript 庫艾栋。很多前端框架爆存,如 Vue.js CLI 和 Webpack,都是基于 Node.js 開發(fā)的蝗砾。

Node.js 的另一個包管理系統(tǒng)是 yarn先较,它也是從 npm 存儲庫中拉取包携冤,并使用與 npm 相同的配置文件。yarn 的主要優(yōu)點(diǎn)運(yùn)行得更快闲勺。

性能

曾幾何時噪叙,Java 和 JavaScript 都因?yàn)檫\(yùn)行速度慢而橫遭指責(zé)。

它們都需要通過編譯器將源代碼轉(zhuǎn)換為由虛擬機(jī)執(zhí)行的字節(jié)碼霉翔。虛擬機(jī)通常會進(jìn)一步將字節(jié)碼編譯為本地代碼,并使用各種優(yōu)化技術(shù)苞笨。

Java 和 JavaScript 都有很大的動機(jī)讓代碼運(yùn)行得更快债朵。在 Java 和 Node.js 中,動機(jī)就是讓服務(wù)器端代碼運(yùn)行得更快瀑凝。而在瀏覽器端序芦,動機(jī)是獲得更好的客戶端應(yīng)用程序性能。

甲骨文的 JDK 使用了 HotSpot粤咪,這是一個具有多種字節(jié)代碼編譯策略的超級虛擬機(jī)谚中。HotSpot 經(jīng)過高度優(yōu)化,可以生成非沉戎Γ快的代碼宪塔。

至于 JavaScript,我們不禁在想:我們怎么能期望在瀏覽器中運(yùn)行的 JavaScript 代碼能夠?qū)崿F(xiàn)復(fù)雜的應(yīng)用程序囊拜?基于瀏覽器 JavaScript 實(shí)現(xiàn)辦公文檔處理套件似乎是件不可能實(shí)現(xiàn)的事情某筐?是騾子是馬,拉出來溜溜就知道了冠跷。這篇文章是我用谷歌文檔寫的南誊,它性能非常好。瀏覽器端 JavaScript 的性能每年都在飛漲蜜托。

Node.js 直接受益于這一趨勢抄囚,因?yàn)樗褂玫氖?Chrome 的 V8 引擎。

下面是 Peter Marshall 的演講視頻鏈接橄务,他是谷歌的一名工程師幔托,主要負(fù)責(zé) V8 引擎的性能增強(qiáng)工作。他在視頻中描述了為什么 V8 引擎使用 Turbofan 虛擬機(jī)替換了 Crankshaft 虛擬機(jī)仪糖。

V8 引擎中的高性能 JavaScript:

https://youtu.be/YqOhBezMx1o

在機(jī)器學(xué)習(xí)領(lǐng)域柑司,數(shù)據(jù)科學(xué)家通常使用 R 語言或 Python,因?yàn)樗麄兪忠蕾嚳焖贁?shù)值計(jì)算锅劝。但由于各種原因攒驰,JavaScript 在這方面表現(xiàn)很差。不過故爵,有人正在開發(fā)一種用于數(shù)值計(jì)算的標(biāo)準(zhǔn) JavaScript 庫玻粪。

JavaScript 中的數(shù)值計(jì)算:

https://youtu.be/1ORaKEzlnys

另一個視頻演示了如何通過 TensorFlow.js 在 JavaScript 中使用 TensorFlow隅津。它提供了一個類似于 TensorFlow Python 的 API,可以導(dǎo)入預(yù)訓(xùn)練模型劲室。它運(yùn)行在瀏覽器中伦仍,可用于分析實(shí)時視頻,從中識別出經(jīng)過訓(xùn)練的對象很洋。

基于 JavaScript 的機(jī)器學(xué)習(xí):

https://youtu.be/YB-kfeNIPCE

在另一個演講視頻中充蓝,IBM 的 Chris Bailey 討論了 Node.js 的性能和可伸縮性問題,特別是在 Docker/Kubernetes 部署方面喉磁。他從一組基準(zhǔn)測試開始谓苟,演示了 Node.js 在 I/O 吞吐量、應(yīng)用程序啟動時間和內(nèi)存占用方面遠(yuǎn)遠(yuǎn)超過 Spring Boot协怒。此外涝焙,得益于 V8 引擎的改進(jìn),Node.js 每次發(fā)布的新版在性能方面都有顯著的提升孕暇。

Node.js 的性能和高度可伸縮的微服務(wù):

https://youtu.be/Fbhhc4jtGW4

在上面的這個視頻中仑撞,Bailey 說我們不應(yīng)該在 Node.js 中運(yùn)行計(jì)算密集型的代碼。因?yàn)?Node.js 采用了單線程模型妖滔,長時間運(yùn)行計(jì)算密集型任務(wù)會導(dǎo)致事件阻塞隧哮。

如果 JavaScript 的改進(jìn)還無法滿足你的應(yīng)用程序的要求,還有其他兩種方法可以將本地代碼直接集成到 Node.js 中座舍。最直接的方法是使用 Node.js 本地代碼模塊近迁。Node.js 工具鏈中包含了 node-gyp,可用于處理與本地代碼模塊的鏈接簸州。下面的視頻演示了如何集成 Rust 庫和 Node.js:

JavaScript 與 Rust 集成鉴竭,遠(yuǎn)比你想象得簡單:

https://youtu.be/Pfbw4YPrwf4

WebAssembly 可以將其他語言編譯為運(yùn)行速度非常快的 JavaScript 子集岸浑。WebAssembly 是一種可在 JavaScript 引擎內(nèi)運(yùn)行的可執(zhí)行代碼的可移植格式搏存。下面的視頻做了一個很好的概述,并演示了如何使用 WebAssembly 在 Node.js 中運(yùn)行代碼矢洲。

在 NodeJS 中使用 WebAssembly:

https://youtu.be/hYrg3GNn1As

富 Internet 應(yīng)用程序(RIA)

十年前璧眠,軟件行業(yè)一直熱議利用快速的 JavaScript 引擎實(shí)現(xiàn)富 Internet 應(yīng)用程序,從而取代桌面應(yīng)用程序读虏。

這個故事實(shí)際上在二十多年前就已經(jīng)開始了责静。Sun 公司和 Netscape 公司達(dá)成了共識,在 Netscape Navigator 中使用 Java 小程序(Applet)盖桥。

JavaScript 語言在某種程度上是作為 Java 小程序的腳本語言而開發(fā)出來的灾螃。服務(wù)器端有 Java Servlet,客戶端有 Java Applet揩徊,這樣就可以在兩端使用同樣的一門編程語言腰鬼。然而嵌赠,由于各種原因,這種美好的愿望并沒有實(shí)現(xiàn)熄赡。

十年前姜挺,JavaScript 開始變得足夠強(qiáng)大,可以實(shí)現(xiàn)復(fù)雜的應(yīng)用程序彼硫。因此炊豪,RIA 被認(rèn)為是 Java 客戶端應(yīng)用程序的終結(jié)者。

今天拧篮,我們開始看到 RIA 的想法得以實(shí)現(xiàn)溜在。服務(wù)器端的 Node.js 和兩端都有的 JavaScript 讓這一切成為可能。

當(dāng)然他托,Java 作為桌面應(yīng)用程序平臺的消亡并不是因?yàn)?JavaScript RIA,而是因?yàn)?Sun 公司忽視了客戶端技術(shù)仆葡。Sun 公司把注意力放在要求快速服務(wù)器端性能的企業(yè)客戶身上赏参。當(dāng)時我還在 Sun 公司任職,我親眼看著這件事情發(fā)生沿盅。真正殺死 Applet 的是幾年前在 Java 插件和 Java Web Start 中發(fā)現(xiàn)的一個安全漏洞。這個漏洞導(dǎo)致全球一致呼吁停止使用 Java Applet 和 Java Web Start 應(yīng)用程序腰涧。

我們?nèi)匀豢梢蚤_發(fā)其他類型的 Java 桌面應(yīng)用程序韧掩,NetBeans 和 Eclipse IDE 之間的競爭仍然存在。但是窖铡,Java 在這個領(lǐng)域工作是停滯不前的疗锐,除了開發(fā)工具之外,很少有基于 Java 的應(yīng)用程序费彼。

JavaFX 是個例外

10 年前滑臊,JavaFX 意欲成為 Sun 公司對 iPhone 的反擊。它用于開發(fā)基于 Java 的手機(jī) GUI 應(yīng)用程序箍铲,想把 Flash 和 iOS 應(yīng)用程序打垮雇卷。然而,這一切都沒有發(fā)生颠猴。JavaFX 現(xiàn)在仍然可以使用关划,但沒有了當(dāng)初的喧囂。

這個領(lǐng)域的所有興奮點(diǎn)都發(fā)生在 React翘瓮、Vue.js 和類似的框架上贮折,JavaScript 和 Node.js 在很大程度上要得益于此。

結(jié)論

現(xiàn)在资盅,開發(fā)服務(wù)器端應(yīng)用程序有很多選擇脱货。我們不再局限于“P”開頭的語言(Perl岛都、PHP、Python)和 Java振峻,我們還有 Node.js臼疫、Ruby、Haskell扣孟、Go烫堤、Rust 等等。

至于為什么我會轉(zhuǎn)向 Node.js凤价,很明顯鸽斟,我更喜歡在使用 Node.js 編程時的那種自由的感覺。Java 成了負(fù)擔(dān)利诺,而 Node.js 沒有這樣的負(fù)擔(dān)富蓄。如果我再次拿起 Java,那肯定是因?yàn)橛腥烁读隋X慢逾。

每個應(yīng)用程序都有其真實(shí)需求立倍。只是因?yàn)閭€人喜歡而一直使用 Node.js 也不見得是對的。在選擇一門語言或一個框架時總歸是有技術(shù)方面的考量的侣滩。例如口注,我最近完成的一些工作涉及 XBRL 文檔,由于最好的 XBRL 庫是用 Python 實(shí)現(xiàn)的君珠,所以就有必要學(xué)習(xí) Python寝志。

喜歡小編輕輕點(diǎn)個關(guān)注了哦!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末策添,一起剝皮案震驚了整個濱河市材部,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌唯竹,老刑警劉巖败富,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異摩窃,居然都是意外死亡兽叮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進(jìn)店門猾愿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鹦聪,“玉大人,你說我怎么就攤上這事蒂秘≡蟊荆” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵姻僧,是天一觀的道長规丽。 經(jīng)常有香客問我蒲牧,道長,這世上最難降的妖魔是什么赌莺? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任冰抢,我火速辦了婚禮,結(jié)果婚禮上艘狭,老公的妹妹穿的比我還像新娘挎扰。我一直安慰自己,他們只是感情好巢音,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布遵倦。 她就那樣靜靜地躺著,像睡著了一般官撼。 火紅的嫁衣襯著肌膚如雪梧躺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天傲绣,我揣著相機(jī)與錄音掠哥,去河邊找鬼。 笑死斜筐,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蛀缝。 我是一名探鬼主播,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼濒蒋!你這毒婦竟也來了扇调?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤在讶,失蹤者是張志新(化名)和其女友劉穎煞抬,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體构哺,經(jīng)...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡革答,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了曙强。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片残拐。...
    茶點(diǎn)故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碟嘴,靈堂內(nèi)的尸體忽然破棺而出溪食,到底是詐尸還是另有隱情,我是刑警寧澤娜扇,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布错沃,位于F島的核電站栅组,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏枢析。R本人自食惡果不足惜玉掸,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望登疗。 院中可真熱鬧排截,春花似錦、人聲如沸辐益。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽智政。三九已至认罩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間续捂,已是汗流浹背垦垂。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留牙瓢,地道東北人劫拗。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像矾克,于是被迫代替她去往敵國和親页慷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 作為一個在Sun微系統(tǒng)公司Java SE團(tuán)隊(duì)工作了十多年的人,難道不應(yīng)該是體內(nèi)流淌著Java字節(jié)碼的血控妻、只要一息尚...
    Java架構(gòu)學(xué)習(xí)者閱讀 2,559評論 4 17
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理州袒,服務(wù)發(fā)現(xiàn),斷路器弓候,智...
    卡卡羅2017閱讀 134,656評論 18 139
  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,810評論 6 342
  • 然而 我已經(jīng) 忘了 要寫的 內(nèi)容郎哭。 那么 晚安咯
    煎餅煎餅煎餅閱讀 197評論 0 1
  • 寒秋雁南歸 碧海云悠悠 翩翩攜君行 侃侃笑人生 盡曉凡塵事 深味世間情 子期若有意 徒有羨吾情 若問何能爾 君若芝...
    平語心聲閱讀 83評論 0 0