編譯|宇琪
策劃 | Tina
Rod Johnson 又回到了一線。
他是 Spring 的創造者,曾經幾乎重新定義了企業 Java 應用該怎麼寫。二十多年後,他重新創業,做了一個面向企業 AI Agent 的開源框架 Embabel,試圖把 LLM 放進真實的業務系統裡,讓它不只是會調用工具,而是能在可控、可解釋、可審計的流程裡工作。
有意思的是,這一次他做的仍然是框架,但他對「框架」的未來並不樂觀,至少不再是過去那種樂觀。在他看來,模型還會繼續變強,工具也會越來越多地替開發者做選擇。Embabel 會不會被更強的模型追上?企業還需不需要這樣一層 harness?未來的框架到底是由開發者挑選,還是由 AI 工具自動決定?這些問題,都離不開他在訪談裡說出的那句話:這可能是最後一波由人類親自選擇的框架。
這句話放在別人嘴裡,可能只是又一次 AI 時代的誇張判斷。但從 Spring 創始人口中說出來,意味就不一樣了。因為 Rod Johnson 親手參與過框架時代的興起,也見過一個框架如何變成企業軟體開發的基礎設施。現在,他回到戰場,卻認為選擇權正在轉移:開發者未必會消失,但開發者親自挑框架、搭技術棧、決定系統骨架的時代,可能正在進入尾聲。
本文基於該 Podcast 影片整理,經 InfoQ 編輯。
核心觀點如下:
如果我要用 TensorFlow 做模型訓練、微調、某些資料處理和攝取,我當然會用 Python。但 GenAI 應用層賦能這件事,更適合在應用原本的語言裡完成,如果應用是用 Java 寫的,那就在 Java 裡完成。
一旦你進入複雜的應用程式,如果你不保持那種架構上的監督,你很快就會陷入一團亂麻。你的 Agent 會愉快地添加新功能,但每添加一個新功能,設計就會退化,程式碼就會變得非常糟糕。
開發者不應該花大量時間在編寫程式碼上,因為你可以透過專注於你獨特增加價值的地方來獲得更大的槓桿。
每個開發者原則上都應該每隔一兩年學一門新語言,因為它真的會改變你的思維方式。
這可能已經是「最後一代由人類主動選擇的框架」了。以後越來越多的技術選型,都會由我們的工具替我們完成。
Spring 創始人回歸一線創業
Simon: 我翻你的履歷時發現,你在創建 Spring 之前,擁有一個關於 19 世紀巴黎鋼琴音樂的博士學位。
Rod: 是的,我的第一個學位是音樂和電腦科學雙主修,當時完全沒辦法決定往哪個方向走。後來我拿到了澳洲的研究獎學金去讀音樂博士,還在雪梨音樂學院教過兩年音樂史。然而,寫程式的衝動一直沒停過。90 年代中期我還寫過共享軟體,真有人寄支票過來。
後來我清醒地認識到,要是繼續待在音樂學術界,我大概一輩子在雪梨都買不起房。於是我做了一個決定:這兩件事裡,一個當愛好,一個當職業——而我當時正好搞反了。不過接下來有十年我幾乎沒碰過鋼琴,因為職業生涯實在太忙了。
Simon: 所以這並非什麼奇怪的彎路或別的什麼,只是碰巧你很有創造力,無論是寫程式還是音樂,你都很享受這兩者。
Rod: 從 80 年代中期第一次寫程式到現在,我差不多從未中斷過程式設計,因為我就愛這件事。即便現在絕大部分程式碼是由 AI Coding Agent 替我寫的,我仍然能獲得一模一樣的興奮感,因為掌控權還在我手裡,我還在創造和塑造東西。哪怕不再親手敲出每一行,只要結果是相同的,這對我而言同樣令人滿足。
Simon:在 SpringSource 被收購後,你做了很多年董事會和投資的事情,然後創辦了 Embabel,是什麼讓你覺得「就是現在,這個時機到了」?
Rod: 我認為是因為產業正處在一個巨大的轉折點上。當 GPT-3 和後來的 ChatGPT 突然變得真正實用、不再重複自己或陷入奇怪的死胡同時,我立刻意識到,怎麼把這項技術真正用來解決企業問題,是很難的問題。其實在這之前兩年,出於個人興趣,我已經寫了不少 TensorFlow 程式碼,和底層 AI 技術打了很多交道。這自然而然地演化成了創建一個框架來幫助解決這些問題的想法。
Simon:說到企業,現在很多團隊被要求拋下 Java,用 Python 重寫一切。你公開講過這是錯誤的,甚至說過「這是 Python 在 AI 領域主導的最後一年」,為什麼?
Rod: 你要解決一個業務問題,就必須考慮這個問題本身的「鄰接性」。你在和什麼打交道?你大概率和資料庫、企業服務、現有程式碼庫打交道。同時,你還要處理一個新東西:LLM。可 LLM 並不在你那個 Python 程序裡執行——宇宙毀滅之前,Python 都沒辦法自己執行推理。LLM 只是一個非常簡單的 HTTP 調用,所以我一直很困惑,為什麼人們會認為某門語言在發起一個極其簡單的 HTTP 調用時會有天然優勢。
事實上,大家已經開始逐漸意識到這一點了。OpenClaw 就不是用 Python 寫的,Peter Steinberger 用的是他偏愛的語言。對大量企業應用而言,它們很明顯是用 Java 寫的,關鍵的鄰接性就在於既有業務邏輯、既有企業服務。那正確的做法很顯然,就是從你的 Java 堆疊裡發起一個簡單的 HTTP 調用。
我認為人們產生這種混淆的根本原因,是沒有把「資料科學」和「企業 AI 應用」區分開,它們是兩件完全不同的事。在 Embabel 之前我寫了大量 Python,兩年前我的 Python 甚至比 Java 流利得多。如果我要用 TensorFlow 做模型訓練、微調、某些資料處理和攝取,我當然會用 Python。但 GenAI 應用層賦能這件事,更適合在應用原本的語言裡完成,如果應用是用 Java 寫的,那就在 Java 裡完成。
Simon:Embable 是用 Kotlin 寫的,對吧?
Rod: Embabel 核心幾乎全部是用 Kotlin 寫的。但我們的大多數示例是 Java。我們投入了大量精力來確保對 Java 用戶來說,它是完全無縫的——正如你預期的那樣,我們絕大多數用戶群都在用 Java。你不會看到 companion object、`.kt` 檔案,不會看到任何奇怪的東西。它就像非常優雅、流暢的 Java。所以當我在核心框架上工作時,我用 Kotlin;當我在示例應用上工作時,我用 Java。老實說,Java 風格的 API 非常棒,即使在 Kotlin 裡使用這個框架時,它和其他語言的體驗也差不多。
Simon: 而且它們之間的集成本來就很無縫,你可以直接從 Kotlin 跳到 Java。
Rod: 大概十三年前,我大量使用過 Scala。我很喜歡 Scala 這門語言,但事實是它與 Java 的集成很痛苦。每次你處理一個集合,那都是折磨。而 Kotlin 的創造者在 Java 互操作性方面做得非常出色,他們沒有引入 Scala 曾有的那些問題,破壞性變更、缺乏二進制相容性等等。所以,是的,我覺得 Kotlin 是一門非常好用的語言。
不過,我也認為指出 Java 已經改進很多這件事很重要,我覺得人們喜歡拿 Java 當稻草人來攻擊很煩人。很多人假裝 Java 沒有進化,而 Java 實際上已經進化了很多。
Coding Agent 正在毀掉你的程式碼庫
Simon:你之前談到 AI 基本上是被當作一個斷開的層硬塞進去的,而不是更深入地整合到現有系統中,結果這導致了一些失敗案例。你認為真正的企業 AI 失敗案例是什麼樣的?
Rod: 我認為最大的問題就出在,當高層下達「AI 一切」的指令,團隊卻在沒有真正業務案例、沒有確認 AI 是否合適的情況下,盲目開展 AI 專案。一個主要的反模式就是「我們必須用更多 AI」這種念頭,卻從來不去問一句:為什麼要用?用來幹什麼?雖然我非常熱愛並且著迷於 AI,但如果能不用 LLM 就完成一件事,那你當然應該不用 LLM,這樣更便宜、更確定、更快。
所以組織首先要做的,是思考「我們怎麼從這兒走到那兒去」。舉個例子,我們在澳洲的一個客戶,他們一開始識別出一類小問題:網站上有某張特定表單,客戶填寫完後需要人工審核才能繼續。95% 的情況其實非常簡單,雖然用正規表達式處理起來稍微麻煩了點,但本質上很簡單。於是他們把這個摩擦點消除掉了,在 95% 的場景裡讓客戶即時推進,不再需要等人工處理。我覺得這是非常棒的起步案例:先在小事上拿到結果,慢慢建立起信任。
另外,對於「異質技術堆疊」問題,它會在兩個方向上造成傷害。第一,技術上讓一切都變難;第二,它往往還會把戰略權交到錯誤的人手裡——那些根本不懂核心業務、可能從來沒見過任何核心業務應用的人,卻在主導戰略。當你要賦能這些應用的時候,這條路完全走不通。
去年我和一家澳洲大公司的首席 AI 架構師聊過,他是一名 Python 開發者。他禮貌地聽完了我的介紹,卻沒什麼興趣。通話結束時,他試圖表現得友善一點,說:「我敢肯定我們公司什麼地方有 Java,我回去問問看。」我從來沒在那家公司工作過,但作為業內人士我太清楚了,那家公司大約 70% 的程式碼是 Java 寫的,剩下的是 .NET,而且他們正逐步淘汰 .NET。這個人入職將近一年了,卻從來沒想過要去問一句:「順便問一下,我們的軟體是用什麼語言寫的?」對他來說,這似乎根本不重要。
Simon:現在有一種越來越普遍的現象,我們作為開發者,與實際編寫的程式碼實現之間出現了巨大的脫節。因為我們對 AI 過度依賴或授權,讓 AI 做了太多決策,把太多東西都外包出去了。很多知識實際上在 AI 那邊,而我們卻被抽象掉了。你認為這個問題有多嚴重?
Rod: 我認為開發者需要掌握的一項核心技能,就是以這種新方式工作,同時保留那些真正重要的控制權。確實可以用 Vibe Coding 來做一些事情,比如某些類型的 UI 應用,它們本來就是一次性的,Agent 在這方面非常非常擅長。但你無法用 Vibe Coding 來編寫嚴肅的軟體。
我是一個 Coding Agent 的積極用戶,我可能最多只寫 5% 的程式碼,也許更少,但我牢牢掌握著控制權。我發現,從設計的角度來看,Agent 出錯的時候比正確的時候多。
我們仍然需要理解架構、清楚正在發生什麼、並且不要過於信任。因為一旦你進入複雜的應用程式,如果你不保持那種架構上的監督,你很快就會陷入一團亂麻。你的 Agent 會愉快地添加新功能,但每添加一個新功能,設計就會退化,程式碼就會變得非常糟糕。
Simon:你提到你只寫 5% 的程式碼,其餘是 AI 生成的。你這樣做是有意為之嗎?是因為你不想寫更多,因為你想對寫出來的東西有更多控制權?
Rod: 在開源專案裡,我手寫的比例更高一些,可能會更保守。但在我們的一些內部應用中,AI 生成的比例接近 95%。要是你讀那些程式碼,你會覺得那是我寫的,設計風格非常清晰。我會坐在那裡看 diff、看輸出,然後經常停下來糾正它:「不對,你把這個硬編碼了,這裡應該是一個策略,提取出來。」
我相信這種模式有可能產生比純手工或者純靠 Coding Agent 更好的結果。我用 Coding Agent 寫程式碼的速度比我手動快得多,而且品質也更好。但如果反過來,我把一切完全丟給 Coding Agent,我深信品質會大幅下降,最終連速度也會降下來。
Embabel 的核心:來自一個遊戲 NPC 規劃演算法
Simon:我們來談談 Embabel 裡面的核心元件「規劃器」。這是一個叫 GOAP(Goal-Oriented-Action-Planning)的尋路演算法,最早是為遊戲裡的 NPC 設計的吧?關鍵點是,它是確定性的。而其他框架比如 LangChain、Crew.ai,則更多是由 LLM 來決定下一步做什麼、怎麼規劃。為什麼你會從遊戲 NPC 領域裡挑出這個演算法?
Rod: 我最開始考慮的確實是最顯而易見的方法——狀態機。平心而論,LangGraph 就是確定性的,你提前定義好狀態機。所以我也一度用過那種辦法。不過我們先退一步,談談為什麼要做規劃。
當然,你可以直接把一堆工具丟給模型,讓一個 Agent 循環來全權處理一切,在某些場景下這確實合理。但對於自動化業務流程這類需要一致性和可預測性的場合,這遠遠不夠,因為你壓根不知道 LLM 會以什麼順序調用你給它的工具,也不知道它會傳什麼參數給那些工具。
所以我們的想法是,讓用戶把流程拆成多個步驟。這些步驟可能是調用一個或多個 LLM,也可能是純程式碼步驟。在這一層面上,LangGraph、Crew.ai、Microsoft Semantic Kernel 做的都是類似的事——把大問題切分成小步驟。這也意味著,如果你在某一步中使用 LLM,可以為不同需求使用不同模型。比如你可以在自己的防火牆後面使用本地 LLM 來處理那些足夠小、且高度敏感的任務,從而永遠不讓客戶資料流出企業邊界,這裡面有大量好處。
但問題回到了:怎麼規劃這些步驟,怎麼決定執行順序?你可以用狀態機,但我發現,當我在做類似 LangGraph 的東西時,修改狀態機,比如增加更多狀態和轉換,非常麻煩,你必須重新連線來擴展它。其次,狀態轉換和每個動作狀態所需的類型,通常都是正交的,這會在類型系統上製造麻煩。
GOAP 規劃方式有兩個很不一樣的點。第一,它是動態的,規劃發生在執行時。第二,它與類型系統完全集成。我們允許用戶創建自定義條件,但動作的排序通常由 Java 方法的參數類型和返回類型決定,這意味著一個動作永遠不會在缺少所需參數時被調用。
GOAP 本質上是一個 A* 演算法。我們識別出目標,然後查看從當前世界狀態出發,哪些步驟可以通向目標。目標有前置條件,世界狀態中必須滿足某些條件。動作也有前置條件和它承諾的後置條件。前置條件是絕對硬性的,除非條件被滿足,否則你不能聲明目標已達成,也不能調用某個動作,而後置條件則是動作承諾會產生的副作用。
規劃器從當前世界狀態出發,找到一條通往目標的路徑。它也可能告訴你「不存在可行動路徑」,這本身就是一個很有價值的資訊。然後它執行第一個動作,再重新規劃,在執行每個動作之後,查看世界狀態,重新評估怎麼到達目標。大多數情況下,快樂路徑會照常運作,動作承諾的後置條件得到滿足,規劃器確認一下,然後邁進下一步。
Simon:這一切都是自動化的?
Rod: 完全自動化。通常 Java 開發者不需要了解規劃器的內部細節,他們只需要定義「動作方法」來提供輸入,用註解標記 Java 方法,方法的參數和返回類型就給規劃器提供了鏈式調用的資訊。在某些情況下,你還可以定義自定義條件來進一步控制工作流。這意味著可能存在多條路徑能到達同一個目標,而規劃器可以選擇成本最低的那條路徑,因為你可以給每個動作分配成本。成本甚至可以是動態的,如果某個動作需要調用一個負載很高的系統,你就可以將其反映為一個動態成本值,這樣一來,規劃器也許就會自動選擇另一條路線。
Simon:基於當前世界狀態在執行時做動態決策,這非常有意思。另一個好處是,因為它是確定性的,當被問到「為什麼會做出這個決定」時,你們能提供非確定性規劃器無法給到的診斷資訊?
Rod: 我們可以完整展示規劃的整條路徑,以及我們觀察到的世界狀態,是如何導致我們制定出那份計畫的。規劃器和整個 Embabel 會發出大量事件,你可以編寫監聽器來持久化這些資訊,或者把它們用於審計日誌。所以你完全可以解釋它為什麼做了某件事,並且確保它每次都做同樣的事。
當然,一旦進入動作步驟內部,如果你調用了 LLM,那部分就不會是完全確定性的,但這也讓你能夠「適度」地調用 LLM。如果你像聊天機器人那樣,用長達三頁紙的提示詞和 30 個工具來工作,你永遠不可能獲得完全的可預測性。而如果你用一段小提示詞加上三個工具去完成一件事,可預測性就會非常高。雖然不可能 100% 確定,但你會發現花在提示工程上的時間會大幅減少。所以整體上,系統會變得可解釋得多,也確定和可預測得多。
為什麼對 MCP 持懷疑態度
Simon:每個人似乎都把 MCP 當作萬靈丹,好像它能解決 Agent 的所有問題。你認為在這個領域,大多數開發者還沒有看到的差距是什麼?
Rod: 我認為 MCP 在賦能整個生態系統方面發揮了極其重要的作用,它確實是一個催化劑,讓更多的人了解到你可以用工具實現什麼。然而,我出於幾個原因對 MCP 持懷疑態度。
首先,如果你在做「用 AI 賦能企業系統」這件事,為什麼要透過 MCP 來執行?你可以用 Embabel、Spring AI 或 LangChain4J,任何框架都可以輕鬆地將一個 Java 方法暴露為工具。所以你必須問一個問題:如果做起來這麼容易,為什麼還要多此一舉?特別是當你可以在領域物件上暴露工具時,你先透過倉庫調用檢索到了正確的領域物件,然後暴露這個物件上的方法,這是 MCP 不那麼容易做到的事。所以,很多時候,你在暴露任何工具時,第一個想法應該是:「我能用我的技術堆疊直接暴露它。」「我為什麼不直接暴露一個 Java 方法或 Python 函式呢?」完全可以做到。
其次,MCP 的賣點是「一個專門為 Agent 設計的 API 規範」。但如果它是 API 規範,我們已經有了 OpenAPI、Swagger、GraphQL,為什麼還需要一個新的?MCP 的論點是「因為它是專門為 Agent 設計的」。但我最近開始得出一個結論:對於一個特定 Agent 來說,唯一完美適合的東西,很可能就是這個 Agent 獨有的。比如,你可以有一個 MCP 伺服器去暴露服務,但如果已經存在一個 OpenAPI 規範,你也可以連接到那個規範,然後根據你特定 Agent 循環的需求來塑造你自己的工具。
我認為 MCP 對推動產業進步有巨大貢獻,但它不是那種一刀切的解決方案。在很多場景下,直接使用現有的 API 規範更有意義,而永遠放在首位的方案應該是:從你當前的技術堆疊裡直接暴露邏輯。
Simon:我記得 Karpathy 發過一條推文,大意是模型正在跑在基於模型構建出來的產品前面。現在你在 Embabel 構建的是編排層。這是否意味著,你們其實已經落後於模型了?
Rod: 這是一個有意思的問題。當然,如果你看我們現在如何構建軟體,coding agent 的規劃能力提升得比我原本預期要明顯得多。大概在去年 11 月底、12 月那段時間,確實出現過一次非常劇烈的躍遷。我認為模型肯定在變得更好,但我也認為,很多根本問題仍然存在。如果你在自動化業務流程,那麼把規劃從模型的控制之外移出來,轉而使用某種確定性方法,我認為這仍然有價值。可解釋性依然很重要。所以我確實認為,即使模型繼續進步,模型之上的框架、agent harness、各種框架仍然非常重要。
一個很好的例子是 Claude Code。當然,Sonnet 4.6 比之前的模型強得多。但 Claude Code 本身也強得多。如果你把今天的 Claude Code 和四五個月前的 Claude Code 相比,它的工作方式已經完全不同,而這種不同確實讓它更有效。所以我其實並不認為模型變聰明和 harness 變聰明之間存在衝突。我認為我們需要在兩個地方同時推進。
我認為你確實會看到一些模型「吃掉 harness」的場景,也就是在那些是否確定並不那麼重要的地方。你可以直接給模型一堆工具,即使它有點不可預測也沒關係。所以我確實認為,有一塊空間裡,模型會需要更少的外圍基礎設施。但我認為,那塊空間與企業應用並沒有特別大的關係。
AI 擅長批評,不擅長原創
Simon:今年一月,你提到你的 Claude Code 工作流程涉及很多設計對話:和 Claude Code 來回討論、長時間的規劃,然後才開始編碼,結果往往比手寫更好。但 Claude 並不理解某些事情,比如 companion objects。所以當你用 Claude Code 構建 Embabel 而 Claude 不完全理解你架構的某些部分時,那種感覺如何?
Rod: 我認為它工作得很好,因為我完全理解架構,並且我經常糾正它。我確實想知道,如果開發者越來越多地選擇「不理解架構」那條簡單的路,會發生什麼。我處於一個非常有利的位置,我完全理解程式碼庫中的架構,我非常了解 Kotlin 這門語言,我們構建在 Spring 之上,我對 Spring 也很了解。我實際上非常了解技術堆疊的每一個部分,這使我能夠有效地掌控局面。我個人會非常擔心那些不理解這些的人,保持控制權非常重要。我認為開發者不應該花大量時間在編寫程式碼上,因為你可以透過專注於你獨特增加價值的地方來獲得更大的槓桿。
Simon:AI 有沒有讓你感到驚訝的時候,比如給過一個你沒想到的設計或架構建議,讓你轉向了完全不同的方向?
Rod: 不經常。然而,有一件事一直很有用,那就是來回的討論。確實有很多次它想到了我沒想到的問題。比如我們在討論一個提議的變更時,它指出了我沒想到的一點。它更擅長批評,而不是提出原創想法。
總的來說,我非常滿意,但有些時候我也會感到沮喪。過去幾天,我試圖為一個內部產品構建一套相當複雜的測試基礎設施,在測試容器裡用真實 LLM 進行測試,偽造所有工具等等,而 Claude Code 表現得非常糟糕。我認為原因之一是它以前沒見過這種場景,這可能是一種相當新的測試形式。
要讓你的 Coding Agent 獲得最大的自主性,你需要對測試非常執著。而我這次碰到的,既是它見過的更極端的測試量,而且某些類型的測試可能也是它以前沒見過的。儘管有明確的指示,它似乎還是出奇地掙扎。
Simon:你有沒有嘗試過用技能和上下文來引導它,試圖讓它提供更接近你想要的建議?
Rod: 我試過用 Skills 和 Claude.md 來配置 Coding Agent 的行為,但有點不幸的是,當上下文越變越大,Coding Agent 就會開始忘東西。有個特別奇怪的現象:它老是想在程式碼體裡寫全限定名,可我非常討厭這個,我更喜歡用 import。我已經把這個偏好寫進了 claude.md 配置檔裡,但大概有 50% 的時間它還是照忘不誤。
Simon: 就算那是 Agent 必須讀取的強制性指令,它也做不到漸進式學習。
Rod: 對,注意力就是會衰減。
語言之爭
Simon:我記得你曾經說 TypeScript 是當今最重要的語言,因為它能讓一個普通 JavaScript 開發者的水準翻倍。既然你認為 TypeScript 比 Java 更重要,那你怎麼同時做到既堅持在 JVM 上構建,又相信 TypeScript 是最重要的語言?
Rod: TypeScript 是門非常聰明的語言。有意思的是,你看曾經靜態類型與動態類型語言的那條路線,現在某種程度上正在趨同。現代 Python 大量使用類型提示,Python 的類型系統也相當不錯了;TypeScript 顯然給 JavaScript 加上了一層類型。
TypeScript 是一門優美的語言,它的確非常重要。但我還會不會說它依然是最重要的?這得看應用的類型。如果我從零開始寫很多類型的應用,我很可能會用 TypeScript 去寫伺服器端和 React。但你去看企業級應用,沒多少是用 Node 寫的,也不應該用 Node 去寫。在 JVM 上,Java、Kotlin 會給你一堆對這個類別的應用極有價值的東西。TypeScript 再漂亮,在這件事上也幫不上什麼忙。
所以我認為,第一,現代 Java 肯定比我當初說那些話的時候好得多;第二,Kotlin 是一門值得認真考慮的出色語言。Kotlin 和 TypeScript 大概旗鼓相當,我仍然會想念聯合類型,我可以長篇大論地論證密封層級絕對不如聯合類型好,但 Kotlin 同樣有很多比 TypeScript 強的地方。TypeScript 的另一個問題是,儘管他們做得非常好,底層仍然有一層瘋狂的東西,你偶爾就會撞見,而且沒法掩蓋。而 Kotlin 是一門現代化語言,它建立在更穩健、更可預測的基礎之上。
Simon:你認為 AI 的進步會在五年內改變這些語言格局嗎?有沒有足夠多的變化來顛覆這些既定事實?
Rod: 我不知道我的觀點是什麼,我可以說服自己語言不重要,也可以說服自己語言很重要。
先說很多人想像的那個圖景,以為訓練語料庫會讓熱門語言擁有天然優勢,然後這種優勢會被固化下來,這絕對不對。我使用 Coding Agent 的三種語言是 Java、Kotlin 和 Python,而毫無懸念,Coding Agent 做得最好的恰恰是 Kotlin,這完全超乎你的預想。
你想,Java 和 Python 都存在了很久,而且最近幾年進化得都很快。你不應該寫出 2019 年的 Java,當然也不應該寫出 2019 年的 Python。訓練資料太多了,你可以說「永遠用值類型」「永遠用增強的 switch 陳述式」「Python 裡永遠用類型提示」,但正因為訓練資料體量太大,你實際上是在對抗它。我倒不是說他倆不好,Java 和 Python 仍然非常好。
可 Kotlin 更好,這讓我非常吃驚,因為 Kotlin 的語料庫並不大。Kotlin 本身也沒怎麼進化,因為它從一開始就是一門現代語言。其次,早期用 Kotlin 的大概率是技術非常嫻熟的人,因此沒有那麼多糟糕的 Kotlin 程式碼,不像 Java 或 Python 那樣。
所以,我不認為熱門語言會因為訓練資料就被固化。LLM 對任何它們見過足夠多的東西都極其擅長,而我們聽說過的所有程式語言,它們都見過很多。但這就引出了另一個問題:既然如此,你幹嘛不用完美的語言去寫每一件事?就像我們之前說的,有些東西我絕對不會用 Python 寫,而會用 Java 寫。既然 LLM 在每一門語言裡都是大師級,為什麼不挑最理想的語言來寫每一個服務?用 Rust 寫這個服務,用 Go 寫那個。(但我不認為現在還有值得用 Go 寫的東西了。)
問題在於,這就像我們曾經看到過的微服務狂熱——還有其他成本。你現在會引入極為龐大的維護成本,除非我們願意完全信任我們的機器,但我不覺得我們該那樣做,我不認為那是個好主意。
Simon: 還有技能問題。光是技術堆疊的多樣性,以及人們需要維護這些技術堆疊,就已經足夠頭疼了。還有安全,每引入一門新語言或一個新函式庫,威脅面就成倍擴大,而且這種風險會跨語言蔓延。
Rod: 至少就目前而言,我們選擇語言和技術堆疊的根本性理由,可能不會改變太多。因為當你把它們投入生產、為它們背書的時候,那些最根本的東西並沒有變。
開源生存法則
Simon:你之前提過,開源專案背後的公司需要從第一天起就有商業模式,這對 Embabel 來說是什麼樣的?
Rod: 最可能的模式是開放核心。我認為開源的純支持模式一直就非常困難,有了 Coding Agent 之後,還會難得多,所以我覺得會存在比框架層面更上一層的產品。我們目前的思路是,把框架作為一種競爭優勢,去構建可能甚至不針對軟體開發者的產品,而是針對更廣泛的知識工作者。框架本身是 Apache 授權,和 Spring 一樣。我們歡迎社群貢獻,我們有活躍的 Discord、GitHub 和問題追蹤器,歡迎任何感興趣的人來貢獻和加入社群。
Simon:Spring 前後經歷了 VMware、Pivotal 再到如今 Broadcom 的收購。你覺得是什麼讓它挺過了這些收購?很多開源專案在被收購之後就枯萎甚至死亡了。
Rod: 我覺得在 2009 年底那筆首次收購發生時,Spring 已經是一個龐然大物了,它已經是事實上的標準。早期的採用率和圍繞它建立的社群,顯然有著巨大的慣性。
但有幫助的一點是,有相當多技術嫻熟的開發者被全職雇來開發 Spring。這意味著那些不那麼令人興奮的事情也會有人去修,因為這是某個人工作的一部分,不管他們感不感興趣。我仍然堅信,開源確實能從背後的商業支持中受益。讓 Spring 變得可靠的關鍵,它非常穩健,任何嚴重問題都會迅速被修復,部分正反映了我們不依賴志願者。社群貢獻當然很棒,但我認為背後的這種專業性至關重要,它給出了那種完整產品式的開發方法。
「這是人們選擇的最後一波框架」
Simon:你認為 JVM 最被低估的東西是什麼?Python 世界完全不知道自己錯過了什麼?
Rod: 效能當然是其中一個面向。但更嚴肅的回答是:運行在它上面那些程式碼,業務邏輯、領域模型,對於理解關鍵業務,有著難以估量的價值。
Simon:關於 AI Agent,你有什麼不受歡迎的觀點嗎?
Rod: 我對 MCP 持有一種相對懷疑的態度。倒不是說我覺得 MCP 不好,而是我覺得現在大家已經把 MCP 當成了「萬能錘子」,於是看什麼都像釘子。
Simon:如果有 Java 開發者被老闆命令「去學 Python,因為 AI 要用 Python」,你會給他什麼建議?
Rod: 我會讓他去讀讀我的部落格。我寫了一系列文章,用完全相同的任務來對比 Python 和 Java 的實現——檔案處理、API 調用、資料管線。結果非常清楚:Java 程式碼在效能、可讀性和生態成熟度上完全不輸 Python。你可以直接把其中一篇文章甩給你的老闆,或者更好一點,自己親手寫一段。很多時候你會發現,Java 的程式碼競爭力其實一點不差。
Simon:如果是已經在線上生產環境跑著的專案,你會選 LangGraph 還是 Embabel?
Rod: Java 專案還是 Python 專案?如果是 Java 專案,那我肯定選 Embabel。否則你就是在往系統裡硬塞一個「異質技術堆疊」。現在 Embabel 已經到 0.3.5 了,離 API 穩定其實非常近。我會很驚訝如果從現在到 1.0 之間還有什麼重大 breaking changes,估計再過四到六週就會到 1.0。
所以說實話,我不覺得現在採用 Embabel 是什麼高風險的事。反倒是,如果我有一個 Java 專案,卻要引入一整套完全不同的技術堆疊,再讓它去和現有 Java 業務邏輯對接,我會覺得這風險大得多。等你把這一大堆東西折騰完,Embabel 可能都已經 1.0 了,到時候你只會特別懊惱:「我當初到底為什麼要這麼搞。」
Simon:今天啟動一個全新的企業專案,用 Kotlin 還是 Java?
Rod: 這取決於團隊規模。如果團隊少於 20 人,我會認真考慮 Kotlin。如果團隊更大,而且大家原本也不熟 Kotlin,那我可能還是會繼續用 Java。
Simon:以前 Java 開發者轉 Scala 的學習曲線其實挺陡的,現在 Java 轉 Kotlin 還有那麼難嗎?
Rod: 老實說,我不太確定。因為我接觸 Kotlin 的時候,其實已經寫了很多別的語言,尤其是 Python。我雖然也寫過幾個月 Java,但後來又回到了 Kotlin。所以我並不是一個「純 Java 背景」轉過去的人。不過我可以明確地說:Kotlin 絕對比 Scala 容易學,Kotlin 本身其實是一門相當容易上手的語言。
而且還有兩點我一直很認同。第一,我覺得每個開發者原則上都應該每隔一兩年學一門新語言,因為它真的會改變你的思維方式。第二,現在學習新語言的門檻已經低到前所未有,LLM 可以極快地幫助你掌握任何語言,所以整體門檻其實已經被大幅降低了,比如我從來沒讀過 Kotlin 的教學書籍。
Simon: 你剛剛提到讓 LLM 去批判程式碼,有時候相比讓它「直接生成」,這種方式反而更值。我也覺得,尤其是在學習新語言的時候,讓 LLM 給你解釋「這裡為什麼這麼寫」「背後的機制是什麼」,很多時候比直接說「幫我生成一段程式碼」更有效。否則你最後只能對著生成結果猜:「它為什麼要這麼寫?」
Rod: 尤其是對於有經驗的開發者來說,更是這樣。我學新語言的時候,經常會問 LLM:「這個語言裡有沒有某個特性的等價實作?」比如我會問:Python 裡有沒有類似 TypeScript type guard 的東西?如果你本身已經理解這些概念,那 LLM 特別擅長幫你把這些概念映射到另一門語言上。
Simon:你每天都會用、最喜歡的 AI 工具是什麼?除了 Claude Code 之外。
Rod: 大概率還是 Claude Desktop。主要是它能讓我同時調用一堆工具做 competitive research,我很多事情都會用它來處理。
Simon:關於 Spring,有什麼你後來覺得「當初做錯了」的地方?如果重做一次,你會在 Embabel 裡換一種方式嗎?
Rod: 有個挺小、但我覺得挺有趣的點。當年我一直想給 Spring retrofit 一套「基於事件的 logging 機制」,但那時候已經太晚了,架構上不好再改。但在 Embabel 裡,我們一開始就這麼設計了。這樣做的好處是:所有 event 都是完整的。你可以透過 SSH stream 出去,可以監聽,可以訂閱。而且更有意思的是,我們甚至可以修改你的「logging personality」,比如讓你的日誌全都用尤達大師的語氣輸出。
某種程度上,Embabel 的整體風格其實是建立在現代 Spring 的經驗之上,只是加了一些在 Kotlin 裡更容易實作的東西。比如我們基本不怎麼用 builder pattern,因為 Kotlin 可以把這些東西寫得更優雅,哪怕最後還是給 Java 使用者使用也一樣。
Simon:如果 Embabel 五年後不存在了,你覺得是什麼殺了它?
Rod: 我完全不知道五年後 Embabel 是否還會存在。五年後,人們還會親手寫應用嗎?還是他們違背了我的建議,讓機器完全接管了一切?我甚至會說:這可能已經是「最後一代由人類主動選擇的框架」了。 以後越來越多的技術選型,都會由我們的工具替我們完成。但說實話,我們正處在一個幾乎獨一無二的時代。別說五年,一兩年後的預測都可能是錯的。
訪談影片原連結:
https://www.youtube.com/watch?v=UcvxYltiS7E
聲明:本文為 InfoQ 翻譯整理,不代表平台觀點,未經許可禁止轉載。
今日好文推薦
Anthropic衝刺IPO:Claude一個月燒掉客戶5億美元,卻成了上市前最強廣告
Token 賣瘋了掙的也是小錢,Snowflake 盯上了 AI 時代最貴的資產
「AI寫的程式碼無一例外都是垃圾」:程式語言Zig的硬核宣言
Codex 500萬用戶福利被嗆「作秀」!Claude Code 吃掉近九成 Token,OpenAI 搶用戶敗在「小氣」上?
會議推薦
企業級 Agent 落地,繞不開 4 個真實的工程問題。如何在 Agent 安全性和可用性之間找到平衡點?Agent 需要什麼樣的記憶系統才能真正理解上下文?如何透過演算法壓榨實現智力增量與成本控制的極致平衡?多 Agent 協作,如何做到可觀測、可治理、可控制?6 月 26-27 日,AICon 全球人工智慧開發與應用大會·上海站,國內頭部公司的 Agent 實踐,一次說透。