何时不该用 SDD?

在生成式 AI 辅助编程的发展过程中,逐渐凸显出一个核心矛盾:AI 的编码能力远超其对系统真实意图的理解能力。这种能力错位也使得“Vibe Coding”所带来的问题被开发人员快速发现——代码生成迅速、看似可用,却常常违背架构约束,导致后期维护成本激增。

为应对这一挑战,开发者自然转向规范驱动开发(Spec-Driven Development, SDD)。然而,SDD 并非万能解药。盲目推行反而可能拖慢节奏、徒增负担。以下六类场景中,不建议采用 SDD:

  • 探索性原型(Exploratory Prototyping):当你尚不清楚最终目标,仅想快速验证技术可行性时,直接编写代码更为高效。
  • 微小任务(Tiny Tasks):例如调整一行 CSS 样式或修正拼写错误。此类操作无需复杂的规范流程。
  • 缺乏领域知识:若你无法判断一份规范是否合理,让 AI 先生成规范再生成代码,无异于“盲人引路”,风险极高。
  • 基础设施受限:在无法运行 CI/CD 或容器化环境的系统中,AI 生成的代码难以自动验证,SDD 易退化为形式化的文档工作。
  • 紧急热修复(Hotfix):生产环境宕机时,应优先恢复服务,而非走完“设计 → 任务拆解”的完整流程。
  • 主观性 UI 调整:如“让 Logo 更大一点,感觉更活泼些”这类感性需求,难以被结构化描述,也不适合纳入 SDD 流程。

SDD能做什么?

SDD 的核心理念是:“意图即真理”(Intent is the source of truth)。传统 AI 编程依赖“Prompt → Code”的线性模式,高度依赖开发者的即时记忆与提示技巧,缺乏上下文持久化与系统性约束。

SDD 引入了一个关键中间层——规格(Spec)。它既是人类意图的结构化表达,也是 AI 执行的刚性边界。

SDD 降低不确定性的原理

Martin Fowler 在其分析文章中指出,AI 编程的最大风险在于非确定性(Non-determinism)。SDD 通过三大机制有效缓解这一问题:

  1. 上下文固化

将易逝的对话转化为持久的 Markdown 文档(如 requirements.md),作为 AI 的“外部记忆”,避免因对话轮次增加而“遗忘”关键约束。

  1. 思维链显式化

强制将“需求 → 设计 → 实现”的隐式思考拆解为独立的物理文件,使评审可前置至设计阶段,而非等到代码完成才暴露架构缺陷。

  1. 任务原子化

AI 不再一次性生成完整功能,而是基于设计文档输出一系列微小、可测试的任务单元,显著缩小错误传播范围。

化的 Markdown 文档。Spec 文件(如 requirements.md)充当了 AI 的 “外部存储器”,防止了随着对话轮次增加而出现的 “遗忘” 现象。

主流 SDD 流派对比:Kiro vs. Spec Kit

目前业界主要有两类 SDD 实践路径:

阶段属性 Kiro(三阶段) GitHub Spec Kit(四阶段) 核心产出物 AI 角色
需求定义 Requirements Specify 用户故事、成功标准 产品经理 / 业务分析师
架构设计 Design Plan 接口、数据流、API 定义 软件架构师
任务拆解 Tasks Tasks 实施步骤、测试计划 技术负责人
代码实现 Execution(隐式) Implement 源码、测试、配置 初级开发者

值得注意的是,Spec Kit 引入了 Constitution(规约)概念——即项目级全局约束(如“必须使用 TypeScript”),而 Kiro 通常通过系统提示(System Prompt)实现类似效果。

SDD 成熟度模型:从文档优先到规格即源码

根据Birgitta Böckeler 的研究,SDD 实践可分为三个层级:

  • Level 1:Spec-First(文档优先)
    代码生成前撰写规范,但后续不再维护。易出现“文档腐烂”。
  • Level 2:Spec-Anchored(规格锚定)
    规范与代码同等重要,任何变更须先更新 Spec。这是推荐的工程目标。
  • Level 3:Spec-As-Source(规格即源码)
    代码完全由 AI 从 Spec 自动生成,人类不直接修改代码。目前仍属实验阶段。

失败模式全景

我们将 SDD 四阶段中的典型失效模式总结为 20 种(详见原文表格):

本文所指的 “失败(Failure)”不是指 AI 模型本身的幻觉(Hallucination)或提示注入攻击,而是指A工程过程的失效(Process Failure)

Phase A: Requirements 阶段(需求定义)

此阶段的核心风险在于 “输入模糊” 与 “上下文过载”。如果种子不纯,果实必烂。

ID 失败模式 (Name) 典型表现 (Manifestation) 根本原因 (Root Cause) 最早信号 (Signal)
R01 Ambiguity Avalanche (歧义雪崩) AI 对一句话需求脑补出大量无关功能。 Spec 缺乏边界约束(Negative Constraints)。 Requirements 文档字数暴涨,出现用户未提及的术语。
R02 Scope Creep Injection (范围蔓延) AI 自动添加 “用户注册”、“通知系统” 等通用模块。 模型过度拟合通用 SaaS 模板,缺乏对当前 MVP 的聚焦。 Design 中出现了 Requirements 里没提到的模块。
R03 Context Amnesia (上下文失忆) 新需求不仅不兼容旧需求,还隐式覆盖了旧规则。 缺乏全局的 “Constitution” 或 Memory Bank 机制。 生成的 User Story 与现有系统逻辑冲突。
R04 Premature AI (过早追求智能) [案例] 骨架未通就开始调优 RAG 或 Prompt。 混淆了 “构建系统” 与 “构建模型” 的优先级。 Spec 中出现大量关于 Prompt 策略而非业务逻辑的描述。
R05 The Golden Hammer (金锤谬误) 强行用 AI 解决正则就能搞定的问题。 对 AI 能力的盲目崇拜,忽视了确定性方案的价值。 Requirements 中没有定义 “非 AI 兜底方案”。

Phase B: Design 阶段(架构设计)

此阶段是 “Vibe Coding” 最容易失控的环节。AI 倾向于为了实现的便利性而牺牲架构的严谨性。

ID 失败模式 (Name) 典型表现 (Manifestation) 根本原因 (Root Cause) 最早信号 (Signal)
D01 The Ivory Tower (象牙塔架构) [案例] 写了大量泛型、抽象类,但只有一种实现。 AI 模仿了企业级 Java/C# 的过度设计风格。 Design 文档中类图极其复杂,但数据流很简单。
D02 The Spaghetti Trap (耦合陷阱) [案例] UI 组件直接包含 SQL 查询或 API 密钥。 缺乏显式的 Layering(分层)指令。 Design 中缺少 Service/Repository 层的定义。
D03 Interface Drift (接口漂移) [案例] 修改了公共函数签名,导致并未修改的调用方崩溃。 AI 为了当前任务便利,忽视了接口契约的稳定性。 `git diff` 显示核心 Interface 文件被修改。
D04 Security Blindspot (安全盲区) API 设计中完全缺失鉴权(AuthZ)参数。 Spec 中未强制包含安全视图(Security View)。 Design 里的 API 定义没有 `token` 或 `user_id` 参数。
D05 Tech Stack Hallucination (技术栈幻觉) 设计了一个不存在的库函数或 AWS 服务。 训练数据截止日期的滞后性或混淆了不同库的 API。 Design 引用了 Google 搜不到的方法名。

Phase C: Tasks 阶段(任务规划)

任务规划的质量决定了执行的成败。AI 往往不擅长处理任务间的时序依赖。

ID 失败模式 (Name) 典型表现 (Manifestation) 根本原因 (Root Cause) 最早信号 (Signal)
T01 Sample Starvation (样例缺失) [案例] AI 瞎猜代码风格,生成的代码与现存风格迥异。 Prompt 中缺乏 One-shot Example。 Task 描述中没有 `Reference: xxx.ts` 的指引。
T02 Task Atomicity Violation (原子性破坏) 一个 Task 包含了 “建表、写后端、写前端” 所有工作。 AI 懒惰,未能进行细粒度的 Work Breakdown。 单个 Task 的预估 Token 数超过上下文窗口限制。
T03 Dependency Deadlock (依赖死锁) Task B 依赖 Task A 的接口,但 B 被排在 A 前面。 缺乏拓扑排序(Topological Sort)逻辑。 Task 列表中没有明确的前置条件(Prerequisites)。
T04 The Happy Path Bias (乐观路径偏差) 所有 Task 都在实现功能,没有一个 Task 处理错误。 AI 的生成偏好是 “完成功能” 而非 “健壮性”。 Task 列表中没有包含 `Error Handling` 关键词。
T05 Validation Vacuum (验证真空) Task 完成的定义是 “写完代码”,而不是 “测试通过”。 Definition of Done (DoD) 缺失。 Task 描述中没有提到具体的 Test Case。

Phase D: Implement 阶段(代码实现)

这是代码实际生成的阶段,也是所有前期错误爆发的终点。

ID 失败模式 (Name) 典型表现 (Manifestation) 根本原因 (Root Cause) 最早信号 (Signal)
I01 Dependency Hell (依赖地狱) [案例] 混用 date-fns, moment, dayjs。 缺乏白名单机制,AI 随意选择它熟悉的库。 `package.json` 在单次提交中新增多个功能重叠的库。
I02 Test Illusion (测试幻觉) [案例] 生成了测试但从未运行,断言全是 Mock 的假数据。 注重 “覆盖率” 指标而忽视了 “真实性”。 测试代码中充满了 `expect(true).toBe(true)` 式的逻辑。
I03 Zombie Code (僵尸代码) 新功能通过复制粘贴实现,旧逻辑被注释掉但未删除。 AI 缺乏重构(Refactor)的胆量,倾向于追加(Append)。 文件中出现大段被注释的代码块。
I04 Configuration Drift (配置漂移) 代码里硬编码了 `.env` 变量名,与生产环境不一致。 Spec 未包含运维/部署约束。 代码中出现 `process.env.NEW_VAR` 但 `.env.example` 未更新。
I05 Regression Roulette (回归轮盘赌) 修复了一个 Bug,引发了三个新 Bug。 缺乏自动化回归测试集,仅依赖人工验证。 CI 状态变红,或相关模块的 Snapshot 测试失败。

纠偏机制

识别失败模式只是第一步。要构建健壮的 SDD 工作流,还需要在仓库中建立一套三层控制网络(Three-Layer Control Fabric)

  • 预防(Prevention):如注入分层架构上下文、维护依赖白名单;
  • 检测(Detection):如 CI 自动校验接口变更、扫描非法跨层调用;
  • 纠正(Correction):如回滚代码、插入重构任务、提供测试样例。
失败模式类型 预防 (Prevention) - 减少发生概率 检测 (Detection) - 尽早暴露问题 纠正 (Correction) - 止损与修复
架构崩坏 (Spaghetti Trap, Ivory Tower)
  • Layering Context: 在 Prompt 中强制注入分层架构图。
  • Reference Architecture: 提供 `reference/` 目录作为架构模板。
  • Arch Linting: 使用 Dependency-Cruiser 扫描非法跨层调用。
  • Gate (Design): 人工 Review Design 文档的复杂度。
  • Tracer Bullet: 强制由 AI 实现一个穿透所有层的最小 Hello World。
  • Refactor Task: 插入专门的重构任务,不写新功能。
接口/依赖失控 (Interface Drift, Dependency Hell)
  • Read-only Locks: 锁定核心接口文件与 `package.json`。
  • Allowlist: 维护 `APPROVED_LIBS.md` 白名单。
  • API Diff Check: CI 自动对比 Swagger/OpenAPI 变更。
  • Gate (Implement): 任何 `package.json` 变更触发强审计。
  • Revert & Spec Update: 回滚代码,强制先更新 Spec 中的接口定义。
  • Adapter Pattern: 让 AI 编写适配层而非修改核心接口。
质量虚标 (Test Illusion, Validation Vacuum)
  • TDD Prompting: 强制 AI 先写测试再写实现。
  • Test Examples: 在 `examples/` 中提供高标准测试样例。
  • Gate (Task): CI 必须变绿(Green CI Constraint)。
  • Mutation Testing: 引入变异测试检测伪断言。
  • Broken Windows Halt: 测试失败时禁止合并任何代码。
  • Auto-Fix with Logs: 将报错日志回填给 AI 让其自我修复。
上下文失效 (Ambiguity, Context Amnesia)
  • System Prompting: 注入全局 Constitution。
  • Spec Anchoring: 要求 AI 在修改代码前先引用 Spec 章节。
  • Spec-Code Alignment: 定期人工抽查代码是否符合 Spec。
  • Spec Refinement: 暂停开发,重写 Requirements 文档。
  • Context Refresh: 清空对话历史,重新加载 Spec。

仓库约定示例

.
├── .spec/
│   ├── constitution.md       # 全局规约:技术栈、白名单、编码规范
│   ├── requirements.md       # 当前任务需求
│   ├── design.md             # 当前任务设计
│   └── tasks.md              # 任务清单与状态
├── examples/                 # 核心纠偏资产:Sample Starvation 的解药
│   ├── component-style.tsx   # 完美的 UI 组件范例
│   ├── api-handler.ts        # 标准的 API 处理范例
│   └── test-case.spec.ts     # 必须遵守的测试写法
├── APPROVED_LIBS.md          # 依赖白名单
└── .github/
    └── workflows/
        └── ci-gate.yml       # 必须包含测试步骤

分阶段检查清单

阶段 检查维度 具体要求
Phase 1: Requirements Gate 用户故事质量 所有 User Story 都有明确的 Acceptance Criteria
表述清晰性 无模糊词汇(如 “better”, “fast”, “modern”)
范围控制 明确定义了 “不做的事”(Out of Scope)
实现中立性 未直接包含具体实现细节(如 “用 Redis”),除非是硬约束
异常覆盖 包含至少 3 个 Negative Test Cases(异常场景)
术语一致性 术语与现有系统一致(需查阅 Domain Dictionary)
Phase 2: Design Gate 接口规范 所有 API 变更都有 Swagger/OpenAPI 定义
数据模型 数据模型变更包含 SQL/Schema 迁移计划
依赖管理 识别并列出所有新引入的依赖库(需查白名单)
安全设计 包含具体的安全考量(Auth, Input Validation 等)
架构合规 架构分层符合 constitution.md 中定义的原则
验证路径 已规划 Tracer Bullet(首个端到端验证任务)
Phase 3: Tasks Gate 任务粒度 单个任务代码行数 < 200(逻辑可独立完成)
依赖结构 任务间依赖关系清晰且无环(DAG)
测试覆盖 每个任务都有关联的测试计划(单元/集成/E2E)
质量内建 包含专门的 “Cleanup/Refactor” 任务(非功能优化)
Phase 4: Implement Gate 代码健康度 代码编译通过,无 Linter 报错
测试有效性 新增测试用例通过,且包含有效断言(非空跑)
自动化状态 CI 流水线全绿(构建、测试、扫描)
代码整洁性 无注释掉的死代码(Zombie Code)
安全合规 无硬编码的 Secret 或 Magic Number
文档同步 Spec 文档(requirements/design)与代码保持同步

失败时的应急预案

当检测到失败模式时,不要试图通过 “再 Prompt 一次” 来碰运气。请执行以下预案:

接口漂移 / 架构崩坏时:STOP & REVERT
1. 立即停止当前 Session。
2. `git reset --hard` 回退到最近一个干净的 Commit。
3. 人工介入 `design.md`,明确添加约束(例如:“必须复用 UserInterface,禁止修改签名”)。
4. 重新生成 Tasks 并 Review。

测试不可跑 / 逻辑死循环时:ADD EXAMPLES
1. 不要让 AI 自己修测试(它通常会删断言)。
2. 开发者手动编写一个通过的测试样例,放入 `examples/` 或直接贴入 Context。
3. 要求 AI 参考该样例重写实现。

依赖膨胀 / 幻觉库时:WHITELIST ENFORCEMENT
1. 拒绝该 PR。
2. 在 System Prompt 或 Constitution 中更新:“仅允许使用 approved_libs.md 中的库”。
3. 要求 AI 使用原生代码实现该功能,或请求人工批准引入新库。

结论

SDD 的本质,是在 AI 编程的流变性中重新注入软件工程的严谨性。其失败根源常归结为三点:规格模糊、反馈滞后、人机信任错位。我们提出三大抓手,来应对这三类失败:

  1. 建立规约:定义 CONSTITUTION.md,作为 AI 行为的底线;
  2. 强制分层:通过仓库结构与设计门禁,防止“面条代码”;
  1. 自动化验证:CI 是王道。没有自动测试的代码,生成得越快,崩塌得越快。
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐