当 AI 写代码后,我们现在写什么
2023 到 2026 年之间,软件行业发生了一件根本性的变化,但几乎没人真正把它说透。
工程师不再只是写代码。
工程师开始描述代码应该做什么。
键盘还是那块键盘,IDE 还是那个 IDE,但我们留在代码仓库里的核心产物,已经向上抽象了一层。
代码变成了意图的副产品,而不是意图本身。
行业开始迷恋 SDD,也就是 Spec-Driven Development。
它的核心是:
规格说明,而不是代码,成为最重要的工程产物。
GitHub 推出了 Spec Kit,AWS 推出了 Kiro,Tessl 以“代码是规格说明编译后的二进制产物”为核心叙事,融资总额达到 1.25 亿美元。
大家终于在一件事上达成一致:
规格说明变成了第一产物。
但问题是:
到底是哪一种规格说明?
图中用两列对比了 2015 年和 2026 年工程师角色的变化:2015 年,人类主要产出代码;2026 年,人类主要产出规格说明。但这个规格说明应该长什么样,仍然是个开放问题。
这就是 2015 到 2026 的范式迁移。
工程师正在软件生产栈中站得更高。而“规格说明长什么样”,也开始变成一个职业身份问题。
Andrej Karpathy 把这个变化称为 Software 3.0。
在这个新时代里,源产物不再是代码,而是用自然语言描述的意图。
他在 2023 年写过一句很火的话:
“最热门的新编程语言是英语。”
他说对了。
但这句话的讽刺意味,是后来才慢慢显现出来的。
因为英语、波兰语、中文,以及所有自然语言,本质上都是模糊的。
这种模糊性曾经是人类沟通的优势。
但当沟通对象变成 AI Agent,它就成了最大的弱点。
OpenAI 的 Sean Grove 在《The New Code》这场被广泛讨论的演讲里,说得更尖锐:
规格说明,而不是提示词,也不是代码,正在成为编程的基本单位。
如果他说得对,那么 2026 年每个技术负责人都必须回答一个以前不需要认真回答的问题:
当文档的读者不再是拥有 10 年业务经验的资深工程师,而是一个拥有 20 万 token 上下文窗口、却没有任何组织记忆的 Agent,这份文档应该长什么样?
默认选择为什么会失败
大家对方向达成共识,不代表对形态达成共识。
规格说明到底是什么?
是 Jira 卡片上的 User Story?
是 OpenAPI 文件?
是一份 80 页的自然语言文档?
还是 Markdown 里的架构宪法?
今天这些东西都被叫作 SDD。
而大多数团队并不是经过深思熟虑后选择其中一种,而是靠习惯。
差异恰恰来自这种“默认漂移”。
这也解释了为什么三个团队都在用 Cursor,最后却得到三种完全不同的生产力结果。
当你问:
“规格说明里应该写什么?”
最自然的回答是:
“就写我们以前一直写的那些:SRS、HLD、LLD。”
这正是会失败的答案。
传统工程文档不够用了
经典工程产物的层级结构,过去三十年一直是我们的职业字母表。
BRS,Business Requirements Specification,业务需求规格说明,从组织视角描述业务需求,通常是 SRS 的前置文档。
SRS,Software Requirements Specification,软件需求规格说明,经典工程文档,用来描述功能需求和非功能需求,通常是 50 到 200 页的长篇文字。
HLD,High-Level Design,高层设计,描述系统组件及其交互关系。
LLD,Low-Level Design,低层设计,描述模块内部结构,比如类、方法和调用顺序。
理论上,这套层级非常漂亮。
但过去二十年里,它之所以能工作,主要是因为资深开发会自动填坑。
这四类文档本来都应该是无歧义的。
但现实里,它们永远有洞。
这些洞靠什么补?
靠领域记忆。
靠走廊里的临时聊天。
靠“你知道我意思吧”。
靠一个老员工突然来一句:
“这个客户以前不是这么玩的。”
但 AI 没有这些东西。
它不会在走廊里偶遇产品经理,也不会假装知道自己不知道的东西。
图中展示了从松散 PM 备注到详细 LLD 的七层规格说明光谱。缺失的层,正好位于 SRS 和 HLD 之间。
每一层都会以不同方式失败。
真正缺的是中间那一层:
既不是业务空话,也不是技术细节。
两类错配
第一个问题:
BRS 和 SRS 对 AI 来说太松了。
随便打开你团队过去五年里通过评审的一份 SRS,你很可能会看到这样的句子:
“系统应提供安全认证能力。”
资深开发看到这句话,会点点头。
他知道这里的“安全认证”指的是 TOTP 形式的 2FA,因为这个客户有 PSD2 合规要求。
但 Coding Agent 没有这些背景知识。
它可能生成一个最低复杂度密码规则,然后继续往下写。
因为从它的视角看,代码能编译,逻辑也说得过去。
第二个问题:
HLD 和 LLD 又太技术化了。
在 AI 时代写 LLD,几乎等于自己把代码写了一遍。
你定义类、方法、调用顺序。
这时 AI 的价值被你吃掉了,因为 80% 的设计工作已经由你完成。
HLD 虽然停留在组件和接口层面,但它不定义业务功能级别的行为。
它告诉你系统由什么组成。
但没有告诉你系统到底应该做什么。
今年有一个行业基准测试给出了实证证据:当需求中故意嵌入歧义时,LLM 生成代码的质量会明显下降。
结果非常明确:
歧义会稳定地降低所有被测模型生成代码的质量。
而且越高级的模型,损失反而越明显。
因为它们会更“聪明”地填空,也更有创造性地猜错你的真实意图。
模型不能自己识别并解决歧义。
越聪明,它就越会把缺失信息补成另一个看似合理、但并不是你想要的东西。
根据我的经验,凡是抱怨 “AI Slop”、每个需求要来回迭代三四轮的团队,结构性问题都一样:
不是提示词不行。
不是模型抽风。
而是输入格式错了。
传统文档无法同时满足 AI Agent 的执行契约需求:
SRS 太松。
LLD 太细。
松散 User Story 又太浅,导致 Agent 会自行发挥所有边界条件。
SRS 和代码之间,缺了一层。
这一层应该描述业务功能级别的行为。
它要精确到 Agent 能实现。
又要清晰到 PM 能审批。
既然传统文档不合适,松散用户故事又太浅,那么中间缺的到底是什么?
答案其实已经 22 岁了。
BDD:那个缺失的语言层
“我的语言边界,就是我的世界边界。”
—— 路德维希·维特根斯坦
2003 年圣诞夜,Dan North 注册了 jbehave.org 域名,并写下了一个打算替代 JUnit 的工具的第一行代码。
他当时不是想发明一种新的测试形式。
他是在解决一个教学问题。
他发现自己教开发者 TDD 时,大家总是卡在 “test” 这个词上。
于是 North 把 “test” 换成了 “behavior”。
神奇的是,一整类“到底该测什么”的问题突然消失了。
写行为是自然的。
写测试不是。
从这个教学实验里,诞生了 BDD,也就是 Behavior-Driven Development。
它是一种用自然语言描述系统行为的方法,业务人员能读,机器也能执行。
核心形式就是 Given / When / Then 场景。
过去二十多年,BDD 走过了一条很戏剧化的曲线:
2015 年达到流行高峰。
2018 到 2024 年长期衰退。
SmartBear 移交 Cucumber,Tricentis 终止 SpecFlow。
然后到了 AI 时代,BDD 意外复兴。
这不是巧合。
也不是因为 BDD 突然“变好用了”。
而是因为 BDD 从一开始就为之设计的那个读者,终于出现了。
一个 Given / When / Then 场景的结构
BDD 的魔法,全部藏在一个场景的三段式结构里:
Feature: ATM cash withdrawal
Scenario: Sufficient balance
Given the account balance is $100
And the card is active
When the customer requests a $20 withdrawal
Then the ATM dispenses $20
And the account balance is $80
这是 Gherkin。
它是 .feature 文件里用于书写 BDD 场景的 DSL,基于 Given / When / Then 关键词。
这个语法和单元测试里的 AAA 模式非常接近:
只不过这里不是代码断言,而是业务领域语言里的句子。
三行就够了。
PM、客户、BA、测试、开发都能理解同一件事。
Coding Agent 也能明确知道他们到底理解了什么。
Gherkin 真正强大的地方,是它可以双向阅读。
PM 坐在评审会上,把这个场景当作故事来读,然后点头。
因为这里是业务语言:
balance、withdrawal、card。
不是技术黑话。
与此同时,BDD 框架,比如 Cucumber、Reqnroll、Behave,会解析这个场景,把每个 step 映射到 step definition。
step definition 就是把 Gherkin 文本连接到可执行测试实现的代码。
同一份文档,两个读者。
业务把它当故事。
机器把它当契约。
中间不需要翻译。
可以想象一个中间是 Gherkin 场景的图示,上方箭头指向业务人员,下方箭头指向 AI 解析器。
同一个场景,两个受众。
业务读它像故事,机器读它像契约。
为什么 AI 移除了 BDD 最后一块障碍
历史上,BDD 最大的成本很高:
必须有人手写 step definition,并且长期维护它们和代码的一致性。
这是团队最终都不想做的活。
也是 Cucumber 在 2019 年左右衰落的重要原因。
但在 2026 年,AI 可以根据场景自动生成 step definition。
这几乎移除了 BDD 历史上唯一真正沉重的维护成本。
实证数据也很清楚:
把 BDD 场景作为 LLM 输入,相比非结构化自然语言,pass@1 提升了 15.1%。
pass@1 指的是模型第一次尝试就解决编码任务的比例。
关键观察在于:
BDD 正好位于 SRS 和 HLD 之间的精度轴上。
它工作在用户行为层。
而这正是 Coding Agent 最需要的粒度,因为业务歧义就藏在那里。
它不像 User Story 那么松。
不像 HLD 那么技术化。
也不像 LLD 那么机械细节化。
它命中了一个软件工程过去从未正式定义过的甜点位。
因为以前,我们还不需要在这一层放一个可执行产物。
Cucumber 的创造者 Aslak Hellesøy 曾经说过一句很有挑衅性的话:
“BDD 不是测试自动化,而是协作式需求分析结合 TDD。”
他说对了。
但只说对了一半。
BDD 两者都是。
而在 AI 时代,这种双重性会变成一股非常强的经济力量。
一个场景,五层测试
“完美不是无可增加,而是无可删减。”
—— 安托万·德·圣埃克苏佩里
真正有意思的地方来了。
AI 时代 BDD 的真正威力,并不在于生成的规格说明质量更高,也不在于生成代码更快。
而在于:
一个产物,消灭了三个独立流程。
业务规格说明。
测试计划。
技术文档。
这种压缩,才是行业真正的革命。
不是更好的提示词。
五层测试扇面
继续看 ATM 场景。
一个余额为 100 美元的客户请求取款 20 美元,ATM 吐出 20 美元。
三行 Gherkin,可以展开成五层验证。
第一层,单元测试。
逐个验证每个步骤是否独立正确。
比如账户扣款在各种金额和边界条件下是否正确。
第二层,集成测试。
把一组步骤和 mock 的 ATM 后端放在一起,验证是否正确调用授权流程。
第三层,E2E 测试。
在真实测试环境里,用真实数据库跑完整场景。
第四层,UAT。
业务人员在 UAT 环境里点击同一个场景,并确认它符合预期。
第五层,回归测试。
这个场景在每次部署时运行,防止未来改动破坏已有行为。
五种粒度。
五层验证。
一个源文件。
可以想象一个中心 Gherkin 场景向外生成五层测试的示意图:unit、integration、E2E、UAT 和 regression。
BDD-AI 之前:
五份产物,五个人,几周工作。
BDD-AI 之后:
一个场景,AI 把后续全部扇出。
生产数据与概念历史
这不是空想。
AutoUAT pipeline 在一个行业案例中已经实现了这个流程。
这个案例来自 Critical TechWorks,也就是 BMW Group 与 CRITICAL Software 的合资企业。
它的流程是:
User Story → Gherkin Scenario → Cypress / TypeScript Test Script。
结果:
95% 生成场景被认为有帮助。
92% 测试脚本被认为有用,其中 60% 无需任何修改,其余部分经过修正或重新生成后可用。
单个脚本平均成本为 0.12 欧元。
这不是“AI 稍微提效一点”。
这是软件生产从未见过的经济不对称。
有意思的是,这背后的思想已经 25 岁了。
Specification by Example,也就是“实例化需求”,由 Gojko Adzic 在 2011 年的书中系统化表达,并获得 2012 年 Jolt Award。
它的核心是:
通过具体、可执行的行为示例来描述需求。
Adzic 定义了六个把规格说明和测试连接起来的关键模式:
从目标推导范围。
协作式规格说明。
用例子说明。
自动化验证。
频繁验证。
演进式文档系统。
这个想法等了四分之一个世纪,才终于等到经济上可行的时代。
因为它真正缺的不是理念。
而是 AI 解决了手动维护 step definition 的成本问题。
当场景可执行,并且在 CI/CD 中通过时,它就是技术文档。
Living Documentation,活文档。
它永远保持最新,因为它同时也是可执行测试。
一旦它不再通过,它就不再是文档。
这正是传统工程文档永远无法保证的质量。
因为传统文档和代码是断开的。
双重价值的经济学
把账算一遍,规模会非常残酷。
一个典型电商功能,在旧世界里:
分析师写 SRS,20 小时。
测试写测试计划,30 小时。
技术写文档,10 小时。
不同产物之间同步,再消耗 20 小时。
总计 80 小时人工工作。
涉及三个专业角色。
横跨几周日历时间。
在 BDD-AI 模式里:
Three Amigos 一起用 3 小时写 Gherkin 场景。
然后 AI 在 API 时间里把它展开成五层测试。
成本按每个脚本几欧元计算。
根据我基于 AutoUAT 案例数据和典型项目工作量的计算,不同领域里,每个功能的成本降低可以达到 60% 到 80%。
我直说:
这不是“AI 帮我们提速”。
这是 AI 消灭了五个产物里的四个。
到这里,关于 AI 生产力的讨论就不再“有趣”了。
而是变得紧急。
AI 时代的 Three Amigos
把 BDD 作为规格层引入现有 SDD 工作流,不需要新工具,也不需要高层批准。
你只需要一个 30 分钟的 Three Amigos 会议。
Three Amigos 是 2009 年形成的 BDD 实践:
业务、开发、测试三个角色,在实现前围绕一个场景进行讨论。
它还需要一个产物层级变化:
以前是:
SRS → User Story → Code
现在是:
BDD Scenario → AI 生成代码和测试 → CI/CD 执行
三个人。
每周 30 分钟。
一个 .feature 文件。
足够了。
可以想象一个示意图,PM、开发、测试三个角色围绕同一个 Gherkin 场景协作,随后流向 AI 生成代码和测试。
AI 时代的 Three Amigos:
30 分钟协作写场景。
API 时间生成完整测试扇面。
文档永远保持最新。
这个仪式的五个阶段
第一阶段:Discovery,5 分钟。
PM 讲故事:
“银行 App 里的客户想查看自己储蓄账户的余额。”
测试立刻追问边界条件:
账户不存在怎么办?
Session 过期怎么办?
客户有多个账户怎么办?
开发问契约:
账户列表从哪里拿?
标识符格式是什么?
这 5 分钟的产物,是一组要写的场景,每个场景都有清晰上下文和动作。
第二阶段:Formulation,15 分钟。
把每个场景写成 Given / When / Then。
三个人一起,在屏幕上,写进 .feature 文件。
使用业务领域语言,而不是技术黑话。
验证方式非常粗暴:
把场景大声读出来。
听起来是否自然?
三个人是否都点头?
必须使用具体值,而不是抽象表达。
写:
Given a customer with a balance of $1,000
不要写:
Given a customer with a positive balance
具体值,才是 AI 最容易理解的东西。
第三阶段:AI Generation,API 时间。
把场景交给 Agent。
可以是 Claude Code、Cursor、Copilot Workspace。
Agent 生成实现、step definition、单元测试和集成测试。
有个关键细节:
Agent 的上下文里应该有 CLAUDE.md 或 AGENTS.md。
这是仓库里的 Markdown 文件,Agent 会把它当作项目架构原则的持久规格说明读取。
它充当跨会话的护栏。
那些你不想每次 prompt 都重复的规则,应该放在那里。
第四阶段:Verification,10 分钟。
测试在 E2E 中运行场景。
业务在 UAT 环境里点击 UI。
Cucumber / Reqnroll 生成业务可读报告:
Sufficient balance: PASS
Account doesn’t exist: PASS
同时开启自验证循环。
这应该成为 Agent 实现后的强制步骤:
它必须把结果和规格说明逐项对比,并确认所有需求都已满足。
这个步骤能消灭大部分“差不多能跑”的迭代。
而这些“差不多”,正是今天吞掉 Sprint 的黑洞。
第五阶段:Living Documentation,自动完成。
CI/CD 里的场景就是文档。
任何破坏场景的代码变更,都会阻止合并。
文档按定义永远是当前状态。
不会再出现:
代码做 A。
文档说 B。
最后只能找资深开发猜哪个才是真的。
什么时候用 Three Amigos,什么时候 Vibe Coding
我这几个月一直在用一个简单启发式规则:
如果功能有清晰业务行为,比如 CRUD、决策流、表单、权限控制,那么 Three Amigos 必须做。
如果是 50 行以内的 Bug Fix,或者探索型原型,Vibe Coding 仍然有意义。
关键不是谁更高级。
关键是有意识地选择,而不是被默认习惯拖着走。
以前,资深开发会凭直觉填坑。
AI 时代,这种奢侈没了。
在云栈社区,我们一起探讨 AI 时代的软件工程实践,欢迎分享你的见解与实战经验。