乐于分享
好东西不私藏

AI 会写程序之后,软件工程真正变贵的是什么

AI 会写程序之后,软件工程真正变贵的是什么

本文转载自 William Yeh,并进行简体中文化。原文链接:https://william-yeh.net/post/2026/03/genai-se-level-up/原文采用 CC BY-NC-SA 4.0 授权协议,本文亦遵循相同协议进行分享。

很多人很容易把这一轮 AI 写程序的进展,诠释成模型正在取代软件工程师,甚至「模型正在取代软件工程」。

这个说法只碰到了表面,却没有碰到核心。 软件工程没有消失,重心正在上移。 过去 SDLC 昂贵的部分,多半落在编写代码、处理低阶细节、人工重构; 现在,既然模型能迅速产生候选实现,昂贵的环节也跟着换了位置。 就像高德拉特的 Theory of Constraints 所说,瓶颈会转移。

问题是,转移到哪里? 相对于以前,新的瓶颈比较容易处理,还是比较困难?

软件工程的典范确实在变。 变化的重点,是抽象层的提升、验证负担的转移,以及治理形式的重组; 工程纪律本身并没有因此终结。

一、LLM 不是编译器

软件工程史上反复出现的一个主题,是抽象层不断上升。

早期编程高度依赖机器码与汇编语言,人类必须直接处理硬件细节、寄存器配置与控制流程。 高阶语言与编译器出现后,指令优化能力强,甚至在大多数情况下强过人类,工程师的注意力才逐步从「这些指令怎么排列」转向「这个逻辑怎么表达」。 写法变方便,人机分工更是被彻底重构。

从这个角度看,今天的 LLM 编程确实像是另一轮抽象层提升。 人类不再只写语法层面的指令,更常以自然语言、规格、测试与约束来描述意图,再由模型生成候选实现。 意图导向、规格导向的开发方式,之所以现在重新变得可行,不是因为理念突然变新,而是因为技术与工具终于开始撑得住。

但这个历史模拟只能用来说明方向,还不足以替后面的结论背书。 很多人看到这里,下一步就想说:既然高阶语言取代了低阶语言,今天 LLM 也会像编译器一样,成为新的工程基础设施。 这个推论太快了。 编译器之所以能成为工程基底,关键不在于它很强,而在于它可预期:同样的合法输入,在同样条件下,应该得到语意一致的输出。

模拟的作用,主要是帮你看清抽象层又上升了一层。 一旦把它延伸成「LLM 已经等同于编译器」,这个类比就走得太远了。 真正需要记住的差异很简单:编译器可以默认信任,LLM 不能。

二、语意层的不确定性

一个常见说法是,现代系统本来就充满不确定性:缓存未命中、垃圾回收时机、JIT 优化、多线程交错,哪一个不是非决定性的? 既然工程师早就习惯和这些东西共处,那么 LLM 的不稳定似乎也只是另一种可管理的系统特性。

这种说法最大的问题,是没有分清楚不确定性发生在哪一层。

传统系统的非决定性(nondeterminism),大多发生在执行路径、资源调度与性能表现层面; 在设计得当的前提下,系统的语意正确性仍可通过类型系统、同步模型、测试与形式方法加以分析与约束。 LLM 的不稳定则更常直接出现在语意建构本身:同样一个提示,可能对应不同的实现策略、不同的边界条件假设、不同的错误处理方式,甚至引入安全弱点、违反隐含限制,或偏离原始需求。[1][2]

这不单纯只是「跑法有点抖」而已,而是「你得到的东西本身可能已经换了意思」。

但把话说到这里,也不能滑向另一个极端,好像 LLM 完全不可工程化。 那也不对。 在任务范围受限、提示结构清楚、工具接口稳定、测试充分的条件下,的确可以明显收敛模型输出。 Anthropic 对 workflow 与 agent 的区分,本身就说明了一件事:工程上真正重要的,是你到底授予了多少自主性,又用什么外部机制把这种自主性给框限起来。 [3]

更准确的理解方式,是把 LLM 看成候选实现产生器,并且用规格、测试、权限与审计把它包起来。 它可以很强,但不能裸奔。[4][5]

要理解 AI 为什么能在某些问题上表现惊人,最好的科普其实不是写程序,而是下棋。

2016 年,AlphaGo 赢了顶尖棋士李世乭固然很了不起,更深远的意义是,它让很多人第一次亲眼看到:只要规则固定、目标清楚、胜负可判定,而且系统可以大量自我对弈,AI 就能在封闭问题里快速逼近甚至超过人类。 围棋虽然复杂,但它仍然是一个封闭世界:棋盘有限,合法动作明确,输赢标准预先给定。 这种问题的难,主要是搜索空间巨大,不是目标函数模糊。 AlphaGo 与后续 AlphaGo Zero 的关键,就是把策略学习、价值评估与搜索结合起来,并通过大量自我对弈持续优化。[6][7]

几年后,AlphaDev 把同一种逻辑用在程序世界。 它把「寻找更好的小型排序程序」表述成一个可搜索的问题:每一步都是组合更好的指令序列,目标函数则相对明确,例如正确性与性能。 也正因为目标清楚、评估稳定、搜索空间可封装,AlphaDev 才能在某些小型排序问题上找到优于既有人类基准的方案。[8]

这里最值得讲清楚的一点是:AlphaGo 和 AlphaDev 的胜利,主要来自 AI 在规则封闭、反馈明确、可大量试错的任务里,对搜索的高效率利用。

这也是为什么它们不能被直接外推到一般企业软件工程。 企业工程面对的通常不是单一且干净的目标函数,而是一组彼此抵触的要求:可维护性、模块边界、合规、事故可追溯性、部署风险、团队交接成本、长期总持有成本。 这些维度很难被压成一个简单分数。 局部性能最优,往往不等于系统治理最优。

不同层级的问题,适合不同程度的自动化。 AI 未必能接管所有工程决策。

四、审查重心转移

代理式工作流的真正冲击,在于它暴露了一个现实问题:当模型生成候选实现的速度远快于人工阅读速度,传统以逐行diff为核心的审查方式,开始难以扩展。

近年来,部分开发者与团队开始尝试一种更激进的工作流:人类主要提供需求、规格与目标,模型或代理则负责编写代码、执行测试、修复错误,甚至在一定范围内自动迭代。 如果用更通俗的话来说,人的角色开始有点像导演,而不再只是亲自下场逐镜头剪片的剪辑师。

这类工作流中,OpenClaw 作者 Peter Steinberger 最具代表性。 他让模型在一个带有工具、上下文与回合控制的环境里,自己跑完一段工作流。 这时候,人类审查的焦点就可能从逐行阅读代码,转向评估需求表述是否清楚、系统意图是否被正确理解、代理执行路径是否合理、测试结果是否可信,以及最终行为是否真的满足目标。[9]

这里最容易产生的误解是,以为「不 review code」等于「不再审查」。 其实更准确的理解是:审查没有消失,改变的是审查的对象。 当 AI 能在短时间内产生大量候选实现时,人类不可能再用老的方式逐行追踪每一段程序; 于是,较合理的做法是:把更多信任建立在规格、测试、静态分析、语意差异辨识与执行证据之上,而不是只建立在肉眼阅读程序文字之上。

不过,我们不要把 OpenClaw 或 Steinberger 当成普遍结论。 它们比较像 F1 赛车:不代表所有人明天都要照那样开车,但它会提前暴露未来工程可能面对的结构性问题。 这些案例的价值,不在于证明「未来所有工程团队都会这样工作」,而在于它们把某些本来还不明显的压力,提早推到了台面上。

更值得注意的,其实不是某一个 demo 跑得多炫,而是不同团队在实现代理式流程时,最后都会收敛到一个很务实的原则:先把能确定、能验证、能回退的部分做好,再去谈更高程度的自治。 Anthropic 在与多个团队合作构建 agent 的经验中,也反复看到这个倾向。 真正比较稳的系统,往往不是一开始就追求「让模型自己决定一切」,而是先把任务切清楚,把工具接口缩小,把失败后的回收方式设计好,然后再视情况逐步放宽模型可自行决定的范围。[3]

这个观察的意义不只是「先从简单开始」这种老生常谈,而是它揭露了代理式工程的成本函数:自主性不是免费的。 每多给模型一层循环控制、多一个外部工具、多一次可自行决策的机会,就同步提高观测、验证、审计与回溯的要求。 所谓成熟,不是把 agent 权限一次拉满,而是知道哪一些判断值得交给模型,哪一些边界必须牢牢握在人类手上。

这才是代理式软件工程真正有趣、也真正让人不安的地方。 工程师没有突然失业,但未来高价值的审查能力,未必是看得出每一行 code 怎么写,而更可能是看得出这套系统的规格是否清楚、证据是否充分、风险是否被控制、责任是否能被追溯。

五、规格开始卡住

如果开发越来越依赖对话、提示与逐步澄清,那么上下文管理就不再只是使用技巧,而会成为真正的工程问题。

原因很简单。 多轮代理式互动,不是把同一句话反复说,而是不断增加限制、修正假设、引用先前输出、放弃失败路径。 系统不只要记住内容,还要知道哪些前提已经失效,哪些推论应该撤回,哪些局部探索不应污染全局。[10]

模型并不是因为对话变长才变笨,而是:模型在多轮互动里,常常不擅长处理自己先前留下来的推论痕迹。 一旦早期对问题的理解有偏差,后面的回合就很容易不是重新定义问题,而是在错的前提上继续修修补补。 Laban 等人的研究可被理解为对这个现象的系统化描述:对话越长,真正危险的往往不是记不住信息,而是舍不得放掉先前已经形成的错误解释。[10]

也因此,后续像Context Branching这类做法才有意义。 它的重点不是把 prompt 包装得更花俏,而是把「探索不同解法」这件事,从一条连续对话改成可分支、可切换、可舍弃的工作流。[11] 这其实是在把版本控制的观念搬进规格管理:不是所有尝试都值得留在主线,也不是每一次失败都应该污染后续推理。

请记住,LLM 的限制不只出现在单次生成的正确率,也出现在规格如何随着回合演化、修正与隔离。 未来越重要的能力,可能越不是「问得更长」,而是「把探索过程切得更干净」。

六、测试开始立法

如果 LLM 与代理式系统开始承担更多实现、重构与局部迭代工作,那么测试策略就不能只是沿用旧习惯,而必须重新回答一个问题:测试的作用,到底只是查错,还是同时负责规定 AI 可以怎么改、不能怎么改。

要谈这个问题,先得把经典的两个测试流派讲清楚。

所谓 Detroit school,也常被称为 Chicago school 或 classicist TDD,核心想法是:测试应尽量从系统的外部行为与状态变化来验证,而不是过度关注对象之间的互动细节。 这一派通常偏好经过真实组合的对象,较少使用 mock; 如果某个功能完成后,系统状态正确、输出正确、公开接口行为正确,那么内部到底是怎么协作的,不一定需要在测试里写死。 这种思路的好处,是测试通常比较耐重构; 只要外部契约没变,内部怎么调整,测试不必跟着大改。[12]

相对地,London school,也就是常说的 mockist TDD,更强调从对象协作与互动设计出发。 这一派常采取 outside-in 的开发方式:先从外部需求开始,逐层往内设计对象之间如何分工,并在过程中大量使用 mock 来验证「谁应该调用谁、何时调用、带什么参数」。 这种做法的优点,是它把设计问题提早暴露出来。 当你在写测试时就必须明确定义各个组件如何互动,很多模糊的责任分配会被迫提前理清。 因此,London school 的支持者常认为,测试不只是验证工具,也是设计工具。[13]

把两者压缩成一句话,可以这样理解。 Detroit / Chicago school 关心的是:最后系统有没有做对事。 London school 关心的是:系统是不是用我预期的协作方式做对事。

这里没有谁对谁错。 它们对应的是两种不同的风险感知。

如果你最担心的是重构成本、测试脆弱性、内部设计被过早绑死,那只会更偏向 Detroit。 因为它保留了较大的内部实现自由,只要外部结果没变,系统就能持续演化。 如果你最担心的是依赖边界不清、责任分工混乱、组件互动失控,那只会更偏向 London。 因为它要求你把协作契约提前讲清楚,借由 mock 让设计更早成形。

问题在于,到了 AI 参与开发的场景,这两派的权重会变。

在代理式重构或生成场景中,模型很可能会调整控制流程、替换内部实现、重新切分模块,甚至用一种人类原本没想到的方式达成同样的外部行为。 如果这时候测试过度绑定方法调用次序、参数传递路径与对象互动细节,那么大量本来有效、甚至更好的重构,都可能被测试判定为失败。 换句话说,过度 London 化的测试,在 AI 场景里特别容易把「设计选择」误写成「功能规格」。

这正是 AI 时代需要重新审视这场旧争论的原因。 问题已经不只是「哪一派更优雅」,而是「哪一种测试更能区分:什么是系统真正不能变的东西,什么只是暂时的实现路径。」

第一层,对于 AI 需要自由探索、自由重构的区域,测试应更接近 Detroit school 的精神。 也就是尽量用公开API、可观察状态、整体行为与高阶不变量来定义正确性,而不要过早把内部协作方式写死。 这一层的目的,是替模型保留足够的搜索空间,让它能在不破坏外部契约的前提下,自主改进实现。

第二层,对于那些真的不能乱动的区域,例如对外协议、错误处理流程、安全检查、高成本依赖调用、金流与审计事件,London school的精神仍然有价值。 因为在这些地方,我们在意的本来就不只是结果对不对,也在意它是否以正确、可追溯、可受控的方式发生。 这时互动测试不是多余,而是在保护关键边界。

第三层,则是传统TDD争论较少正面处理、但在AI场景中特别重要的一件事:测试不只要检查答案,还要提供足够抽象的验证标准。 只靠单一输入对单一输出的例子,对人类手写程序有时还勉强够用; 对生成式系统来说,这种验证往往太窄,容易让模型学会的是「迎合测试」,不是「满足规格」。 也因此,property-based testing 这类方法会变得更重要,因为它验证的不是个别样本,而是程序在一整类情境下是否维持某些不变条件。[14]

所以,比起问「Detroit 还是 London 哪个对」,更值得问的是:哪些测试是在保护真正的外部契约? 哪些测试其实只是把历史实现偶然性误写成规格? 哪些互动细节真的是安全或合规要求? 哪些地方其实应该交给模型自由重构?

AI 时代比较合理的方向,不是在 Detroit 和 London 之间二选一,而是把不同测试放回它们各自最适合的层级。 对可自由重构的内部逻辑,应优先保护外部结果与高阶不变量; 对不能出错的依赖互动、权限流向与副作用,再用更严格的互动验证去守边界; 至于生成式系统特有的风险,则要再往上补一层,利用 property-based 或 differential testing 去检查「不同实现是否其实破坏了同一个规格」。[15]

测试不再只是查错工具,更像是一套治理语言:一方面给模型留出探索空间,另一方面清楚告诉它,哪里可以动,哪里绝对不能动。

七、Clean Code 变了

关于「干净代码」(clean code),过去最常见的说法是:它能降低人类工程师的理解成本,让维护、交接与重构变得比较容易。 这个说法当然没有错。 但到了 LLM 参与开发的时代,这套论述还得再往前走一步。 今天的问题已经不只是「人看不看得懂」而已,更是:模型能不能稳定理解你给它的程序。

对人类来说,命名差一点、函式大一点,也许还能硬读; 对模型来说,这些东西会直接改变它如何切分问题、辨认模式、推测哪里是主干、哪里只是噪声。

这里最容易被低估的一点是,对模型来说,代码不是单纯的执行对象,也是上下文材料,要根据这些材料去推断命名意图、模块边界、控制流程与可重用模式。 程序越杂乱,模型越难分辨什么是核心结构,什么只是历史残留; 越容易把偶然写法误判成必要约束,把局部噪音误当成系统规律。 于是,所谓 clean code 在 AI 时代的意义就变了:它不只是让人比较好维护,也是在替模型降低语意负担

Clean code 真的可能有帮助吗?

Jain 等人的研究,把这件事变成了一个可以测量的假设 [16] :如果不急着增加数据量,而是先改善代码本身的可读性与结构性,模型会不会学得更稳? 他们不是去改善算法本身,而是改善模型接触这段程序时所看到的认知表面。 整体方向是:先让程序的命名更有语意、让结构更容易分段理解、让高阶步骤更容易被看见。

而结果也很清楚:在程序生成任务上,数据整理得更好,确实能带来可观提升; 甚至在某些设定下,少量但较干净的数据,会比大量但混乱的数据更有价值。 这个结论对工程实务非常重要,因为它说明了一件常被忽略的事:在 AI 时代,很多时候真正拉开差距的,不是你喂了模型多少东西,而是你喂进去的材料到底有多容易被正确理解。

这个发现替 clean code 提供了一个新的经验支持,也改变了我们对工程价值的理解。 过去谈工程纪律,常常像是在谈一种类似「童子军规则 (The Boy Scout Rule)」的道德心:今天命名清楚、模块分明,未来团队比较好维护。 这当然成立。 但在 AI 时代,这些做法不只服务未来的人,也立刻服务当下的模型。 你把程序整理得越清楚,模型越容易在较小的语意空间里工作; 上下文噪音越少,生成就越稳定; 结构越清楚,幻觉风险和误解成本就越低。 也就是说,传统工程纪律没有因 AI 而过时,反而第一次在「机器可理解性」上得到了很强的操作性理由。

在LLM时代,干净代码正在从人类维护性的美德,变成模型可生成性的基础设施。 对我们这些有品质执念的资深程序员来说,真是个好消息。

下一次再谈 clean code,不要只问「这样别人看不看得懂」。 还要多问一句:这样的结构,模型能不能稳定理解、稳定延续、稳定验证。 这不是审美问题。 这是生成条件问题。

八、可治理的代码

一旦接受前面的判断,工程问题就会改写成另一句话:不是能不能生成 code,而是能不能生成可被安全吸收、可被验证、可被审计的 code。

这至少包含三层要求。

第一层是执行隔离。 未经验证的 AI 输出,不应直接跑在高权限、真实数据或可对外互动的环境中。 候选实现的执行,本身就是安全决策,而不是普通的开发便利功能。[17]

第二层是语意审查与变更理解。 当产出速度远超过人工阅读速度,人类不可能只靠文字 diff 理解变更影响。 未来的审查机制势必更依赖语意差异分析、结构化重构辨识、静态检查与契约违反提示,协助人类把注意力集中在真正改变业务逻辑、权限流向与风险边界的地方。[18]

第三层是高保证验证。 对多数一般系统来说,单元测试、整合测试与模拟环境已足够吸收大部分风险; 但在安全关键、金流、基础设施与高合规场景,这些往往不够。 这时更形式化的状态建模、模型检查与规格验证方法,就可能成为必备品。[19]

这一切都指向同一个事实:生成加速了,但验证不会因此自动变简单。 很多时候,它只会变得更重要。

九、乐观主义的边界

坊间流传很多乐观派说法。 像「AI 明天就会取代工程师」这种口号不必认真对待,真正需要认真回应的,是它的强化版本:真实软件工程benchmark确实在快速进步,代理式 coding 正在逼近大规模可用门槛。

的确,以 Copilot 的实验来看,生成式工具已经能在受控任务中带来明显的速度提升。[20] 而从 SWE-bench 这类更贴近真实 issue resolution 的 benchmark 来看,代理式 coding 也确实已经跨过了早期那种「只能做玩具题」的阶段。[21]

但也正因为能力上升得够快,benchmark 本身开始暴露出另一层问题。 OpenAI 在 2026 年不再把 SWE-bench Verified 视为前沿能力的好指标,并不是因为它不重要了,而是因为模型越接近高分,测试设计缺陷、数据污染与任务定义模糊,就越会主导最后的评估结果。[22]

所以,这不是一份单纯的捷报,更像是一份压力测试报告:当模型还不够强,大家关心它会不会做; 一旦模型开始会做,大家才突然发现,真正决定结果能否信任的,是测试到底有没有设计好、规格到底有没有写清楚、验证到底有没有跟上。

别再说「工程快要不重要了」,应该要说「当模型更强时,规格、测试与 benchmark 设计反而变得更重要」。 一旦能力上来,先暴露出来的不是工程不再需要,而是验证与治理的缺口被照得更亮。 这恰恰回到本文的中心命题:能力提升,没有让治理退场,反而把治理的必要性放大了。

你的治理能力,有跟着提升上来吗? 这才是值得担心的。

结论

历史是良师。 当年从汇编语言过渡到C语言,人类并没有完全放手,而是在更高的抽象层级上重新建立了约束体系:结构化编程、模块化、类型系统。 这些约束不是为了限制编译器,而是为了确保人类仍然能在必要时理解和控制系统。

LLM 时代的转折也很类似。 「把边界限缩到可掌握的颗粒度」这个原则没有消失,只是往上迁移到更高的抽象层级:从「人类要看懂每一行代码」,迁移到「人类要看懂每一个模块的意图与契约」,再到「人类要看懂系统的架构决策与约束框架」。

想把这一轮变化看清楚,要先问对问题。 不要再问「AI 会不会取代编程」——那是一个太粗、太浅、也太容易把讨论带偏的问题; 真正值得问的是:谁在定义规格? 谁在验证结果? 谁在控制权限? 谁在承担后果?

这四件事没有被设计好,模型越强,风险只会越大。 这四件事被设计好了,模型越强,工程收益才可能真正放大。

至于将来是否会出现像 AlphaGo 那样彻底超越人类认知框架的时刻? 也许会。 但在那之前,我们需要的不是盲目的信任,或盲目的不信任,而是像编译器时代一样,在新的抽象层级上,重新建立一套人类能够理解和掌控的约束体系。 只是这次,那套约束体系的名字可能叫做 harness、validation loop、architectural guardrails,而不是 structured programming 和 SOLID。

  1. 1. Liu, Fang, et al. “Exploring and Evaluating Hallucinations in LLM-Powered Code Generation.” 2024. 
  2. 2. Zhang, Ziyao, et al. “LLM Hallucinations in Practical Code Generation: Phenomena, Mechanism, and Mitigation.” 2024. 
  3. 3. Anthropic. “Building Effective AI Agents.” 2024/2025. 
  4. 4. Shavit, Yonadav, et al. Practices for Governing Agentic AI Systems. OpenAI, 2023. 
  5. 5. Google DeepMind. Frontier Safety Framework 2.0, 2025. 
  6. 6. Silver, David, et al. “Mastering the game of Go with deep neural networks and tree search.” Nature 529 (2016): 484–489. 
  7. 7. Silver, David, et al. “Mastering the game of Go without human knowledge.” Nature 550 (2017): 354–359. 
  8. 8. Mankowitz, Daniel J., et al. “Faster Sorting Algorithms Discovered Using Deep Reinforcement Learning.” Nature 618 (2023): 257–263. 
  9. 9. Steinberger, Peter. “Shipping at Inference-Speed.” 2025. 
  10. 10. Laban, Philippe, C.-S. Wu, et al. “LLMs Get Lost In Multi-Turn Conversation.” 2025. 
  11. 11. Nanjundappa, Bhargav Chickmagalur, and Spandan Maaheshwari. “Context Branching for LLM Conversations: A Version Control Approach to Exploratory Programming.” 2025. 
  12. 12. Fowler, Martin. “Mocks Aren’t Stubs.” 2007. 
  13. 13. Freeman, Steve, and Nat Pryce. Growing Object-Oriented Software, Guided by Tests. Addison-Wesley, 2009. 
  14. 14. He, Lehan, et al. “Use Property-Based Testing to Bridge LLM Code Generation and Validation.” 2025. 
  15. 15. “Differential Testing with LLMs using Natural Language Specifications and Code Artifacts.” 2025. 
  16. 16. Jain, Naman, et al. “LLM-Assisted Code Cleaning For Training Accurate Code Generators.” 2023 / ICLR 2024. 
  17. 17. Perrone, Giuseppe, et al. “WebAssembly and Security: A Review.” 2024. 
  18. 18. Tsantalis, Nikolaos, Ameya Ketkar, and Danny Dig. “RefactoringMiner 2.0.” IEEE Transactions on Software Engineering 48, no. 3 (2022): 930–950. 
  19. 19. Lamport, Leslie. Specifying Systems: The TLA+ Language and Tools for Hardware and Software Engineers. Addison-Wesley, 2003. 
  20. 20. Peng, Sida, et al. “The Impact of AI on Developer Productivity: Evidence from GitHub Copilot.” 2023. 
  21. 21. SWE-bench. Official Leaderboards. 
  22. 22. OpenAI. “Why SWE-bench Verified no longer measures frontier coding capabilities.” 2026. 
本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » AI 会写程序之后,软件工程真正变贵的是什么

猜你喜欢

  • 暂无文章