Skip to content

实践:使用 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-001

SpecForge 会探查:

  • 如果幂等性密钥生成本身有竞态条件怎么办?
  • 如果第一个请求在进行中失败 — 第二个请求会成功吗?
  • 幂等性密钥的过期策略是什么?
  • 修复是否处理了支付成功但数据库写入失败的情况?

第 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、修复是什么、为什么这是正确的修复