為什麼Java正在死去? - Komal

發表於2020-12-22

微服務無所不在的浪潮席捲了我們:

  • 易於擴充套件
  • 高可用性
  • 無需擔心併發和多執行緒的簡化程式碼庫
  • 集裝箱化帶來了可移植性

所有這些因素促使我們質疑Java(更具體地說是JVM)的功效,更不用說Java最臭名昭著的框架Spring了。

有時,人們沉浸在諸如Kubernetes這樣的技術中,感覺Java的時代已經過去,Java在容器和微服務生態系統中的表現還不理想(這是軟體可擴充套件性和高可用性的關鍵)。但是,作為曾經堅定支援Java的人-儘管一直受到Python等語言(現在已經成為我的首選語言)的簡單性和優雅的影響,但我仍然繼續為Java不可否認的某些領域保留一席之地優點。

例如,我很清楚Java的強大執行緒功能,在我的職業生涯早期就將它們直接用於關鍵銀行應用程式。雖然將編譯語言的效能指標與指令碼語言的效能指標進行比較是不公平的,但Java堅如磐石的效能卻是無與倫比的。

但是在水平可伸縮性和微服務體系結構的世界中,語言本身固有的高效能不重要了,因為人們可以簡單地產生更多的容器worker來獲得出色的效能。Python等指令碼語言可以在容器領域中即時放大或縮小,效能相比Java已經毫不遜色了。

我完全地確信Java已經完成了使命(至少在微服務領域如此)。在我的新工作中,這些信念僅得到進一步加強,我痛苦地意識到Java語言變得多麼令人討厭,煩躁和令人費解:部分原因是由於Spring等過時的儀式框架。

 

Java和Spring的儀式

讓我們從臭名昭著的Spring框架開始。

與五年前相比,Spring是如此龐大且令人費解,充斥著無窮無盡的註釋,這些註釋使開發人員在每次需要完成工作時都只能依靠教程或示例程式碼。仔細閱讀Spring自己的詳盡文件既可能是艱鉅的任務。

實際上,我最喜歡的是像Spring這樣的框架,而不是Java本身。Spring採用了一種已經很禮貌的語言,用單行註釋和看似簡化的包裝器對其進行掩蓋,從而加劇了這個問題,這些包裝器最終召喚出了您通常不需要的類的呼叫和例項化的狂歡。正如任何開發人員都會同意的那樣,語言的控制,命令和透明性對於有效的軟體開發至關重要。簡而言之,作為一名開發人員,您想準確地瞭解程式碼中發生了什麼以及執行了哪些例程-至少是在較高層次上。但是Spring在這方面痛苦地阻止了您。

如果您必須在類的頂部放置六個註釋,而每個註釋都在做自己的事情,並且在Spring上下文的網格中錯綜複雜地相互聯絡,那麼您將處於一片模糊的境地。這不僅是Spring是這樣。

以Lombok庫為例。這是其首頁上宣傳的:

“ Project Lombok是一個Java庫,它會自動插入您的編輯器和構建工具中,從而為您的Java增光添彩。永遠不要再編寫另一個getter或equals方法,帶有一個註釋的類將具有功能齊全的生成器,自動執行日誌記錄變數等等。”

壓縮Java程式碼令人沮喪,並且需要痛苦地面對這種壓縮了的語言工作,這種方式帶來不了任何好處。

Java應該簡單地停止嘗試與指令碼語言的簡潔性相匹配。首先,這犧牲了Java程式碼的一致性:想象回到Java只是發現所有的getter和setter都消失了(根據我們曾經學過的知識這些屬性方法對於Spring autowire自動裝配很重要),現在已被單行註釋替換@NoArgsConstructor。邏輯上的一致性在哪裡?

其次,它增加了已經令人費解的抽象陣列。例如,在這裡,Spring可以在後臺設定自動裝配(bean注入),這是可以理解的,但是Lombok在應用程式上下文中位於何處,以及如何在兩者之間協調訊息傳遞?

如果我的每個類都有六個註釋,那麼這些註釋還例項化了多少其他例程或類來完成這一簡化的工作?沒有真正的開發人員會希望將所有這些額外的程式碼潛伏在角落。可悲的是,這是三年後我遇到的那種Java程式碼。沒有一件事情發生改變。實際上,即使發生的微小變化也只會使情況變得更糟。

 

Java仍將重點放在愚蠢的規則上,這些規則規定了應使用的類名稱,應使用的包以及變數是私有的還是受保護的。說真的,誰在乎?

相反,“我們都是成年人”實際上是Python對語言中缺少訪問說明符的官方回應。這種嘲諷而引人入勝的單行回應立刻引起了我的共鳴。最終,它使我經常覺得是荒謬且不必要的概念更為理智。

 

保持簡單,愚蠢

如果您在軟體行業中不停地聽到一件事,那就是KISS的首字母縮寫:保持簡單,愚蠢。如果Java要生存,這是需要認真考慮的事情。

如今,微服務模式已在軟體行業中幾乎普及。甚至許多執行舊版應用程式的組織也越來越多地替換其舊的整體,以簡化設計並提高可伸縮性。對於程式設計師而言,這意味著將其龐大的程式碼庫或複雜的業務邏輯分解為更簡單,簡潔的功能-一種無需在程式碼中進行狀態管理的範例,從而免除了併發問題和多執行緒噩夢。

歸根結底,所有服務,無論是某種形式或形式,都只處理某種格式(JSON或XML)的資料,然後將它們傳遞到諸如Kafka的訊息匯流排上以進行進一步處理。甚至在一個可笑的簡單的設定像這樣,Java和Spring繼續秉承其隆重程式碼語法以及倒退到不合時宜的修辭。Application Contexts、錯綜複雜bean injections、autowiring、 POJO mappers、消耗記憶體JVM和臭名昭著的class loader-所有這些都是毫無意義的痛苦來處理。

黑客新聞討論

我是一個刻板的Java開發人員,即使我過去使用過許多其他語言。我認為作者錯過了Java設計的重點。當您需要良好的效能而不是絕對的最佳效能時,它應該是更友好,更安全,更通用的C ++。因此,我認為這是最好的選擇。

總的來說,這篇文章是來自那些從未使用過Java或只做過一些Spring教程,對語言的複雜性感到沮喪並轉向其他內容的開發人員的普遍抱怨。

Java是最快的流行語言之一,JVM是一個很棒的執行時,而不是臃腫腫的執行時。看看V8有多龐大,與Java相比,JS標準庫仍然是垃圾。JVM可能是目前最好的執行時,這也是Java為什麼如此流行的很大一部分。

JVM具有強大而快速的FFI,配置檔案,指標,多個世界一流的GC,它非常穩定,它可以毫無問題地處理帶有數百兆程式碼的專案。

 

不是Java語言本身搞砸了,而是框架和庫中註釋的大量使用,使構建應用程式一次寫入就永遠無法除錯問題。當您在不熟悉的現有程式碼庫上開始工作時,真正的問題就開始了。對Spring的深入瞭解是即使是很小的工作的絕對要求。

 

我認為Java中的許多“最佳實踐”,尤其是那些來自“有效Java”的實踐,對於大多數開發人員來說都是偏執狂,只會製造出比他們解決的問題更多的問題。

 

像Java那樣死勝於像Rust那樣活著,雖然我不喜歡典型的Java框架的複雜性,並且由於這個原因七年來沒有做過任何Java,但稱Java死了是因為“每個人都在使用微服務”以及“當您可以執行更多程式碼容器worker時為什麼要為效能而煩惱”有點荒謬。因為在高流量服務上使用Python,因此部署的計算機數量要多出3倍。

 

我的公司有一個龐大的,過度設計的整體,我們將其分解為更明智的微服務,並且該架構現在更清潔,更易於維護,擴充套件等。不過,我同意,預先設計微服務通常是過早的優化,因為您最初對服務之間的界限放在何處的猜測很可能是錯誤的。

整體和微服務都是使用Spring Boot用Java編寫的,但是我同意作者的觀點,即Spring特別導致執行時程式碼,這對於開發人員來說是很難真正理解的。我很好奇,從長遠來看,用Go之類的語言編寫未來的微服務是否會更可維護。

 

我不同意Go是Java Microservices的良好替代品。我建議您研究一下Quarkus(https://quarkus.io)之類的東西,如果Java對某人來說很冗長,她/他可以使用Kotlin(https://kotlinlang.org),它可以與Java 100%互操作但乾淨,現代,務實。使用Quarkus,您有一個非常強大但簡單的框架,如果您需要非常快速的啟動和非常低的記憶體消耗,則可以將其開箱即用(GraalVM)編譯為單個二進位制檔案。

Go宣揚了簡單性,但是當有人必須在更大的專案中使用它時,就會很麻煩。您沒有任何函式性的程式設計功能,例如過濾器,對映,查詢來操縱集合。非null(nil)安全性或帶介面的魔術{}確實使它變得不安全,特別是與Kotlin,Swift等現代語言相比,這種語言本身就具有可空性的概念。依賴注入支援非常有限。我認為Go是被炒作的,如上所述,您今天通過GraalVM以及Java,Kotlin也具有出色的單一二進位制功能。

 

如果您不喜歡Spring,請不要使用Spring!

如果您不喜歡註釋,則不要使用註釋!

然後,您無需撰寫煽動性的頭條新聞...

 

Spring是完全不能容忍的。如果註釋錯誤,則根本無法除錯該過程。我急切地尋找能夠深入瞭解在執行時autowire了哪些物件的工具。

 

用偵錯程式觀察執行時行為很簡單。如果建議使用建構函式注入,則只需在建構函式中新增一個斷點,然後在偵錯程式中啟動應用程式即可。

 

對於他所說的關於Spring的一切表示同意,但感到驚訝的是他主張使用Python作為替代方案,而不是Go。在微服務環境中,它似乎是Java的更直接替代。比Python效能更高,易於部署,並提供了大量的靜態型別檢查。

 

我已經用Java編寫了很多微服務,並且最近開始使用非常相似的體系結構(但是使用Go)啟動了一個新專案。

我有機會反省了我對Go的滿意之處以及Java遺漏的內容。

  • *由於很多原因,我都不喜歡Java語言,儘管兩者都不是完美的。
  • *我非常喜歡使用二進位制而不是位元組碼物件,因此Go在這裡要好得多。
  • * JVM是與程式碼關聯的非常大的執行時,並且啟動時間仍比Go(或一年前)更長。這會使Java CLI工具變慢,並且出色的CLI可以幫助製作出出色的產品。
  • *我更喜歡Go的標準庫方法;易於使用的生產就緒“傻瓜”實現,而不是抽象的“引用”實現。
  • *我特別不喜歡Go使用大寫形式將欄位和變數標記為公共,因為我發現型別和變數名稱之間的衝突確實很常見。
  • * Go的“慣用”實踐比Java聰明得多。我已經停止使用Java中的getter和setter方法,並放棄了其他一些抽象的“最佳實踐”(工廠工廠!所以我想我不太喜歡慣用的Java。我感到自己並不孤單。
  • *總的來說,我喜歡Go的感覺,就像它是Unix工具一樣,在Java中,Java總是感覺像他們在試圖重寫世界。考慮到Java的來源,這種方法對我來說總是很奇怪。
  • *我真的很討厭Java中的“框架中的一切”方法,並在幾年前放棄了它。特別是Java EE,Wildfly,Spring,JPA等。它們都增加了巨大的重量和複雜性,而沒有實現任何實質性的收益。並不是一定要這樣,而且我認為情況正在改善,但是有許多Java庫只是非常複雜和抽象,沒有充分的理由。

因此對於我的用例來說,Go顯然是正確的選擇,但是在Go中工作12個月後,我對Java語言有很多想念的地方。我對Java AOT的東西寄予了很高的期望,但它似乎停滯了(也許我錯過了一些東西)。

 

 

相關文章