Skip to content

2.2 SDD:先写规格的契约思维

小李的团队上周花了一整个下午吵架——前端说接口返回 userName,后端说规格里写的是 username。联调时才发现分页参数也不一致,一个用 page,一个用 offset

"如果一开始就写好 OpenAPI 规格,根本不会有这个问题。"——这就是小李坚持 SDD 的原因。


❌ 没有 SDD vs ✅ 有 SDD

❌ 没有 SDD 的协作方式

前端:"用户接口返回什么格式?"
后端:"你等等,我还没写完。"
……三天后联调……
前端:"你返回的是 userName,我用的是 username!"
后端:"你分页传的是 page,我期望的是 offset!"
结果:联调三天,全在修字段名不一致的问题

✅ 有 SDD 的协作方式

先写 OpenAPI 规格 → 前端基于 Mock 开发,后端按规格实现 → 契约测试验证
结果:零联调扯皮,文档永远最新,前后端并行开发

SDD 的核心:规格即真理

SDD 的核心理念可以用一句话概括:

在写代码之前,先用精确的规格文档定义"系统应该做什么"。
规格是唯一真实来源,所有代码、测试、文档都从规格生成。

小李的实际操作

让我们看小李设计"博客文章管理 API"的 SDD 过程:

第一步:写规格(最重要的产出物)

yaml
# blog-api-spec.yaml —— 小李花半天写的规格
openapi: 3.0.3
info:
  title: 博客文章管理 API
  version: 1.0.0
paths:
  /articles:
    get:
      summary: 获取文章列表
      parameters:
        - name: page
          in: query
          schema:
            type: integer
            default: 1
        - name: limit
          in: query
          schema:
            type: integer
            default: 10
      responses:
        '200':
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ArticleList'
    post:
      summary: 创建新文章
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateArticleRequest'
      responses:
        '201':
          description: 文章创建成功

第二步:从规格自动生成一切

规格文档 (OpenAPI)
    ├── 自动生成 → Swagger UI(交互式文档)
    ├── 自动生成 → Prism Mock 服务器(前端不用等后端)
    ├── 自动生成 → TypeScript 类型定义
    ├── 自动生成 → 代码骨架(Controller、Service)
    └── 自动生成 → Dredd 契约测试

第三步:前后端并行开发

  • 前端:基于 Mock 服务器开始开发,API 响应格式已经确定
  • 后端:按照规格实现逻辑,契约测试确保不跑偏

第四步:验证

后端开发完成后,运行契约测试验证"实现是否符合规格"。


为什么 SDD 在 AI 时代特别重要?

这里有一个关键洞察

AI 时代的关键洞察
在人类写的代码库中,歧义的成本是几小时的调试。
在 AI 生成的代码库中,歧义的成本是数千行听起来合理但微妙错误的代码。

LLM 需要精确的输入才能产生精确的输出。而规格文档,正是人类能给 AI 的最精确的指令。

对比一下:

模糊指令 → LLM → 大量可能错误的代码
"做一个用户管理 API"

精确规格 → LLM → 精确符合要求的代码
openapi: 3.0.3
paths:
  /users:
    get:
      responses:
        '200':
          schema:
            type: array
            items:
              $ref: '#/components/schemas/User'

SDD 的工具生态

SDD 不是只有一个工具,而是一整个工具链:

传统 SDD 工具:

类别工具用途
API 规格OpenAPI / SwaggerREST API 规范定义
Mock 服务Prism / WireMock基于 API 规格的 Mock
测试验证Dredd / Schemathesis自动契约测试
代码生成OpenAPI Generator从规格生成代码
行为规格Cucumber / GherkinBDD 风格的行为定义

2025-2026 AI 原生 SDD 工具:

工具提供方核心特点
KiroAmazon (AWS)双模式 IDE:Vibe Mode 和 Spec Mode
Spec KitGitHub结构化 Spec、Plan、Task 工作流
TesslTessl 团队从规格直接生成代码
ZeeSpec开源60 个结构化问题引导规格编写

SDD 的局限

SDD 很强大,但也有明显的代价:

局限具体表现
前期投入大写规格本身就需要时间,小型项目可能不值得
学习曲线陡OpenAPI、TLA+ 这些规范语言需要学习
灵活性降低需求变更时,规格和代码都要改
不适合探索你还不确定要做什么的时候,没法写规格

SDD vs BDD vs TDD

这三个缩写经常被混淆,但其实很清楚:

TDD
起点:单元测试
关注:代码是否正确
粒度:函数/方法级别
BDD
起点:用户场景
关注:行为是否符合预期
粒度:功能/场景级别
SDD
起点:形式化规格
关注:系统契约是否正确
粒度:系统/API 级别

可以理解为:TDD 是微观的验证,BDD 是中观的行为描述,SDD 是宏观的系统契约。


📌 本节核心要点

概念要点
SDD 核心"规格先行"——规格是唯一真实来源,一切从规格生成
AI 时代的关键LLM 需要精确输入才能产生精确输出,规格是给 AI 最好的指令
核心流程Specify(定义)→ Plan(规划)→ Implement(实现)→ Verify(验证)
代表工具传统:OpenAPI、Prism、Dredd;AI 时代:Kiro、Spec Kit、Tessl
不适合快速探索、小团队内部工具、需求不明确的项目
SDD vs TDD vs BDDTDD 验证代码,BDD 描述行为,SDD 定义系统契约

知识检查

问题 1:为什么说 SDD 在 AI 时代特别重要?用"歧义成本"来解释。

查看答案

在人类写的代码中,歧义的成本是几小时的调试。但在 AI 生成的代码中,歧义的成本是数千行听起来合理但微妙错误的代码。LLM 需要精确的输入才能产生精确的输出,而 SDD 的规格文档正是人类能给 AI 的最精确的指令。

对比:

  • 模糊指令 "做一个用户管理 API" → AI 可能猜错细节
  • 精确规格(OpenAPI 定义了每个字段类型和约束)→ AI 按规格生成精确代码

问题 2:SDD 的一个完整工作流程是怎样的?从规格文档可以自动生成哪些东西?

查看答案

工作流:写规格 → 自动生成 → 前后端并行开发 → 契约测试验证

从规格可自动生成

  • 交互式文档(Swagger UI)
  • Mock 服务器(前端不用等后端)
  • TypeScript 类型定义
  • 代码骨架(Controller、Service)
  • 契约测试(Dredd)

问题 3:TDD、BDD、SDD 三者的关注点和粒度有什么区别?

查看答案
  • TDD:起点是单元测试,关注"代码是否正确",粒度为函数/方法级别(微观验证)
  • BDD:起点是用户场景,关注"行为是否符合预期",粒度为功能/场景级别(中观描述)
  • SDD:起点是形式化规格,关注"系统契约是否正确",粒度为系统/API 级别(宏观契约)

问题 4:列出 2 个 SDD 不适合的场景,并说明原因。

查看答案
  1. 快速探索/原型阶段——需求还不清楚,写规格本身就很难
  2. 小团队内部工具——投入产出比低,写规格的时间可能比写代码还长

下一节预告

TDD 和 SDD 都很"严谨",但有一种方法论恰恰相反——它鼓励你"不看代码"。下一节我们看 Vibe Coding。

下一节:Vibe Coding——跟着 AI 感觉走