实践:使用 SDD 修复 Bug
本实践展示如何使用 SpecForge 以一种能创建持久规格的方式记录、界定和解决 bug — 让同类 bug 永不再次发生。
为什么将 Bug 记录为规格?
大多数 bug 会反复出现,因为正确的行为从未被正式规格化。在没有规格的情况下修复 bug 意味着:
- 修复没有验收标准(你怎么知道它已经修好了?)
- 回归测试没有可追溯性
- 同样的模式可能在相关代码中再次出现
SDD 将 bug 视为缺失或不正确的规格。修复 bug 意味着编写本应存在的规格,然后实现以匹配它。
场景
用户报告同时下两个订单有时会产生重复扣款。这是订单下单流程中的并发 bug。
第 1 步 — 澄清 Bug
提示词:
使用 specforge 澄清项目 proj_abc123 中的 bug 修复需求:
同时下单时产生重复扣款SpecForge 会询问:
- 重复发生在哪里 — API 层、支付处理器还是数据库?
- 这在特定条件下(负载、网络延迟)可重现吗?
- 预期行为是什么 — 每个订单恰好一次扣款,始终如此?
- 是否存在本应捕获此问题的测试?
第 2 步 — 创建 Bug 修复规格
提示词:
为项目 proj_abc123 中订单下单的重复扣款 bug 创建规格。
根本原因:OrderService.placeOrder 中的竞态条件 — Stripe 调用没有幂等性密钥。
预期:无论并发请求如何,每个订单恰好一次扣款。规格包含的内容:
markdown
## 验收标准
1. 同时下两次相同订单恰好只产生一次 Stripe 扣款
2. 第二个并发请求收到 409 Conflict 响应,带有订单 ID
3. 幂等性密钥从 orderId 派生并存储在 orders 表中
4. 支付发起后不能修改现有订单
5. 集成测试覆盖 10 个同时请求的并发订单下单
6. 单元测试覆盖幂等性密钥生成的边缘情况(UUID v4、碰撞抵抗)第 3 步 — 挑战修复设计
提示词:
挑战项目 proj_abc123 中的规格 SPEC-BUG-001SpecForge 会探查:
- 如果幂等性密钥生成本身有竞态条件怎么办?
- 如果第一个请求在进行中失败 — 第二个请求会成功吗?
- 幂等性密钥的过期策略是什么?
- 修复是否处理了支付成功但数据库写入失败的情况?
第 4 步 — 安全检查
提示词:
对项目 proj_abc123 中的规格 SPEC-BUG-001 运行安全检查并发支付 bug 通常具有安全影响 — 确保修复不会引入 TOCTOU 漏洞。
第 5 步 — 逆向工程现有代码
记录当前(有缺陷的)代码实际上做了什么:
提示词:
逆向工程项目 proj_abc123 中 /Users/me/my-app/src/orders/OrderService.ts 的代码这会创建当前行为的规格 — 用于精确理解规格和实现在哪里发生了偏离。
第 6 步 — 先生成测试(TDD 方法)
提示词:
为项目 proj_abc123 中的规格 SPEC-BUG-001 生成测试在接触实现之前先编写回归测试。这确保:
- Bug 可以用测试重现(红色)
- 修复使测试通过(绿色)
- 测试永远留在套件中(回归保护)
第 7 步 — 生成执行计划
提示词:
为项目 proj_abc123 中的规格 SPEC-BUG-001 生成执行计划对于 bug 修复,计划通常看起来像这样:
markdown
## 第 1 阶段:重现
- [ ] 编写触发重复扣款的失败集成测试(RED)
- [ ] 确认测试在当前实现下失败
## 第 2 阶段:修复
- [ ] 在 orders 表中添加 idempotency_key 列(迁移)
- [ ] 在 Stripe 调用之前在 OrderService 中生成幂等性密钥
- [ ] 与订单创建原子性地存储密钥(事务)
- [ ] 处理 Stripe 幂等性端点的 409 响应
## 第 3 阶段:验证
- [ ] 运行集成测试(GREEN)
- [ ] 运行完整测试套件
- [ ] 使用 Stripe 测试模式并发请求手动测试第 8 步 — 实现并验证
实现修复后:
提示词:
根据 /Users/me/my-app/src 的代码验证项目 proj_abc123 中的规格 SPEC-BUG-001确保所有 6 个验收标准都被实现和测试覆盖。
第 9 步 — 检测与原始规格的漂移
如果存在涵盖订单下单流程的现有规格,检查 bug 修复是否引入了漂移:
提示词:
检测项目 proj_abc123 中规格 SPEC-002(订单下单)的漂移修复可能需要在原始规格中反映为新标准:"系统必须对所有 Stripe API 调用使用幂等性密钥。"
第 10 步 — 捕获经验教训
提示词:
捕获经验教训:支付提供商 API 调用必须始终包含从业务实体 ID 派生的幂等性密钥,
而非从请求生成的 UUID这个模式现在被存储,并将影响未来涉及支付 API 调用的规格。
本实践的输出
最终你将得到:
- 一个带完整验收标准的 bug 修复规格(SPEC-BUG-001)
- 与每个标准可追溯的回归测试
- 更新以反映正确行为的原始规格
- 防止模式再次出现的捕获经验教训
- 审计追踪:何时发现 bug、修复是什么、为什么这是正确的修复