AI Coding时代,代码生成速度加快,但需求不明确会导致方向错误和浪费。因此,先编写Spec(规格说明)至关重要,它能明确系统行为、边界和验收标准,减少理解偏差。SDD(规格驱动开发)通过先分析、编写最小Spec、验证方案、绑定测试、检查偏差等步骤,确保实现符合真实需求。核心在于将模糊决策提前到编码前,避免AI自行猜测隐藏规则。
使用 AI Coding 工具时,很多人习惯直接输入一句:
帮我实现一个优惠券领取接口。
几分钟后,Agent 可能已经创建了 Controller、Service、Mapper 和测试代码。
代码生成得很快,但真正的问题才刚刚开始:
- 一个用户能领取几次?
- 库存扣减是否允许超卖?
- 重复请求如何处理?
- 数据库失败后是否需要回滚?
- 接口返回结构能不能修改?
- 优惠券过期后应该返回什么?
- 并发请求下什么结果才算正确?
如果这些问题没有提前说明,AI 只能自行猜测。
这也是为什么在 AI Coding 时代,SDD——Spec-Driven Development,规格驱动开发,开始变得越来越重要。
它的核心并不复杂:
在编写代码之前,先明确系统应该做什么、不能做什么,以及如何证明它已经完成。
一、什么是 Spec?
Spec 可以翻译为规格、规范或需求说明。
但它不是一份几十页的形式化文档,也不等于传统的产品需求文档。
对一个具体开发任务来说,一份可用的 Spec 至少应该回答四个问题:
目标是什么?
输入和输出是什么?
有哪些约束和异常情况?
如何判断任务已经完成?
例如,“实现优惠券领取接口”不是一个完整的 Spec。
更完整的描述应该是:
## 目标
为用户提供优惠券领取接口。
## 业务规则
1. 一个用户只能领取同一张优惠券一次;
2. 优惠券必须处于可领取时间范围内;
3. 库存不能小于 0;
4. 并发请求不能造成超卖;
5. 重复请求需要返回第一次领取结果;
6. 领取成功后异步发送通知。
## 接口约束
- 不修改现有响应结构;
- 用户未登录时返回 401;
- 库存不足时返回业务错误码 COUPON_SOLD_OUT;
- 优惠券不存在时返回 COUPON_NOT_FOUND。
## 验收标准
- 单用户重复请求只能生成一条领取记录;
- 100 个并发请求竞争 10 张库存时,成功数量必须等于 10;
- MQ 重复投递不能重复发送权益;
- 数据库异常时不能永久扣减库存。
有了这些规则,开发者和 Agent 才知道应该实现什么。
二、为什么 AI 写代码越快,Spec 越重要?
传统开发中,程序员会在编码过程中不断补全需求。
遇到模糊的地方,可以询问产品,也可以根据项目经验作出判断。由于代码写得相对慢,很多问题会在实现过程中逐渐暴露。
AI Coding 改变了这个节奏。
Agent 可以在需求仍然模糊时,迅速生成一整套“看起来完整”的代码。
速度越快,错误方向造成的浪费反而越大。
例如,需求本来需要数据库条件更新:
UPDATE coupon
SET stock = stock - 1
WHERE id = ?
AND stock > 0;
但由于 Spec 没有写“并发下不能超卖”,Agent 可能生成:
Coupon coupon = couponRepository.findById(id);
if (coupon.getStock() <= 0) {
throw new BusinessException("库存不足");
}
coupon.setStock(coupon.getStock() - 1);
couponRepository.save(coupon);
这段代码在单元测试里可能完全正常,但在并发场景下存在风险。
问题不是 AI 不会写原子扣减,而是需求没有告诉它:
原子性是这个功能的必要条件。
AI 擅长把明确需求转换成代码,却不擅长替业务方决定隐藏规则。
因此,AI Coding 的关键能力不只是写 Prompt,而是编写可以执行和验证的 Spec。
三、SDD 和传统需求文档有什么区别?
传统需求文档通常偏向产品视角,例如:
用户点击领取按钮后,可以成功领取优惠券。
这句话能描述用户体验,但不足以直接指导工程实现。
SDD 更关注系统行为:
当用户第一次领取且库存充足时:
- 创建领取记录;
- 库存减少 1;
- 返回领取成功。
当相同用户重复领取时:
- 不重复扣减库存;
- 不创建新记录;
- 返回已有领取结果。
当多个用户并发领取最后一张优惠券时:
- 只能有一个请求成功;
- 其余请求返回库存不足。
它不会规定每一行代码怎么写,但会明确:
- 系统状态如何变化;
- 哪些行为必须发生;
- 哪些行为绝对不能发生;
- 哪些结果可以被测试验证。
可以把二者简单理解为:
需求文档:用户想要什么
Spec:系统必须表现成什么样
代码:系统具体如何做到
四、一个适合 AI Coding 的 SDD 流程
在实际项目中,不需要建立非常复杂的制度。
一个功能可以按照下面五步推进。
第一步:先让 Agent 分析,而不是直接写代码
不要一开始就输入:
帮我实现接口。
可以先输入:
分析这个需求,不要修改代码。
请输出:
1. 当前调用链;
2. 需要确认的业务规则;
3. 可能影响的数据表;
4. 并发和事务风险;
5. 建议的验收标准。
Agent 的第一项任务不是编码,而是帮助发现 Spec 中缺少的信息。
第二步:编写最小可用 Spec
Spec 不需要很长,但必须具体。
推荐至少包含:
## 背景
为什么需要这个功能。
## 目标
这个任务要解决什么问题。
## 非目标
本次明确不处理什么。
## 行为规则
正常、异常和边界情况下系统如何表现。
## 技术约束
不能修改的接口、表结构或依赖。
## 验收标准
通过哪些测试证明完成。
其中“非目标”非常重要。
例如:
## 非目标
- 本次不增加优惠券转赠功能;
- 不修改前端交互;
- 不调整现有优惠券表结构;
- 不处理历史重复数据。
它可以防止 Agent 顺手进行没有必要的扩展和重构。
第三步:让 Agent 根据 Spec 输出实现方案
此时依然不要急着改代码。
根据 Spec 给出实现方案。
说明:
1. 修改哪些文件;
2. 每个文件负责什么;
3. 事务边界如何设计;
4. 幂等如何实现;
5. 如何处理失败补偿;
6. 准备增加哪些测试。
不要修改代码。
这一步的目标,是检查 Agent 对 Spec 的理解是否正确。
第四步:实现并绑定验收标准
确认方案后,再让 Agent 开始编码:
按照已经确认的 Spec 和方案实现。
要求:
1. 不修改 Spec 之外的功能;
2. 不改变现有接口协议;
3. 每条验收标准必须有对应测试;
4. 完成后逐条说明验收结果。
此时测试不再是代码写完后的附属品,而是 Spec 的可执行证明。
第五步:检查代码是否偏离 Spec
功能完成后,不应该只问:
代码有没有 Bug?
更应该问:
根据 Spec 审查当前 Git Diff。
逐条检查:
1. 是否满足全部业务规则;
2. 是否实现了非目标中的内容;
3. 是否改变了现有接口;
4. 每项验收标准是否有证据;
5. 是否存在 Spec 未定义但代码自行决定的行为。
这一步能够发现一种常见问题:
代码本身看起来合理,但实现的并不是原始需求。
五、Spec 最重要的部分不是功能,而是边界
很多 Spec 会详细描述正常流程,却忽略失败场景。
例如:
用户领取优惠券后,系统扣减库存并生成记录。
这只描述了理想情况。
真正决定系统质量的,通常是下面这些边界:
- 用户重复点击怎么办?
- 请求超时后再次重试怎么办?
- Redis 成功但数据库失败怎么办?
- 数据库成功但 MQ 发送失败怎么办?
- MQ 重复消费怎么办?
- 优惠券刚好在请求过程中失效怎么办?
- 两个请求同时扣减最后一张库存怎么办?
因此,一份好的 Spec 应该主动写出系统不变量。
所谓不变量,就是无论发生什么情况,都必须成立的规则。
例如:
## 系统不变量
1. 优惠券库存永远不能小于 0;
2. 同一用户和优惠券只能存在一条有效领取记录;
3. 同一个消息重复消费不会产生额外权益;
4. 接口失败不能留下无法恢复的中间状态;
5. 所有库存变化必须能够追踪。
这些内容比“使用 Redis 还是数据库锁”更重要。
技术方案可以变化,但系统不变量不能被破坏。
六、SDD 和 TDD 是什么关系?
SDD 和 TDD 并不是互相替代的关系。
TDD,也就是测试驱动开发,通常遵循:
先写失败测试
→ 编写最小实现
→ 测试通过
→ 重构
SDD 解决的是:
我们到底要实现什么?
TDD 解决的是:
如何通过测试逐步实现它?
可以把它们组合起来:
Spec 定义业务行为
↓
验收标准转换成测试
↓
先运行测试并确认失败
↓
编写最小代码
↓
测试通过
↓
根据 Spec 再次审查
例如 Spec 中有一条:
100 个并发请求竞争 10 张库存时,只能成功 10 次。
对应的测试就应该真正模拟并发,而不是只测试单线程下库存从 10 减到 9。
如果测试无法证明 Spec 中的规则,测试数量再多也没有意义。
七、Spec 不应该变成新的形式主义
SDD 最大的风险,是把简单开发任务变成文档工程。
修改一个按钮文案,不需要写十页 Spec。
判断一个任务需要多详细的规格,可以看三个条件:
业务规则是否复杂?
失败代价是否很高?
是否需要多人或多个 Agent 协作?
对于简单任务,几行就够:
## 目标
将登录页按钮文案从“提交”改为“登录”。
## 约束
只修改中文文案,不调整布局和接口。
## 验收
中文环境显示“登录”,英文环境保持不变。
对于库存、支付、权限、数据迁移等高风险功能,则应该把异常场景和不变量写得更完整。
Spec 的目标不是增加文档数量,而是减少理解偏差。
八、真正的 SDD,是把模糊决策提前
很多软件问题并不是代码写错了,而是团队从未明确讨论过某个问题。
例如:
用户重复提交到底算成功还是失败?
如果 Spec 没有确定,Controller、Service、前端和测试可能会给出四种不同答案。
SDD 的价值,就是把这些模糊决策从上线后提前到编码前。
它会迫使团队先回答:
- 这个功能真正的目标是什么?
- 哪些行为必须保持兼容?
- 什么情况算成功?
- 什么情况必须失败?
- 系统失败后应该处于什么状态?
- 我们怎样证明实现是正确的?
这些问题一旦明确,后面的代码反而更容易写。
结语
AI Coding 降低了代码的生产成本,却没有降低正确理解需求的成本。
当 Agent 可以在几分钟内生成数百行代码时,开发中最昂贵的部分正在从“怎么写”转向:
写什么
为什么写
什么才算写对
SDD 并不是要求所有团队先写厚重文档。
它真正强调的是一个简单原则:
在让人或 AI 编写代码之前,先把目标、边界和验收标准说清楚。
未来优秀的开发者,可能不只是最会写代码的人。
更重要的是,他能够把一个模糊想法,转化成一份清晰、可执行、可验证的 Spec。
因为 AI 可以很快完成实现,但只有人能够先决定:
我们到底想让系统变成什么样。
GPT 5.6 的 Ultra 模式引入多Agent并行协作,将AI Coding从单Agent执行转向多Agent团队化工作,适合复杂模块重构等任务,而非简单修改。并行协调四个子Agent分别处理不…
GPT-5.6 的 Ultra 模式:AI Coding 开始从一个 Agent 变成一支小队GPT 5.6的Ultra模式通过协调多个Agent并行处理复杂编程任务,显著提升效率,适合跨模块重构等任务,但不建议用于简单修改。这标志着AI Coding从单Agent向多Agent协作的转变。
中国可能收紧顶尖 AI 模型出海:已经开源的模型还能限制吗?中国有关部门近期讨论是否限制先进AI模型出海,涉及闭源和开放权重模型。但当前仅为讨论,未形成政策。文章重点探讨了已开源模型的不可控性——一旦参数公开下载,技术上难以收回。可能的限制措施包括只提供API…
