Reed's News
← 返回精选

软件工厂为何失败:仅靠工程框架远远不够

AI 60 dhorthy 2026/7/23 5888 字 原文 ↗

或:仅靠工程框架远远不够

说明 我运营着一家名为HumanLayer的公司,专注开发人机协作工具。因此下文观点可能带有一定偏向性,但仍希望能为你提供帮助,至少能让你觉得这个话题和我一样有趣。——德克斯

如今,所有人都在争分夺秒地将AI编码投入生产。关于循环工程的讨论铺天盖地,主流观点是我们应该编写更多循环。1

循环工程:多写循环就对了

StrongDM曾撰文介绍他们的"熄灯软件工厂"——那里无需人工读写代码。

这套叙事逻辑大致如下:

  • 你才是瓶颈所在
  • AI模型已经足够好用
  • 代码生成近乎零成本
  • 只管加速交付即可

OpenAI的瑞安·洛波波罗今年2月发表过相关文章,并在4月的演讲中介绍了OpenAI的软件工厂Symphony

OpenAI瑞安·洛波波罗谈框架工程

这些业内精英都极为聪慧,我对他们满怀敬意。但也有人刻薄地指出,这不过是又一个吸引风投资金、盲目扩张的借口。

我们的同行马里奥在AI Engineer Europe大会上疾呼请慢下来——原本不该因AI编码工具出故障的公司,如今却频频因此宕机

正如马特·波科克所言,代码库的崩溃速度比以往任何时候都快

我尚未找到StrongDM关于"熄灯工厂"实际效果的确切数据或结论,仅在weather-report上看到今年2月至6月的零星更新。编辑补充——7月23日Hacker News上有与该团队的讨论,看来我们很快就能得到更正式的进展报告!

Faros AI团队发布的报告显示:自今年1月和2月大家开始使用AI编码工具以来,代码合并前的评审质量大幅下滑:

  • 评审评论数量增多、篇幅变长,大量PR未经评审就直接合并
  • 生产事故发生率飙升
  • 每位开发者产出的bug数量显著上升

| Faros AI:代码合并前质量下滑——评审评论增加25%、长度增加22.7%、31.3%的PR跳过评审 | Faros AI:生产环境质量下滑——每PR事故率上升242.7%、月度事故增加57.9%、人均bug数增加54% | |---|

这份报告更多是相关性信号,而非确凿证据 3,而本文的核心也正是要提醒大家警惕这类粗糙数据。但就我所见,报告结论在整体趋势上是成立的

很多人会说这是"能力问题"——用不好AI工具,是你自己的问题。

无论你怎么尝试……嗯,我敢保证,总有人会告诉你:如果"堆token"不管用,那就是你能力不足。你只需要投入更多token,别再去读代码了。如果你刚开始接触,他们会说这是必经阶段。去年夏天我也曾这么认为

尴尬的是,我之前关于"如何更好使用AI编码"的言论被录制成视频,如今在YouTube上累计播放量已近百万。我并非在炫耀,只是想说明:我深入研究AI编码工具的最佳用法已有很长时间,也总结出了一些对很多人真正有用的经验。

| 《AI编码工具的高级上下文工程》(https://hlyr.dev/ace) | 《拒绝凭感觉——在复杂代码库中解决难题》(https://hlyr.dev/nva) | 《我们对RPI的所有误解》(https://hlyr.dev/qrspi-mlops) |

总之,网络上那些"多堆token就行"的论调,核心承诺很简单:只要做好足够的框架工程,就能两全其美:

  • 开发速度提升10至100倍
  • 保证代码高质量
  • 再也不用做大家都痛恨的代码评审

我们要做的,无非是配置更多代码检查工具,给PR评审机器人加一些"对抗性评审"之类的指令,软件就能自动平稳构建。

但我想让你明白:无论投入多少框架工程或循环优化,都无法解决一个本质问题——这是模型训练层面的缺陷。

为了理清这一点,我不得不深入研究编码模型的训练与评估机制,包括RLVR(强化学习与人类反馈)和基准测试两个方面。

本文将围绕以下几点展开:

  • 软件工厂的概念始于1968年,它如何演变?AI又带来了哪些改变?
  • 为何模型在基准测试(包括最新的"前沿"测试)中表现优异,却能生成大量粗糙代码?
  • 尽管如此,我们仍能在不搞垮代码库的前提下实现高效开发

我会抛开层出不穷的技能插件和那些"疯狂堆token"的狂热建议,从宏观层面谈谈真正有效的方法,不涉及特定技巧或框架。

视频版:本文基于我在2026年AI Engineer World's Fair的主题演讲展开,并补充了更多内容。

感谢@addyosmani、@CyrusNewDay、@HamelHusain、@zeeg、@dillon_mulroy、@nayshins和@jeffreyhuber对本文提出的修改意见。

阿迪·奥斯曼尼的观点值得强调:

如果你喜欢"凭感觉写代码",尽管继续。我自己也经常这么做,但同时我也要维护大量生产环境软件(还通过HumanLayer帮助数千名工程师维护代码)。因此本文后续内容主要针对那些在复杂代码库中解决难题的开发者。

我经常听到用遗留系统(brownfield)来区分这类场景。过去这个词通常指运行了十年的Java系统,但如今开发速度如此之快,AI构建的代码库可能在3到6个月后就开始出现问题——开发速度放缓,新增功能的方式也不得不改变。

我职业生涯一直在构建和研究软件工厂,但最近才了解到:这个术语最早可以追溯到1968年的北约会议——正是那次会议提出了"软件工程"的概念。

另一个有趣的细节是,美国国防部曾发布一份31页的PDF,讨论国防部如何更好地使用Jenkins等工具。

我们先以2022年(AI大规模应用前夕)的标准来定义"软件工厂":在传统软件工厂中:

  • 人决定要构建什么——工程师、产品经理和领导层共同驱动愿景
  • 需求进入追踪系统——Linear、Jira等工具,形成需求状态流转的闭环
  • 有人领取任务并开发——通常会进行手动或自动化测试
  • 提交拉取请求(PR)——自动检查,人工评审代码,可能还要拉取代码进行测试
  • 发现问题?回退到开发环节
  • 部署到生产环境——交付给用户使用
  • 添加监控——整个行业围绕"凌晨3点故障告警工程师"构建
  • 用户反馈——提出需求、发现bug、提交功能请求 → 团队将其加入追踪系统

wsff-boxes-2x.mp4

如此循环往复。还没引入AI,整个流程就已经包含多个循环环节。

团队几十年前就意识到:开发和评审都需要数小时甚至数天时间。

开发和评审均需耗时数小时/天

因此我们会提前做足准备工作——团队共同参与规划、架构设计、冲刺计划。这样做的好处是:

  • 减少返工:在写代码前就达成共识
  • 减少逐行评审时间:如果你读过一份高质量长PR就会知道,当代码近乎完美时,评审速度会快得多

提前规划:1小时前置工作减少返工,评审时间从6小时缩短至20分钟

我们稍后会回到这一点,先看看引入AI编码工具后发生了什么。

现在几乎每家公司都在——

花大半年时间宣传他们如何打造AI代理工厂,实现75%代码由AI生成

AI代理工厂的核心,其实是将"人工开发"替换为"AI代理开发",再搭配编排工具、框架、沙箱、模型、计算机操作等配套设施。我不会深入这些细节——坦白说,我已经看腻了,相信你也是。

AI代理软件工厂:由AI代理完成开发

当AI代理负责开发时:

  • 开发时间从数小时/天缩短至数分钟/小时
  • 评审仍需数小时/天:人类仍需阅读代码、测试改动,因此评审成为新的瓶颈

开发耗时缩短至数分钟/小时;评审仍需数小时/天

于是人们开始想办法加速评审:

  • AI代理评审:检查代码风格、bug和安全问题
  • AI代理回归测试:通过浏览器等外部工具测试,完成后可能还会给你发一段可爱的演示视频

AI代理评审与回归测试:速度提升,但仍是瓶颈

评审速度变快了,但可能依然是瓶颈。没关系,我们可以再加循环。

接下来,你可以将生产事故也纳入工厂流程:不用再凌晨3点叫醒工程师,他们醒来时可能已经看到修复bug的PR了。

将生产事故纳入工厂流程

我们还可以将用户反馈纳入流程:用户提出需求,AI直接开发实现。

将用户反馈纳入工厂流程

到这一步,核心问题只剩两个:你能给队列塞多少任务?以及评审和测试产出结果的速度有多快?

核心问题:队列容量与评审速度

这就引出了"熄灯软件工厂"的概念。

丹·夏皮罗最早提出这个术语西蒙·威利森撰文介绍了StrongDM的实践——在这种模式下,人类不再需要阅读代码。

看着运转流畅的软件工厂,你可能会觉得那个烦人的代码评审环节格格不入,然后决定:人工逐行评审代码?算了吧。

熄灯软件工厂:人工评审环节被划掉

于是你砍掉人工评审,把精力投入到其他方面:

  • 强化测试,让AI自行验证工作成果
  • 完善沙箱和编排系统
  • 优化自动化评审
  • 加强监控
  • 改进部署流程
  • 收集用户反馈信号

转而投入测试、监控与部署

现在核心问题只剩一个:我们能让AI代理开发多少功能?我们想把摊子铺多大?就像"煮沸整个海洋"那样?

核心问题:队列容量

我要提出一个可能颇具争议的观点:熄灯工厂模式行不通。

我们来聊聊软件工厂失败的原因。

2025年7月,我们全面推行熄灯模式:AI读取需求和工单,后台代理处理所有中小任务,全程无需人工干预。

如果你认真尝试过这种模式几个月,就会知道结局如何。你总会遇到至少一个棘手问题,即便用最先进的提示词和工作流,AI也无法解决:

  • 你做了深入的上下文研究,把所有相关信息整理好供模型分析
  • 让AI尝试用10种不同方法复现问题

最终你不得不硬着头皮,去啃那套三个月没看过的代码,试图找出问题所在。

与此同时:

  • 你的网站宕机了
  • 用户怨声载道
  • 而你(如果和我一样)会陷入痛苦——看着那些被你放任进入系统的粗糙代码。

第一次遇到这种情况时,我还能自我安慰:"虽然花了两周时间梳理Claude生成的乱码代码,但为了开发速度,这点代价值得。"但到11月第三次发生时,我们决定干脆重写,我的联合创始人花了整整两周,在VS Code(甚至没用Cursor)里手动梳理所有代码模式。

我想说明的是:AI模型有一个致命缺陷——它们无法长期维护和提升代码库质量,除非有大量人工引导。4

这里所说的"可维护性",特指那种"修改代码库一处,就可能破坏另一处"的糟糕状态,也就是马丁·福勒所说的"霰弹式修改"

关于可维护性我不再赘述,相关著作有很多:

那为什么AI模型做不好软件维护?

你可能会反驳:"德克斯,从7月到现在,模型已经进步很多了啊!"

确实,某些方面进步很大,但另一些方面几乎没有变化:

  • 解决一次性问题,或是凭感觉搭建新营销网站?进步巨大。
  • 长期提升代码库质量?据我观察,几乎没什么进步。

2025至2026年,模型解决一次性问题的能力大幅提升;但提升代码库质量的能力几乎未变

我无法证明这一点,你也一样。目前还没有能有效评估模型维护代码库质量能力的基准测试(后面会谈到相关进展)。

但如果你长期使用AI编码工具——很多人也在讨论这个问题——你可能已经有同感:它们往往会让代码库越来越糟,后续开发越来越困难。

为了找出原因,我们不妨回溯到初代AI编码工具。

Claude Code上线不到一年,年收入就从0飙升至约40亿美元,如今更是达到约90亿美元。

Claude Code营收增速

这有些不可思议,因为当时已经有很多优秀的CLI工具,比如aiderclinecodebuff——它们都早于Claude Code,内置了出色的上下文工程,具备和Claude Code一样的工具集:读取、写入、编辑、grep、bash。我用过这些工具,它们确实不错,但工具调用偶尔会失灵——看着AI在同一个编辑操作上反复失败,你最终还是得自己打开编辑器动手。

2024年的SWE-Agent论文指出,工具设计的微小改动会带来显著差异,比如在ReadFile结果中包含行号,或是将编辑工具从查找替换改为按行范围编辑。

SWE-Agent工具设计对比:无编辑工具 vs. 无校验编辑 vs. 带校验编辑——工具设计的微小改动会大幅影响AI代理行为

Claude Code推出后迅速崛起。你可以将其归因于渠道优势,但公认的原因是:Claude Code更出色,因为Anthropic在框架内部对模型进行了强化学习(RL)训练——这是首次有实验室针对模型即将配套使用的工具,直接对模型本身进行训练。Claude Code因此变得极其擅长在代理循环中调用这些工具。

调整工具定义和评估标准,直到找到模型适用的形态——我曾为不同场景花数周时间做这件事。但如果你拥有模型权重,可以直接修改模型来适配特定工具,那就是另一个维度的竞争了。

OpenAI团队在11月的演讲中说得很清楚:如果你只构建框架,却不拥有模型权重、无法在框架内进行RL训练,那么在与同时拥有框架和模型的团队竞争时,你永远处于劣势。

我做了大量研究并制作了可视化图表来解释其中原理,但发现Calvin French-Owen(Codex团队成员,Segment创始人)在AI Council的演讲把这个问题讲得更清晰简洁。因此我参考他的幻灯片制作了这段动画:

rl-traces.mp4

要让模型更擅长编码,你需要:

  • 生成AI编码代理解决问题的轨迹(例如修复测试)
  • 根据某些标准(验证器)对这些轨迹打分
  • 更新模型权重,让优质轨迹更易被生成,劣质轨迹更难出现

然后重复这个过程数百万次,持续数周或数月。

但这种"打分"方式往往过于单一,甚至有些随意。

SWE-bench Multilingual为例,任务规模很小——每个约15分钟工作量,来自Redis、jq、Django等开源项目。评分只有1分或0分,依据两个标准:

  • FAIL_TO_PASS:是否修复了指定问题?
  • PASS_TO_PASS:修复过程中是否未破坏其他功能?

举个真实例子,来自Ruby项目fastlanefastlane__fastlane-19304任务:它的zip操作会获取两个可选参数并直接调用.empty?方法,因此当用户不传入includeexclude参数时,程序就会崩溃:

'zip_command': undefined method 'empty?' for nil:NilClass

人类修复这个问题只需要两行代码(将nil值默认转为空数组):

# fastlane/lib/fastlane/actions/zip.rb
- @include = params[:include]
- @exclude = params[:exclude]
+ @include = params[:include] || []
+ @exclude = params[:exclude] || []

在评估过程中,模型:

  • 基础提交版本开始——代码库处于修复前的状态
  • 只拿到bug报告——即本例中的'zip_command': undefined method 'empty?' for nil:NilClass

AI代理根据问题编写代码,它看不到最终的修复补丁,也看不到作为评分依据的测试补丁

# fastlane/spec/actions_specs/zip_spec.rb
+ it "sets default values for optional include and exclude parameters" do
+ params = { path: "Test.app" }
+ action = Fastlane::Actions::ZipAction::Runner.new(params)
+ expect(action.include).to eq([])
+ expect(action.exclude).to eq([])
+ end

之后:

  • 保留AI生成的补丁
  • 丢弃它对测试文件的任何修改(防止模型悄悄注释掉失败的测试,或插入无用的模拟代码)
  • 应用基准测试提供的测试补丁
  • 运行整个测试套件:既有原有的zip测试(PASS_TO_PASS),也有新增的测试(FAIL_TO_PASS),看是否全部通过

SWE-bench Multilingual任务评分流程:以fastlane为例——AI代理拿到bug报告和代码库后编写补丁,在沙箱中应用基准测试的测试补丁并运行,全部通过得1分,否则0分

补充说明——基准测试并非验证器,实际上它们必须相互独立(不能用测试数据训练模型,诸如此类)——我这里主要是想说明"评估AI编码代理轨迹质量"的方式及其局限性。

模型如何得出正确答案并不重要,只要测试通过就算成功,但不会因损害代码库可维护性而受惩罚

这就是为什么AI会给所有代码套上try-catch:

给JSON解析套上try-catch

以及写出破坏类型系统价值的懒类型转换:

懒类型转换

运行测试只需几秒就能得到明确的通过或失败结果,这也是RL能通过数百万次循环优化模型生成能力的原因。

但糟糕架构的代价要以周、月甚至年为单位来衡量。第一次有人打开某个文件想做一行修改,却发现根本无法一蹴而就——之前有人凭感觉写了代码,现在不得不在11个地方做相同修改,还得祈祷不会影响其他文件。

一个糟糕的决策导致代码混乱,最终在数周或数月后引发bug/事故——而我们无法将事故回溯到最初的决策

测试能在几秒内给出反馈,但糟糕架构的代价要以周、月甚至年为单位来衡量

软件开发是一个逐步发现问题的过程,但多数现代基准测试会一次性暴露所有问题——无需优化"后续是否易于修改/调整"的能力

糟糕的设计是当前基准测试无法评估的唯一维度。我知道RL不等于基准测试,但如果RL能解决这个问题,基准测试的设计也会随之改进。

无论如何,我个人不认为当前基准测试的任何提升,能代表模型突然具备了不搞乱代码库的能力。

当然,很多聪明人正在解决这个问题。我想说的不是这件事做不到,而是炒作已经远超实际进展

我认为以下几个方向是正确的:

  • SWE-Marathon(Abundant AI):约400小时的任务,例如"复刻Excel所有功能"——采用复合奖励机制,而非单一的通过/失败评分
  • DeepSWE(Datacurve):在从未实际构建过的开源代码库上执行大型任务,从根本上避免训练数据污染,但尚未解决质量问题
  • Frontier Code(Cognition):多PR任务,采用巧妙的确定性质量评估方式——惩罚模型编写无法在补丁前代码上失败的测试(如果你没听说过变异测试,那你会大开眼界)5——通过评审模型检查代码质量规则

Frontier Code:人类整理历史问题,生成特定版本的问题+代码库、最优解决方案和代码质量规则——AI代理的代码由验证器、回归测试、评审模型评估,同时检查新增测试是否能在补丁前代码上失败

但用模型来评判质量也有局限性。

事实上不难想象:如果模型能可靠区分优劣代码,那它一开始就能写出优质代码。RL需要快速可靠的"预言机",但目前还没有针对可维护性的预言机。

当然,更多评审代理和更多token确实有帮助——它们能提升下限,发现明显的问题。

但它们无法突破上限,因为上限取决于我们通过RL教给模型的内容,而我们至今仍不知道如何教会它做好设计。

因此我仍不放心把代码库交给这些工具,但它们是我见过的首批尝试评估可维护性、而非仅停留在通过/失败层面的测试。

补充说明也许未来的模型能天然具备这种能力,到时候我们就不用操心了。如果你想一直用提示词碰运气,直到GPT-7发布,那请便——但现实是我们现在就要解决问题,接下来我会分享我们的做法。

目前,最终的评判者还是你——所以我们要把代码评审环节加回来:

lights-on-agentic-1

我们要回归AI出现前的做法:提前做一些规划,减少冗长且艰难的评审。

我们要找到杠杆点,并借助AI实现,分为四个阶段:

  • 产品需求定义
  • 系统架构设计
  • 程序设计
  • 垂直切片开发

一切从产品评审开始:用一份简短文档明确要做什么为什么做。目标是把两句话的想法或一段冗长的语音备忘录,转化为半结构化的内容。

首先,对齐要解决的问题——用用户的语言描述真实的用户痛点。其次,明确成功的标准——上线后如何判断这项功能值得做。理想情况下,这是用户层面的结果,比如"完成XYZ流程的时间更短"或"更早达到ABC入门里程碑"。有时也会是更底层的指标,比如错误率或延迟,甚至只是"关于X的支持工单停止了"。

我们尽量聚焦产品层面,而非技术层面。作为一个同时涉足产品和技术的人,我经常忍不住想聊技术细节。这时我会把想法记下来留到后续阶段,然后回到用户实际体验的话题上。如果技术决策阻碍了产品决策,我们就先敲定现有内容,进入架构设计阶段,或做更多可行性原型研究

由于大部分内容关乎用户所见,我不会用文字描述,而是直接做原型。一个粗糙的HTML原型,能解决三段文字都扯不清的争论。

这是一个真实的正在进行中的例子——文档用JSON大纲明确功能,再配上两个实际界面的HTML原型(点击可放大):

| 产品评审文档:用JSON大纲定义流程步骤与分支 | HTML原型:新任务界面,包含流程步骤的图形预览 | HTML原型:AI代理停止时的对话交接建议 | |---|

当然,不是所有改动都需要产品评审。文案微调、一次性脚本、有明显复现路径的bug——我们还是直接交给AI处理。这套流程适用于那些AI误解需求会导致高昂代价的改动。

对于本系列的所有文档,我们采用"作者自愿评审"模式。如果你想节省评审时间,可以提前找好会评审PR的人,和他们一起过一遍产品/技术规格,无论是通过文档评论异步沟通(我们用HumanLayer内部测试,你也可以用GitHub、Notion、Plannotator等工具)。

产品评审敲定后,进入系统架构设计阶段。这并非什么新鲜事,就连喜欢"凭感觉写代码"的人也开始认可它的价值。

如果你想节省评审时间,就在写代码前找好会评审PR的人,和他们一起过一遍产品/技术规格

在这个阶段,我们对齐服务、接口、 schema、队列和存储之间的交互方式,但不深入程序设计细节。为了最大化人机沟通效率,我们大量使用可视化工具,比如序列图:

sequenceDiagram
participant UI
participant API
participant ResourceService
participant Store
UI->>API: PUT /resources/:slug
API->>ResourceService: create(input)
ResourceService->>Store: insert resource
ResourceService-->>UI: 201 resource

契约/接口定义:

PUT /api/resources/:slug
request: { destination: string }
response: { resource: Resource }

数据模型与转换:

-- 新表
CREATE TABLE resource (
slug TEXT PRIMARY KEY,
destination TEXT NOT NULL,
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);
-- 新查询语句
-- SELECT ... FROM ...

Mermaid工具够用,但有时会小题大做,还可能让你误以为大家已经达成共识。架构设计的杠杆作用很高,很多模型的不良倾向都能在这个阶段提前避免,但仅靠架构设计还不足以产出高质量代码——我们还需要程序设计

架构设计完成后,要做一件在AI编码中被严重忽视的事:程序设计

大多数人认为架构正确后,模型就能顺利生成代码。你可以试试,但结果可能不尽如人意。

实际有效的做法是:在任何人(人类或AI)开始编写代码前,从架构层面再往下走一层,明确代码的形态:类型定义、方法签名、程序结构和调用栈。

我们最初的程序设计方案很糟糕——难读又费力。我们试过用Mermaid,但真正好用的是伪代码形式的轻量可视化:

调用栈树:适用于任何编排或控制流变更。如果重点是变更内容,可使用diff格式:

entrypoint
runCommand
+ handleCreateResource
+ ResourceClient.create(input)
+ POST /resources
+ renderResult
- legacyCreateFlow

狄龙·马尔罗伊提到在规划中使用调用图,我认为这完全正确。

狄龙·马尔罗伊谈规划中使用调用图

文件树diff:让你时刻掌握代码库结构和文件位置

src
└── resource
+ ├── resource-client.ts # 新增 - 封装API契约调用
+ ├── resource-client.test.ts # 新增 - 覆盖请求/响应映射
~ └── resource-route.ts # 修改 - 将创建操作接入UI

核心新函数的类型与方法签名:这些内容太细节,不适合放在架构文档中,但AI很容易搞错

interface Item {
id: ItemId
parentId: ItemId | null
// ...
}
interface Cursor {
position: ItemId
direction: 'up' | 'down'
// ...
}
resolveTarget(items: Item[], cursor: Cursor) -> ItemId | null

这些内容生成起来很快(模型初稿,你再调整),每一项都是你原本会在代码评审中隐含做出的决策——而评审是改变主意成本最高的时刻。

接下来我们喜欢做"垂直切片"开发——我和马特·波科克在2026年1月的直播中聊过这个概念,它也被称为 tracer bullets(示踪弹开发)

模型喜欢我所说的"水平规划"——按技术栈顺序开发:

  • 数据库迁移
  • 服务层
  • API
  • 前端

horizontal-slices.mp4

但实际操作中,这种方式意味着你无法在开发过程中"触摸"到完整的解决方案。你可以用代码测试,但对我开发过的几乎所有功能来说,读测试只是开始,在浏览器中查看效果,或用curl调用接口,才是开发过程中频繁进行的环节。

在AI出现前,很少有人会写2000多行甚至500多行代码却不中途检查任何内容

我花了一段时间才意识到差异:在AI出现前,我写代码总是从中间开始向外扩展,大致流程是:

  • 定义API契约并返回模拟数据,用curl测试
  • 开发前端消费模拟数据,在浏览器中迭代优化
  • 将API接入服务层(服务层返回模拟数据/行为)
  • 添加数据库迁移,将服务层接入数据库
  • 加入业务逻辑
  • 添加错误处理

每一步我都会测试、迭代、优化。

vertical-slices.mp4

如果我非常在意代码质量,或对模型在代码库某部分的表现存疑,我会在每一步都评审代码。检查100-200行代码并及时调整,比写完2000多行代码后再排查问题要划算得多。

大多数前沿模型不会主动设计这样的开发计划,而且很难针对不同代码库或任务进行泛化,所以我更倾向于全程参与。相信我,如果能把思考工作外包出去,我早就这么做了。

因此,若想在不事后清理大量粗糙代码的前提下,维持接近人类的代码质量(也就是真正实现高效开发),以下几个步骤需要人类全程参与:

  • 产品设计
  • 系统架构设计
  • 程序设计
  • 垂直切片开发

显然,我们不会对所有交付内容都走完整流程(详见下文80/20法则)。大致分布如下:

  • 约40%的任务直接交给AI,或仅需1-2轮轻量反馈
  • 中等任务:将产品/系统设计合并到一份规划文档中,不分阶段
  • 大型任务:走完所有步骤。对于大型重构等不需要产品设计的场景,会跳过该环节

大多数情况下,我会让AI每次完成1-3个切片,然后边开发边评审代码。无论是内部实现还是功能本身,尽早调整方向都比写完2000多行代码后再找问题容易得多。

不是PR太多,而是糟糕的PR太多。

早在AI出现前,我们就都评审过很多需要返工的PR。

但一份优秀的PR会让人赏心悦目:你滚动浏览每个文件,代码干净整洁,完全符合团队达成的所有决策、讨论和关于软件开发的宝贵经验。

相反,如果PR需要20%的返工(这已经很保守了,我认为大多数AI生成的PR返工率接近50%),对提交者评审者来说都是智力负担情绪负担。(即使提交者是AI,也总得有人启动任务、调整AI结果,至少有人关心最终结果)。

为了节省你的时间(快结束了),我在支线内容"时间都去哪了"中详细聊过这个话题。

核心结论可能会让人有点沮丧:"目前我们仍离不开代码评审"。

我也曾憧憬过这样的世界:只需提出需求,让模型自行开发,不用读代码,就能得到不断演进、不会垮掉的优质生产软件。

但我在这里尽力阐述的全是约束条件:模型擅长某些事,不擅长另一些事。如何在这些约束下优化流程?

模型擅长某些事,不擅长另一些事。如何在这些约束下优化流程?

你可能一心想着提升10-100倍速度,试图说服自己代码质量不再重要,但其实你可以接受这些约束,安全地实现2-3倍的速度提升。

我的最终建议很简单:

  • 充分了解约束条件,通过大量实践培养直觉
  • 在约束范围内优化系统
  • 寻找杠杆点
  • 认真读代码

就这些。如果你想了解我们的产品,可以继续往下看。希望本文能帮你避免灾难,至少能让你觉得那些小动画还挺有趣。

感谢阅读

🫡 -德克斯

我们正在开发humanlayer.com,这是一个AI代理IDE和协作平台,帮助你在维持接近人类水平代码质量的前提下,实现2-3倍的开发速度提升。

我们的目标是两个方向:"软件工厂的构建模块"和"更优的软件可维护性验证器"(甚至可能是更优秀的模型)。

HumanLayer对3人及以下的小团队免费,如果你需要帮助入门,可以加入我们的Discord社区,或发送邮件至founders@humanlayer.dev

特别感谢@calvinfo的灵感启发,我的联合创始人@0xBlacklight,@swyx和@aiDotEngineer团队提供的展示平台,以及所有支持我们的客户、投资者、朋友和家人。

如果你想了解更多,我一直在分享相关内容,以下是本文涉及的所有链接,以及播客、白板讲解等其他形式的内容:

播客与文章:

《AI That Works》系列:

本文相关链接:

脚注

作为AI技术的"循环",大致是由一位据称是养羊农民的人在澳大利亚偏远岛屿上发现的。

我做这行感觉已经很久了,但公认的爆发期是2025年12月到新年这段时间

没错,我特意选了这个词,一个字母一个字母打出来,因为它很贴切。如果你觉得代码已经够糟了,那AI生成的文案会让你更崩溃

当然,GPT-5.5 xhigh能做出很棒的重构,但前提是你得告诉它这么做。而要做到这一点,你必须足够了解代码库,知道它需要重构。我们这里讨论的是为什么熄灯模式行不通。

2013年我在Sprout Social时,老板跟我说过一个他喜欢玩的游戏:看看能从Python单体应用中删掉多少代码,同时保证数千个单元测试全部通过