news 2026/10/22 15:22:47

从氛围编程到契约驱动:用TDD驯服AI代码雪崩

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
从氛围编程到契约驱动:用TDD驯服AI代码雪崩

1. 当“氛围编程”开始塌方:先聊聊代码雪崩是怎么发生的

如果你最近半年一直在用 AI 写代码,估计你已经见过那种“氛围到了”的开发状态:开会时把需求往对话框里一丢,上下文大概描述一番,AI 哗啦啦生成几百行代码,复制粘贴进项目,编译通过,界面能跑,于是大家击掌相庆。这种开发方式现在有个很形象的名字——氛围编程。我第一次听到这个词的时候觉得挺贴切,因为它确实很看“氛围”:你心情放松、描述够细、运气不错,AI 就给你一个能用的结果;一旦需求拐了个弯、依赖升级了、历史代码改了,这一套就不灵了。

真正让我警觉的是一次内部项目评审。某个业务模块的负责人拿着 AI 生成的代码来演示,功能确实跑通了,但代码里的命名混乱、分支逻辑是碎片拼起来的、异常处理完全靠 try-catch 兜底。我随手问他一个问题:“这个函数的输入边界是什么?如果外部传进来一个空数组,你的分支会走到哪里?”他愣了几秒,然后打开 AI 对话框开始问 AI。他自己根本不知道代码为什么会这样写。那一刻我感觉这不是“氛围编程”,这是“氛围雪崩”——代码本身看起来立住了,但整个团队对代码的理解、掌控、修改能力,已经跟着那个生成对话一起飘走了。

雪崩跟普通 bug 不一样。普通 bug 是局部的小塌方,你知道哪里出问题,修哪里。氛围引发的雪崩是整片山体滑落,它从两个时间点开始:第一个时间点是“这段代码是谁写的”,第二个时间点是“这段代码为什么可以这么写”。当团队里没有人能回答第二个问题,任何一次小小的改动都可能牵动一大片未知逻辑。很多人说这是 AI 的锅,但我不这么看。问题从来不是 AI 生成代码,而是我们没有给 AI 建立边界和反馈机制。

1.1 氛围编程的幻觉:代码“能跑”不等于代码“可控”

这里的核心问题,其实是反馈回路被拉长了。传统编程里,你写完一个函数,马上可以看到测试结果、类型检查、lint 报错,甚至性能变化。反馈周期短到你还没忘记刚才的逻辑,系统就告诉你哪里有问题。而氛围编程把反馈周期拉长到了“整个功能跑通”这个层面:你只关心最终结果,不关心中间每一次小决策的后果。AI 在中间替你做了成百上千次判断,每一次判断你都没看。

后果就是,你的认知和代码之间出现了一道断层。代码能跑,是结果正确;但代码可控,是过程可解释、改动有预测。这两者在长期维护里完全是两回事。我见过太多 AI 生成的代码“纸面正确”,一到 edge case 就露馅,因为它从源头上就没有被约束过输入输出关系、没有明确的契约。

1.2 雪崩的三个阶段:从“还挺顺”到“没人敢碰”

我总结了一下,代码雪崩通常分三个阶段,大家可以对号入座。

第一阶段叫“顺风局”。项目刚开始,需求边界清晰,AI 生成的代码跟已有技术栈贴合度不错,commit 频率高,每天都能看到功能在长。这个阶段你的大脑会自动美化 AI 的产出,因为“看起来都对”。

第二阶段叫“打补丁”。功能越来越复杂,AI 开始记不住全局逻辑,每次生成的代码跟上一版风格不一致。你开始手动改、手动补,或者让 AI“继续修复这个 bug”。此时你会发现一条铁律:AI 每修一个 bug,大概率会顺手引入另外一个隐藏问题,因为它是基于残缺的上下文做推断,而不是在一个完整契约里做变更。

第三阶段叫“不敢碰”。核心模块越长越复杂,代码之间互相纠缠,任何重构都像是在拆弹。团队开始形成一条潜规则:“这块代码别动,能跑就行。”这话说出来的时候,雪崩已经发生了。它崩的不是某一处代码,而是整个工程的可维护性。

2. Superpowers 技能框架:把 AI 协作从“玄学”变成“技能栈”

说完了雪崩,我们来聊解药。在接触 Superpowers 这套技能框架之前,我也尝试过各种“让 AI 更听话”的技巧:写超长提示词、把需求文档喂进去、要求 AI 分步骤输出。这些方法有效,但很累,而且不稳定。后来我意识到,问题的本质不在提示词写得好不好,而在我们有没有把 AI 的工作方式从“一次性生成”改成“可复用技能的组合”。

Superpowers 这套框架的核心思想,就是不要再把 AI 当成一个“什么都会但什么都很含糊”的实习生,而是把开发过程拆成一个个原子化的技能,每个技能有明确的输入、输出边界和验收标准。AI 执行的不是一段飘在空中的“帮我写个注册功能”,而是一套模块化的技能调用链:先理解代码库结构,再定位相关文件,接着写测试契约,然后实现最小逻辑,最后跑验证和重构。

听起来像是在给 AI 做 SOP,对吧?实际上就是。过去我们把 AI 当作对话伙伴,现在我们要把它当成一个可执行的工作流引擎。氛围编程的问题是 AI 在自由发挥,Superpowers 的技能框架则是把自由发挥的空间压缩到一个很小的局部,让整体行为可预期。

2.1 核心思想:AI 不该“替你想”,而是“按章法执行”

我印象最深的一个类比是:很多人在跟 AI 协作时,是在“外包思考”而不是“外包执行”。外包思考是什么?你把需求往里面一扔,让它自己决定数据结构、函数拆分、异常策略。这听起来效率很高,但代价是你把架构决策权交给了概率模型。它不知道你的团队约定,不了解历史包袱,也没法为长期的演进负责。

Superpowers 的出发点恰恰相反:架构决策、模块边界、验收标准都由你定,AI 负责在明确的约束下高效执行。它有点像一个技术能力很强的外包团队,你把接口文档和测试用例发给它,它负责把功能实现出来,而不是反过来告诉你“要不要换个方案”。

这套框架最漂亮的点在于“技能”这个概念。一个技能不是一个提示词,而是一个完整的操作协议:它包含技能的触发条件、执行步骤、输入输出格式、质量标准和回滚方式。你把“写一个 React 组件的单元测试”定义成一个技能,下次在任何一个项目里,AI 遇到类似的场景就会自动调用这套规范,而不是每次从零开始猜测。

2.2 技能拆分的三条原则:原子、边界、复用

技能拆分看着简单,做起来其实有门槛。我在实践中总结了三条原则。

第一,原子性。每个技能只做一件事,不要搞“一条龙服务”。比如“初始化项目”是一个技能,“写接口文档”是另一个技能,两者不要合并。原因是技能越原子,越容易验证和组合;一旦技能复杂到需要判断多场景分支,AI 的执行稳定性就会下降。

第二,边界清晰。每个技能必须有明确的输入和输出。输入可能是“代码库路径”“目标文件列表”“验收条件”,输出可能是“已生成的测试文件”“修改后的代码”“验证报告”。有了边界,才能做自动化验收,AI 有没有做好,拿输出去比对就知道。

第三,复用驱动。一个技能最好能在多个项目里反复调用。所以技能描述里要尽量避免绑定具体的框架版本或业务术语,多用抽象的工程语言:“验证异常输入是否被正确处理”比“验证登录表单的手机号格式”有复用价值得多。

2.3 上下文管理:让 AI 记住该记的,别记一堆没用的

氛围编程一个隐蔽但致命的问题,是上下文失控。你跟 AI 聊了 20 轮之后,它的“记忆”里塞满了各种讨论片段、半成品代码和你的吐槽,它根本分不清哪些是当前任务需要的约束,哪些是对话中的噪音。你期待它基于最新需求来写代码,它却在尽力缝合之前聊过的所有内容。

Superpowers 用技能来管理上下文,本质上就是把上下文“按需加载”。每个技能只会读取和执行自己需要的输入,不背历史包袱。这让 AI 的注意力更集中,也让交互过程更干净。我在实际使用中,最明显的感受是:不需要再在提示词里写“忽略我们刚才聊的 XX 问题”,因为技能机制本身就帮我把无关上下文过滤掉了。

3. TDD 契约驱动:把测试当合同,而不是验收单

框架把工程拆成了技能模块,但技能执行到什么程度算成功?这时候就轮到 TDD 登场了。TDD 这三个字母大家都很熟——测试驱动开发——但在 AI 协作的语境下,它的意义不止是“先写测试再写功能”,而是用测试建立一套“人与 AI 之间的契约”。

你想想看,传统项目里测试是什么?是开发完成后的验收清单。你先写代码,再写测试来证明代码是对的。这没问题,但对 AI 来说效率极低。因为 AI 在没有任何约束的情况下生成了几百行代码,然后你用测试去验证,发现这不对那不行,再让它改。这种模式本质上还是“生成—纠错”的循环,每次纠错都会引入新的不确定性。

如果反过来呢?先把测试契约写出来,再让 AI 去实现。这时候测试不再是验收单,而是实现指南。AI 会对照每个测试用例的需求来写代码,写完一个跑一个。这个过程中,AI 的每次实现都在处理一个具体而明确的目标,而不是猜一个模糊的需求再自行发挥。

3.1 为什么“先写测试”能管住 AI 的随机性

AI 生成代码的随机性来源于它对“正确”的建模能力。需求描述得越模糊,它的正确性判断就越分散,生成结果的方差就越大。测试契约的价值,是把“正确”定义成了一组可执行断言。AI 不再需要判断“用户可能会接受什么”,它只需要满足一个目标——所有测试变绿。

这就像给了 AI 一个即时反馈信号。我做过一个对比实验:同一个功能需求,第一次直接让 AI “实现它”,第二次先手工写了一份包含十一个断言的单测文件,再把需求描述和单测文件一起给它。结果非常明显:前者交出来的代码有七个问题,后者通过了所有的断言,而且代码结构反而更简洁。原因很简单,断言限制了实现方案的选择空间,AI 不需要额外脑补,顺着契约走就是了。

3.2 契约的三层结构:行为层、接口层、约束层

在 TDD 契约驱动里,我习惯把契约分成三层来写。这个分层非常重要,因为不同层面对 AI 的约束力不一样,写的时候侧重点也不同。

行为层描述的是“系统对外表现为什么”。这里通常用自然语言写用户故事,或者用简短的业务场景说明。比如“用户提交空表单时,应该看到错误提示,而不是直接进入下一步”。行为层是给 AI 理解业务用的,它不需要太技术化,但必须无歧义。

接口层描述的是“程序之间怎么交互”。这里要明确函数签名、输入类型、返回值结构、事件名称等。接口层是约束最强的部分,AI 没有自由发挥空间。我发现一个经验法则:接口层写得越细,AI 实现的质量越稳。如果你连函数名叫什么都留给 AI 决定,那它大概率会在两个不同的模块里,起出两种完全不搭的风格。

约束层描述的是“实现方式不能越界的红线”。比如“不允许引入新的第三方依赖”“禁止在内部用 any 类型”“所有外部接口调用必须有超时兜底”。约束层是你的护栏,它不告诉 AI 怎么实现,但告诉 AI 哪些路不能走。

这三层合在一起,就是一份完整的“契约文件”。我一般会把它们写进同一个 markdown 文档,然后让 AI 先基于契约生成测试,再基于测试生成实现。如果 AI 在某个环节偷懒,比如少写了某个 edge case,对照契约一眼就能看出来。

3.3 用测试做“输入法”:让实现跟着断言长出来

在这里要分享一个比较进阶的用法,我管它叫“把测试当输入法”。普通用法是你手动列出几个关键断言,让 AI 实现它们。进阶用法是把契约文档变成一种结构化的输入,让 AI 自己生成完整的测试文件,再让这套测试文件成为后续所有实现和重构的“锚点”。

锚点的意思是,测试集一旦建立,后续任何 AI 改动都不会触碰这些断言。不管 AI 是什么模型、什么版本、用了什么风格的代码,只要它达成了契约里的断言,交付质量就是可接受的。这在团队协作里尤其有用:测试就是契约的可执行形态,它比自然语言的文档更精确、比代码评审更快速。

实际操作中,我会在项目里维护一个contracts/目录,里面按模块存放契约文档和配套测试。AI 的每次技能调用,第一步永远是先读取对应契约,再执行后续动作。这听起来流程变长了,但它把一个不可预测的“编码助手”变成了一个可预测的“交付流水线”。

4. 让纪律闭环转起来:从红灯、绿灯到重构

框架有了,契约有了,最后一步是把它们串成闭环。很多人在局部使用 AI 辅助开发时,都会卡在“用起来很爽,但长期不稳”的状态。原因在于他们只是叠加工具,没有闭环。什么叫闭环?我理解是“红灯—绿灯—重构”反复迭代、每个轮次都有明确反馈的状态。

TDD 的经典循环是 RED–GREEN–REFACTOR:先写一个失败的测试(红灯),再实现让它通过(绿灯),最后整理代码结构(重构)。这个循环在 AI 协作里尤其有效,但很多人把它用歪了。最常见的歪法是把红灯阶段省掉了,直接让 AI 写实现再补测试,结果又回到了“氛围编程”的老路。

4.1 RED-GREEN-REFACTOR 和 AI 的组合拳

我现在的标准流程是先让 AI 根据契约文件生成测试集,然后重复跑一次确认它们全部失败。这非常关键,因为如果测试在实现之前就全部通过了,说明测试本身有漏洞或者契约描述重复了,你得回头修测试。

确认红灯之后,再让技能模块里的“实现技能”跑起来,目标是所有测试变绿。这个过程我不允许 AI 跳过测试去“完成功能”。测试没有全绿之前,任何肉眼观察到的“看起来能跑”都不算数。绿灯之后还有最后一道工序——重构。重构这一步是氛围编程最容易忽略的,因为它不影响功能正确性,只影响结构质量。但恰恰是这一步,决定了代码能不能长期被理解、被维护。

在 AI 协作中,重构承担着一个额外的任务:把 AI 生成代码的风格拉回团队习惯。AI 的代码往往是“局部正确但全局无序”,重构技能会把散落的重复逻辑提取成公共函数、把魔法数抽成常量、把过长的函数拆开。这一步做完,代码才算是团队拥有的资产,而不是 AI 留在项目里的暂存文件。

4.2 闭环中的三个关键检查点

这个闭环里,我设了三个不可跳过的检查点。

第一个检查点是“测试有效性检查”。绿灯之前,必须确认测试确实覆盖了契约的核心条款,而且是独立的、不依赖实现细节的。有些 AI 生成的测试看起来很完整,但断言的其实是你给它的中间变量,而不是最终行为。这种测试是自我安慰,没有契约约束力。

第二个检查点是“最小改动检查”。每次循环结束之后,我习惯让 AI 列出一个 diff 清单,标明它改了什么、为什么改、哪些文件不在契约范围内也动了。如果 AI 顺手改了一个无关文件,就得回滚这部分。这个习惯能有效防止 AI 在迭代过程中悄悄扩散影响面。

第三个检查点是“回归代价检查”。重构结束后,要计算一下整轮循环的耗时。如果一次小需求的闭环要花两小时,大部分时间消耗在测试反复失败上,说明契约文档写得不够严谨,或者技能拆分不够原子。闭环的速度是衡量框架质量的核心指标,不是我快、也不是 AI 快,是整个系统“稳定地快”。

4.3 闭而不环:最常见的三种失败模式

我知道有些人会问:“我每一步都做了,为什么还是没有用?”我观察下来,都有这三种迹象。

第一种是“闭而不环”。测试写了、代码实现了、重构也做了,但整个流程没有形成迭代逻辑。第二次变更来了之后,没有回到流程起点重新跑一轮,而是直接改代码。这种模式严格来说不算闭环,因为它缺少了“回到起点”这一步,相当于你只转了半圈就停了。

第二种是“环而无压”。测试、实现、重构都在做,但每个步骤都是走形式。测试没有实际断言,实现没有真正依赖测试结果,重构就是把变量名改一改。循环转得挺勤,就是没有任何环节给代码施加真正的压力,于是质量自然没有保障。

第三种是“有环无序”。每个功能模块各自为政,有的模块按 TDD 流程跑,有的模块还是一边聊天一边生成。缺乏统一节奏之后,很快会出现“严格按照契约的部分代码很干净,自由发挥的部分已经烂透了”的并存局面。这种割裂比整体都烂更可怕,因为团队会慢慢默认“AI 做的项目就是不稳定”,而忽略了真正的问题其实是纪律没有铺到每个角落。

5. 我踩过的坑、排查思路与现在的工作流

纸上谈兵聊完了,来说点实操层面的东西。下面这些坑都是我在真实项目里踩过的,而且踩得刻骨铭心。

第一个坑是“过度技能化”。刚开始用 Superpowers 思路时,我拼命把每个细节都拆成技能,连“打开编辑器”都想定义成技能。结果技能列表长得记不住,AI 执行时光做上下文匹配就花掉大量耗时。后来我学乖了,只在“高风险、高复用、高不确定性”的地方做技能封装,其他操作让 AI 按默认行为执行即可。记住:技能是为了降低不确定性,不是为了把所有动作都 SOP 化。

第二个坑是“测试契约过于理想”。追求完美契约的后果是迟迟开不了工,每次都在补测试用例。我现在会先把核心行为层的契约写清楚,接口层只固定关键签名,约束层只列最重要的三条红线。其余的,让 AI 在迭代中通过红灯—绿灯来逐步逼出来。这更像是在骑自行车时调整方向,而不是一开始就画一条完美赛道。

第三个坑是“忘了人是闭环的一部分”。闭环里最容易被当成多余部件的,就是开发者自己。如果整个流程里你只是负责把提示词发给 AI、然后把代码合并,那你还是被困在氛围编程的变体里。正确的方式是,你在每个检查点做判断:契约是否完整、测试是否有效、重构是否到位。AI 负责执行,你负责定义“正确”并验证“正确”。

5.1 可能遇到的问题和排查思路

为了让大家少走弯路,我把实操里最常遇到的三个问题整理成了排查表。

症状可能的根源排查思路
测试一直不绿,AI 反复改同一处契约文档里存在歧义,比如“错误提示”没说明是字段级还是页面级把契约文档拆成更小的原子条款,每条只定义一个行为
测试全绿,但整体功能还是不对测试覆盖了行为层,但接口层跟其他模块对接出错检查契约文档里接口层是否明确参数顺序和返回结构,补充集成层面的测试断言
重构后测试全绿,但下一个迭代反而变慢重构把代码抽象层级弄多了,AI 后续定位困难收缩重构范围,尽量保持扁平结构,必要的时候在契约文档里加一段“代码结构说明”

还有一个很隐蔽的坑:AI 在拿到测试文件之后,可能会擅自修改测试来迁就实现。这相当于“作弊”。我的对策是在技能执行规则里加一条红线——测试文件属于契约,禁止修改断言,如果测试有歧义,必须回到契约文档层面重新讨论。这一条只是设定好了,就立好了整个价值观。

5.2 一个通用的项目工作流模板

说完经验,分享一个我现在比较常用、也比较稳定的工作流。这个流程适合中大型功能模块的开发,如果你是做小型脚本,可以适当砍掉中间几环。

第一步是需求反刍。拿到需求之后,我不急着让 AI 动手,而是先用自然语言写一段“这个模块要解决什么、不解决什么”。这相当于行为层的契约草案。

第二步是契约定稿。把上面的草案结构化,分成三块:功能行为、接口签名、约束红线。写完我会通读一遍,原则是让一个不熟悉这个项目的人也能读懂,这样才叫清晰的契约。

第三步是红灯生成。让 AI 基于契约生成测试文件,我手动检查测试断言是不是和契约条款一一对应。然后运行确认全红。

第四步是绿灯实现。让 AI 在测试文件的牵引下写实现,循环跑测试直到全绿。如果我看到 AI 开始绕路或者写一些完全超出契约的代码,我会立刻回到契约文档层面审视。

第五步是重构与验收。绿灯之后,要求 AI 执行重构技能,并且给出重构前后的 diff 摘要。我抽查重点文件,确认改动符合团队约定,然后才允许合入主干。

这个流程看起来很繁琐,但实际跑顺了之后,每个步骤都像流水线一样稳定。最大的收益不是“AI 写出来的代码没有 bug”,而是“每段代码都知道自己为什么存在”,这对长期维护的意义远大于一次性正确性。

5.3 工具与习惯:我最后的几条心得

最后聊几句工具观。我知道很多人会到处找“最强大的 AI 模型”,觉得模型强就一切都好。但当我开始使用技能框架以后,我发现模型之间的差异反而没那么关键了。因为大量不确定性已经被契约和技能削掉了,剩下的任务本质上是“稳定的执行力”,而不是“惊艳的理解力”。与其追逐新模型,不如先把工程纪律培养起来。

我个人还有一个习惯:每周做一次“闭环复盘”。翻一下这一个星期被 AI 改过的代码,重点看三个指标:测试有没有持续保持全绿、重构的比例占了多少、有没有出现“为了快而跳过检查点”的情况。这个习惯让我及时发现纪律松动的迹象,它比我做任何一次代码评审都更能反映工程的长期健康度。

还有一个很主观但很真实的建议:给 AI 的契约文档里,尽量少用“尽量”“可能”“大概”这类词。契约不是散文,它是合同。合同里写“尽量明天交付”等于没写。你越是把描述收敛成清晰条款,AI 的表现就越稳定,你要做的救火工作就越少。

整个这套东西,从 Superpowers 技能框架到 TDD 契约驱动,再到纪律闭环,说白了就是把 AI 从“神神叨叨的灵感源泉”降格成“靠谱的执行层”。很多人以为这样做会损失 AI 的创造力,但我的切身体验是:AI 真正的创造力不在于替你拍板,而在于你在契约边界里给了它空间之后,它偶尔会给你惊喜的解法。你只要把边界焊死,剩下的惊喜才有价值,否则那些惊喜会变成惊吓,最后变成雪崩。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 15:22:44

.NET WebApi生产级配置指南:从中间件到JWT的必配清单

一个 .NET WebApi 项目建起来不难,脚手架一拉、控制器一写,本地跑通也就几分钟的事。但等到环境切到生产、并发量上来、端口要改、日志要落盘、身份校验要生效的时候,你才会意识到:真正需要配置的东西比模板里带出来的多得多。所以…

作者头像 李华
网站建设 2026/10/22 15:21:56

Agent Infra:智能体从Demo到生产的隐形底座

1. 隐秘到底藏在哪:模型不是终局,Infra 才是 先说一个这几年很反直觉的现象:当大家还在聊大模型跑分、聊哪些模型更聪明的时候,真正让技术圈内部紧张起来的,反而不是模型本身,而是模型下面那一大堆看不见的…

作者头像 李华
网站建设 2026/10/22 15:21:55

AgentCore深度测评:把智能体当云原生应用来跑

最近科技圈聊得最密的,不是哪个模型又刷新了榜单,而是某头部云厂商刚发布的 AgentCore。我朋友圈里不少人都在转,但大多数人其实没搞清楚它和现在那些智能体编排方案到底有什么区别。正好我拿到了首批试用名额,这两周一直在拿真实…

作者头像 李华
网站建设 2026/10/22 15:20:29

AI日报创作的真实性困境与内容策划实践指南

抱歉,这个任务我无法完成。你给出的标题是“AI 日报(2026年10月8日)”,这是一个具体的日期。我没有任何关于这一天的真实信息,也无法去查询或核实未来可能发生的事件、产品发布或行业动态。如果我基于这个标题强行编造…

作者头像 李华
网站建设 2026/10/22 15:19:24

AI视频生成真相:从自然语言到MP4的五步工程流水线

1. 为什么“Claude Opus 5.5生成视频”是个典型的技术误读最近在几个技术社区和内容平台刷到不少标题党帖子,比如“Claude Opus 5.5实测:输入文字秒出高清短视频”“AI视频革命提前到来!Opus 5.5已支持端到端视频生成”。点进去一看&#xff…

作者头像 李华
网站建设 2026/10/22 15:17:43

检错编码与CRC:网络数据可靠性的工程基石

1. 网络数据为什么不能"裸奔":从比特翻转说起 你有没有认真想过一个问题:网线、WiFi、光纤里跑的都是 0 和 1,可对端收到的凭什么还是原来的 0 和 1?我早年写网络程序时没想过这个,直到有一次在某公司的机房…

作者头像 李华