我是前 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)注了哦!