在过去的三个月里,我与一群志同道合的经验丰富工程师团队一直在 Amazon Bedrock 平台上构建一个非常酷的项目。虽然我对我们正在构建的内容感到相当兴奋,但我们团队还有一个独特之处——我们的大部分代码都是由 AI 代理(如 Amazon Q 或 Kiro)编写的。在您不以为然之前,请容我说明:不,我们并非在进行氛围编程。我不认为这是构建稳健软件的正确方式。
相反,我们采用人类与 AI 代理协作的方式来生成代码变更。对我们团队而言,每个提交都关联着工程师的名字,而该工程师最终需要审查并为代码负责。我们通过设定引导规则来约束 AI 代理在代码库中的操作方式,而使用 Rust 语言编写带来了巨大优势。Rust 编译器以注重正确性和安全性而闻名,能在编译时捕获大量问题,并提供有助于代理迭代的有用错误信息。与氛围编程形成鲜明对比的是,我更倾向于使用"代理式编程"这个术语。虽然听起来不那么激动人心,但在我们行业里,平淡往往意味着可靠。
如今我提交的代码中,约有八成由 AI 智能体完成。我的个人工作流程是:先分解任务直至思路清晰(常借助 AI 探索实现方案),随后向 AI 智能体发出指令,审阅其输出结果,通过反复迭代优化直至满意,偶尔也会接手修改集亲自收尾。我会仔细检查智能体生成的每一行代码,只有对代码质量完全满意时才会采纳——这与我自己逐行编写时的标准毫无二致。
我向来是个高效的程序员,即便过去几年能投入编码的时间有限,也总能见缝插针地完成代码编写。而最近几个月,我的代码产出量更是达到了职业生涯的巅峰。我的团队同样如此——我们的代码产出效率是普通高效团队的十倍。这并非夸大其词,我们确实收集并分析了相关数据指标。
以时速200英里疾驰
这正是有趣之处。即便是经验丰富的典型软件团队,也无法保证万无一失。即便采用完善的测试与工程实践,漏洞仍会偶尔潜入生产环境。我们都听过"生产环境测试"这个说法——正是这种现实让我始终认为,仅聚焦测试远远不够,在爆炸半径控制和恢复时间上的投入同样至关重要。
AI 辅助编程亦不例外。即便经过人工严格审查,生成的代码仍可能存有缺陷,且我怀疑其出错概率并无显著差异。然而当团队提交频率提升十倍时,整体概率格局将彻底改变。原本每年仅出现一两次的生产级故障,可能演变为每周例行事件。即便多数漏洞能在集成或测试环节被发现,它们仍会污染共享代码库,需要投入排查精力并拖慢整个团队节奏。这绝非危言耸听——我们团队已观察到明确迹象:当研发吞吐量呈阶梯式增长时,这类挑战便会浮现。
我越来越确信,要让智能体开发将工程速度提升一个数量级,我们也需要将问题提交的概率降低一个数量级。甚至可能需要降低更多,因为在高速开发状态下,单个提交之间也可能以意想不到的方式相互影响。
换句话说,以200英里时速飞驰时,你需要强大的下压力才能让赛车紧贴赛道!
成本效益的重新平衡
减少漏洞概率的最佳方法之一是改进测试。作为航空迷,我一直很钦佩飞机制造商采用的测试理念。从早期模拟到组件测试,从风洞测试到极限破坏测试,直至整机组装后的试飞环节。就连飞行模拟器也在提升航空业整体安全性方面发挥着作用。软件行业虽然尝试过其中部分理念,但远未达到普及程度。
例如,我一直很喜欢"风洞"式测试,即在受控环境中测试完全组装好的系统。为实现这一点,我采用的一种模式是实现可在本地运行的高保真"模拟"版外部依赖项。这样做之后,你就可以编写在本地运行的构建时测试,验证整个系统的端到端行为。你甚至可以向模拟依赖项注入意外行为和故障,测试系统如何处理它们。这类测试编写和执行都很简单,因为它们在本地运行,而且特别擅长捕捉组件衔接处那些隐蔽的缺陷。
遗憾的是,对于具有中等复杂度的服务而言,模拟所有外部依赖项并非易事。即便做到了,现在你还需要负责跟进真实依赖项的演进变化。基于这些原因,根据我的经验,大多数团队都不会编写此类测试。
我认为我们正在看到早期迹象,表明智能体编码能够改变这一局面。AI 智能体非常擅长快速生成大量代码,尤其是在预期行为明确且几乎没有歧义的情况下。那些原本理论上可行但因实施和维护成本过高而难以落地的想法,现在其成本已经下降了一个数量级。我十分热衷于把握行业中的这种变革浪潮,因为它们为过去不切实际的新方法打开了大门。
我们的项目(在 AI 智能体的协助下)维护了外部依赖项的模拟实现,包括身份验证、存储、链式复制和推理引擎,供测试使用。随后我们编写了一个测试工具,利用这些模拟组件在开发人员的机器上启动整个分布式系统,包括所有微服务。构建时测试会针对这个完整组装的系统启动金丝雀测试,从而验证整个系统的运行状况。
我对这种方法能够捕捉到一类过去只有在变更提交并进入测试环境后才能发现的错误非常看好。几年前,这类想法虽然美好但会因成本过高而遭遇阻力。而这次,我们仅用几天时间就在一个相对复杂的系统中实现了该方案。
高速开发需要更紧密的反馈循环
归根结底,所有这些变更都需要经过构建、测试和部署,才能为客户创造价值。软件团队拥有需要数小时来完成构建、打包和测试软件变更的 CICD 流水线并不罕见。这样的流水线随后可能还需要数天时间,才能将一批变更逐步推广到预生产阶段乃至最终的生产环境。通常来说,具备这种自动化水平的团队会被认为是健康高效的团队。
代理式编码改变了这一动态。在构建、打包和测试一组提交所需的时间内,可能已有十几组提交等待发布。当变更集准备部署到生产环境时,可能已包含上百次提交。若其中某次提交存在问题,就需要回滚部署,导致整个流水线停滞。与此同时,更多变更持续堆积,加剧了混乱与风险。
我是一名 F1 赛车迷,这让我联想到赛道上发生事故时黄旗升起的场景。通常,赛车以惊人的速度和加速度在赛道上飞驰。但一旦发生事故,赛道裁判便会举起黄旗,要求所有车辆减速跟随安全车。原本激动人心的比赛瞬间转变为悠闲的环场巡游,直到碎片清理完毕、赛道恢复安全。为最大限度减少此类延误,赛事主办方会全力做好各类事故预案,确保能在数分钟内完成赛道清理并重启比赛。
正如全系统本地测试有助于缩短发现特定错误的反馈周期一样,我们或许也需要以类似思路来构建持续集成与持续部署流程。当团队以每小时数十次提交的速度推进时,问题需要在数分钟内被识别、隔离和回滚,而非耗费数小时甚至数天。这意味着常规的构建测试基础设施必须实现比当前快一个数量级的运行效率。就像在线游戏在玩家操作与系统响应存在高延迟时会变得无法操作,如果每次代码提交仍需经历漫长等待才能获得反馈,要实现十倍效率提升无异于痴人说梦。
通信瓶颈
我乐于观察运转良好的操作。如果你曾窥探过繁忙餐厅的后台,乍看之下可能会觉得一片混乱。但若你花时间留意细节,就会发现所有成员都在持续相互协调。厨师、帮厨、服务员、传菜员和经理之间信息流转不息。通过保持持续同步,一家管理有方的餐厅即使在高峰时段也能服务好顾客,同时保证品质与响应速度。
我认为要让软件开发团队实现类似的速度提升,就需要对团队沟通方式加以约束。当吞吐量提升一个数量级时,你不仅是在编写更多代码——更是在做出更多决策。该采用这种还是那种缓存策略?如何处理这个边界情况?怎样的抽象才恰到好处?在常规速度下,团队可能每周做出一两个此类决策。而在10倍速状态下,他们每天都要做出多个这样的决策。
挑战在于,许多这类决策会影响其他人的工作进度。工程师 A 决定重构认证流程,这会波及工程师 B 即将扩展的 API 接口。这些不仅仅是实现细节——它们是会在代码库中产生涟漪效应的架构决策。
我发现传统的协调机制在此处会引入过多延迟。等待 Slack 回复或将快速同步会议安排到当天晚些时候,意味着要么形成进度阻塞——决策阻碍了推进——要么在意识到冲突前冒着走错方向的风险。在高吞吐量的工作状态下,协调成本可能占据主导地位!
一种方法是消除协调需求——如果每个人都独立开发组件,就不太需要协调。但我发现这种理想状态在大多数现实系统中并不切实际。因此另一种选择是大幅降低协调成本。我们团队在同一楼层办公,我认为这对我们的开发速度至关重要。当有人需要做出可能影响他人的决策时,他们可以走过去在白板前花几分钟讨论清楚。我们会就方案达成一致,实时讨论权衡取舍,然后两位工程师都能立即回归工作。决策得以快速、正确地制定,且不会造成工作阻塞的堆积。
我承认这并不能解决分布式团队的问题——这仍然是一个待解的难题。
前进之路
我对智能体开发的潜力感到非常兴奋。我认为它不仅能够提升软件开发效率,还能让我们解决那些以往因过于小众或成本过高而无法攻克的问题。这些收益是真实存在的——我们团队实现十倍的吞吐量提升并非理论空谈,而是可量化的成果。
但关键在于:如果我们只是简单地将 AI 智能体生硬地套用到现有开发流程中,这些收益将无法实现。就像给配备窄轮胎和老旧刹车的汽车加装涡轮增压器,结果不会是更快的圈速——而是车祸连连。当代码产出速度提升 10 倍时,我们当前的测试、部署和团队协作方式就会成为制约因素。瓶颈只是发生了转移。
这意味着我们需要从根本上重新思考软件开发的方式。为每日 10 次提交设计的 CICD 流水线在面临 100 次提交时会不堪重负。在常规速度下"足够好"的测试策略,在高速状态下会让过多漏洞溜进生产环境。曾经运转顺畅的沟通模式,如今会造成工作阻塞的持续堆积。
好消息是,我们已经掌握了关于全面测试、快速部署和高效协作的绝佳思路——这些思路曾展现出巨大潜力,却因实施和维护成本过高而未能广泛普及。变化在于,智能体开发本身能够显著降低这些成本。那些提升我们代码产出效率的 AI 智能体,同样能协助构建维持这种产出效率所需的基础设施。
这才是真正的机遇所在:不仅在于更快地编写更多代码,更在于利用 AI 使以往不切实际的工程实践变得可行。能在智能体开发中取得成功的团队,将是那些认识到整个软件开发生命周期都需要协同演进的团队。
原文链接: