Spring创始人Rod Johnson重新创业做企业AI Agent框架Embabel,提出这可能是人类亲自选择的最后一代框架,分享了企业AI落地的架构思路。 ## 1. 企业AI应用的技术栈选择:贴近原有业务栈而非盲目换Python Rod Johnson区分了数据科学和企业AI应用两个场景:模型训练、数据处理适合用Python,但GenAI应用层赋能更适合在原有业务语言中完成。 如果企业现有系统是Java栈,直接从Java栈调用LLM HTTP接口即可,不需要重构为Python栈,盲目引入异构技术栈会增加技术难度,还会让不懂核心业务的人掌握战略主导权。 Embabel核心用Kotlin开发,对Java做了无缝适配,Kotlin和Java互操作性远好于早年的Scala。 ## 2. AI编码的架构风险:保留人类对架构的控制权 Coding Agent确实能大幅提升编码效率,Rod Johnson自己的项目中AI生成代码比例可达95%,但**必须由人掌控架构监督**。 如果完全放权给Agent添加功能,不做设计管控,复杂应用很快会出现设计退化、代码质量崩盘,只有一次性非核心项目适合完全让AI自由编码。 开发者应专注于高价值的架构设计工作,把重复编码交给AI,这种结合模式的产出质量优于纯手写或纯AI生成。 ## 3. Embabel的核心设计:用游戏NPC算法实现可控可审计的Agent规划 不同于多数框架让LLM自主决定下一步,Embabel采用原本用于游戏NPC的GOAP确定性规划算法:通过动作前置/后置条件、参数类型匹配,动态在运行时生成通往目标的执行路径,还支持按动态成本选择最优路径。 这种设计天生具备可解释、可审计能力,能完整展示规划路径和决策依据,同时允许在不同步骤灵活选用不同LLM,支持敏感数据本地处理,可预测性远高于纯LLM规划。 ## 4. 框架未来:选择权正在从人类向AI转移 Rod Johnson认为,这很可能是**最后一代由人类主动选择的框架**,未来越来越多技术选型会由AI工具自动完成。 模型能力变强会逐渐替代部分编排层能力,但对于企业业务流程来说,可控、可审计的确定性框架仍然有不可替代的价值,模型能力提升和框架优化并不冲突。
Spring 创始人重回一线做AI 框架,却说:这是人类亲自选择的最后一代框架
2026-06-03 12:41

Spring 创始人重回一线做AI 框架,却说:这是人类亲自选择的最后一代框架

本文来自微信公众号: InfoQ ,编译:宇琪,作者:Tina,原文标题:《Spring 创始人重回一线做 AI 框架,却说:这是人类亲自选择的最后一代框架》


Rod Johnson又回到了一线。


他是Spring的创造者,曾经几乎重新定义了企业Java应用该怎么写。二十多年后,他重新创业,做了一个面向企业AI Agent的开源框架Embabel,试图把LLM放进真实的业务系统里,让它不只是会调用工具,而是能在可控、可解释、可审计的流程里工作。


有意思的是,这一次他做的仍然是框架,但他对“框架”的未来并不乐观,至少不再是过去那种乐观。在他看来,模型还会继续变强,工具也会越来越多地替开发者做选择。Embabel会不会被更强的模型追上?企业还需不需要这样一层harness?未来的框架到底是由开发者挑选,还是由AI工具自动决定?这些问题,都绕不开他在访谈里说出的那句话:这可能是最后一波由人类亲自选择的框架。


这句话放在别人嘴里,可能只是又一次AI时代的夸张判断。但从Spring创始人口中说出来,意味就不一样了。因为Rod Johnson亲手参与过框架时代的兴起,也见过一个框架如何变成企业软件开发的基础设施。现在,他回到战场,却认为选择权正在转移:开发者未必会消失,但开发者亲自挑框架、搭技术栈、决定系统骨架的时代,可能正在进入尾声。


本文基于该播客视频整理,经InfoQ编辑。


核心观点如下:


  • 如果我要用TensorFlow做模型训练、微调、某些数据处理和摄入,我当然会用Python。但GenAI应用层赋能这件事,更适合在应用原本的语言里完成,如果应用是用Java写的,那就在Java里完成。


  • 一旦你进入复杂的应用程序,如果你不保持那种架构上的监督,你很快就会陷入一团乱麻。你的Agent会愉快地添加新功能,但每添加一个新功能,设计就会退化,代码就会变得非常糟糕。


  • 开发者不应该花大量时间在编写代码上,因为你可以通过专注于你独特增加价值的地方来获得更大的杠杆。


  • 每个开发者原则上都应该每隔一两年学一门新语言,因为它真的会改变你的思维方式。


  • 这可能已经是“最后一代由人类主动选择的框架”了。以后越来越多的技术选型,都会由我们的工具替我们完成。


1Spring创始人回归一线创业


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:你要解决一个业务问题,就必须考虑这个问题本身的“邻接性(Adjacency)”。你在和什么打交道?你大概率在和数据库、企业服务、现有代码库打交道。同时,你还要处理一个新东西: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实际上已经进化了很多。


2Coding Agent正在毁掉你的代码库


Simon:你之前谈到AI基本上是被当作一个断开的层硬塞进去的,而不是更深入地集成到现有系统中,结果这导致了一些失败案例。你认为真正的企业AI失败案例是什么样的?


Rod:我认为最大的问题就出在,当高层下达“AI一切”的指令,团队却在没有真正业务案例、没有确认AI是否合适的情况下,盲目开展AI项目。一个主要的反模式就是“我们必须用更多AI”这种念头,却从来不去问一句:为什么要用?用来干什么?虽然我非常热爱并且着迷于AI,但如果能不用LLM就完成一件事,那你当然应该不用LLM,这样更便宜、更确定、更快。


所以组织首先要做的,是思考“我们怎么从这儿走到那儿去”。举个例子,我们在澳大利亚的一个客户,他们一开始识别出一类小问题:网站上有某张特定表单,客户填写完后需要人工审核才能继续。95%的情况其实非常简单,虽然用正则表达式处理起来稍微麻烦了点,但本质上很简单。于是他们把这个摩擦点消除掉了,在95%的场景里让客户即时推进,不再需要等人工处理。我觉得这是非常棒的起步案例:先在小事上拿到结果,慢慢建立起信任。


另外,对于“异构技术栈(Alien Stack)”问题,它会在两个方向上造成伤害。第一,技术上让一切都变难;第二,它往往还会把战略权交到错误的人手里那些根本不懂核心业务、可能从来没见过任何核心业务应用的人,却在主导战略。当你要赋能这些应用的时候,这条路完全走不通。


去年我和一家澳大利亚大公司的首席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,我深信质量会大幅下降,最终连速度也会降下来。


3Embabel的核心:来自一个游戏NPC规划算法


Simon:我们来谈谈Embabel里面的核心组件“规划器(planner)”。这是一个叫GOAP(Goal-Oriented-Action-plann)的寻)寻路算法,最早是为游戏里的NPC设计的吧?关键点是,它是确定性的。而其他框架比如LangChain、Crew.ai,则更多是由LLM来决定下一步做什么、怎么规划。为什么你会从游戏NPC领域里挑出这个算法?


Rod:我最开始考虑的确实是最显而易见的方法——状态机(state machine)。平心而论,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%确定,但你会发现花在提示工程上的时间会大幅减少。所以整体上,系统会变得可解释得多,也确定和可预测得多。


4为什么对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”的场景,也就是在那些是否确定并不那么重要的地方。你可以直接给模型一堆工具,即使它有点不可预测也没关系。所以我确实认为,有一块空间里,模型会需要更少的外围基础设施。但我认为,那块空间与企业应用并没有特别大的关系。


5AI擅长批评,不擅长原创


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:对,注意力就是会衰减。


6语言之争


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:至少就目前而言,我们选择语言和技术栈的根本性理由,可能不会改变太多。因为当你把它们投入生产、为它们背书的时候,那些最根本的东西并没有变。


7开源生存法则


Simon:你之前提过,开源项目背后的公司需要从第一天起就有商业模式,这对Embabel来说是什么样的?


Simon:Spring前后经历了VMware、Pivotal再到如今Broadcom的收购。你觉得是什么让它挺过了这些收购?很多开源项目在被收购之后就枯萎甚至死亡了。


Rod:我觉得在2009年底那笔首次收购发生时,Spring已经是一个庞然大物了,它已经是事实上的标准。早期的采用率和围绕它建立的社区,显然有着巨大的惯性。


但有帮助的一点是,有相当多技术娴熟的开发者被全职雇来开发Spring。这意味着那些不那么令人兴奋的事情也会有人去修,因为这是某个人工作的一部分,不管他们感不感兴趣。我仍然坚信,开源确实能从背后的商业支持中受益。让Spring变得可靠的关键,它非常健壮,任何严重问题都会迅速被修复,部分正反映了我们不依赖志愿者。社区贡献当然很棒,但我认为背后的这种专业性至关重要,它给出了那种完整产品式的开发方法。


8“这是人们选择的最后一波框架”


Simon:你认为JVM最被低估的东西是什么?Python世界完全不知道自己错过了什么?


Rod:性能当然是其中一个方面。但更严肃的回答是:运行在它上面那些代码,业务逻辑、领域模型,对于理解关键业务,有着难以估量的价值。


Simon:关于AI Agent,你有什么不受欢迎的观点吗?


Rod:我对MCP持有一种相对怀疑的态度。倒不是说我觉得MCP不好,而是我觉得现在大家已经把MCP当成了“万能锤子”,于是看什么都像钉子。


Simon:如果有Java开发者被老板命令“去学Python,因为AI要用Python”,你会给他什么建议?


Simon:如果是已经在线上生产环境跑着的项目,你会选LangGraph还是Embabel?


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

AI原生产品日报频道: 前沿科技
本内容来源于网络 原文链接,观点仅代表作者本人,不代表虎嗅立场。
如涉及版权问题请联系 hezuo@huxiu.com,我们将及时核实并处理。
正在改变与想要改变世界的人,都在 虎嗅APP
赞赏
关闭赞赏 开启赞赏

支持一下   修改

确定