Spec Driven Development

Posted on Sun 09 November 2025 in Journal

Abstract Journal on 2025-11-09
Authors Walter Fan
Category learning note
Status v1.0
Updated 2025-11-09
License CC-BY-NC-ND 4.0

规范驱动开发(Spec Driven Development):代码与文档的协同之道

"代码会撒谎,但规范不会。" —— 某个被 Bug 折磨到凌晨三点的程序员

你是否经历过这些场景:代码写完了,文档还没写;文档写完了,代码已经改了好几版;好不容易同步了,结果发现前后端理解还是不一致;联调时发现接口对不上;维护文档比写代码还累。

这就是典型的"代码和文档分离"带来的痛苦。根据实践经验,开发者平均需要花费 30% 左右的时间来处理文档和接口不一致的问题。

本文将深入探讨规范驱动开发(Spec Driven Development,简称 SDD),一种让规范和代码保持同步的开发方法。通过实践案例和工具介绍,帮助你建立起更高效的开发流程。

什么是规范驱动开发

规范驱动开发的核心思想很简单:先写规范,再写代码,规范即文档,文档即代码

这听起来有点像"先有鸡还是先有蛋"的哲学问题,但 SDD 的答案是:先有规范这个"蛋",然后孵化出代码这只"鸡"

SDD 的基本流程

  1. 编写规范(Spec) - 用结构化的方式描述功能需求
  2. 生成代码框架 - 根据规范自动生成代码骨架
  3. 实现业务逻辑 - 在框架基础上填充具体实现
  4. 验证一致性 - 确保代码和规范始终保持同步

这个过程可以类比建房子:先画图纸(规范),再打地基(代码框架),最后装修(业务逻辑)。如果中途修改图纸,地基也需要相应调整,从而避免"图纸说东,房子朝西"的情况。

graph LR
    A[编写规范<br/>Spec Definition] --> B[生成代码框架<br/>Code Generation]
    B --> C[实现业务逻辑<br/>Implementation]
    C --> D[验证一致性<br/>Validation]
    D --> E{规范变更?}
    E -->|是| A
    E -->|否| F[部署上线<br/>Deployment]

    style A fill:#e1f5ff
    style B fill:#fff4e1
    style C fill:#ffe1f5
    style D fill:#e1ffe1
    style F fill:#d4edda

规范驱动开发与其他方法论的对比

在软件开发中,存在多种"驱动开发"的方法论,各有侧重。理解 SDD 与其他方法的异同,有助于在实际项目中选择合适的开发策略。

mindmap
  root((驱动开发<br/>方法论))
    DDD
      领域模型
      业务理解
      战略设计
      战术设计
    FDD
      功能列表
      快速迭代
      特性交付
      项目管理
    SDD
      接口规范
      代码生成
      文档同步
      契约验证
    BDD
      行为场景
      自然语言
      协作沟通
      验收测试
    TDD
      测试先行
      重构
      红绿循环

FDD:功能驱动开发

FDD 的核心特点: - 以功能(Feature)为核心组织开发 - 每个功能都是独立的、可交付的单元 - 强调快速迭代和频繁交付

FDD 的典型流程是:需求分析 → 功能列表 → 功能设计 → 功能实现 → 功能测试。

与 SDD 的对比: - 相似点:都强调结构化和可交付性 - 主要差异:FDD 关注"做什么"(功能清单),SDD 关注"怎么做"(接口规范);FDD 更偏向项目管理层面,SDD 更偏向技术实现层面

举例说明:

FDD 视角:
- Feature: 用户登录
- 子功能:邮箱登录、手机号登录、第三方登录

SDD 视角:
- Spec: 登录接口规范
  - 输入:邮箱/手机号 + 密码
  - 输出:token + 用户信息
  - 错误处理:密码错误、账户锁定等

DDD:领域驱动设计

DDD 的核心特点: - 以领域模型为核心 - 强调业务专家和开发者的协作 - 通过"通用语言"(Ubiquitous Language)统一理解

DDD 的核心概念: - 实体(Entity)、值对象(Value Object) - 聚合(Aggregate)、领域服务(Domain Service) - 仓储(Repository)、工厂(Factory)

SDD vs DDD: - 相似点:都强调用结构化的方式表达业务 - 不同点: - DDD 关注"业务是什么"(领域模型),SDD 关注"系统怎么做"(接口规范) - DDD 更抽象,SDD 更具体 - DDD 说"用户是一个实体,有身份标识",SDD 说"用户接口的请求格式是..."

举个例子:

DDD 视角:
- 领域:电商系统
- 实体:订单(Order)、商品(Product)
- 值对象:金额(Money)、地址(Address)
- 领域服务:订单服务(OrderService)

SDD 视角:
- API 规范:创建订单接口
  - POST /api/orders
  - Request Body: { productId, quantity, address }
  - Response: { orderId, totalAmount, status }

三者的关系:互补而非竞争

其实这三种方法并不冲突,它们可以很好地配合使用:

DDD(业务理解) → FDD(功能规划) → SDD(技术实现)
    ↓                  ↓                  ↓
  领域模型           功能列表           接口规范

三者的关系可以这样理解:DDD 定义业务领域和模型,FDD 规划具体功能清单,SDD 制定技术实现规范。它们各有侧重,可以配合使用。

graph TD
    subgraph DDD[领域驱动设计 DDD]
        D1[业务理解<br/>Business Understanding]
        D2[领域模型<br/>Domain Model]
        D3[实体与值对象<br/>Entities & Value Objects]
    end

    subgraph FDD[功能驱动开发 FDD]
        F1[功能列表<br/>Feature List]
        F2[功能设计<br/>Feature Design]
        F3[功能实现<br/>Feature Build]
    end

    subgraph SDD[规范驱动开发 SDD]
        S1[接口规范<br/>API Specification]
        S2[代码生成<br/>Code Generation]
        S3[实现验证<br/>Implementation & Validation]
    end

    D1 --> D2 --> D3
    D3 --> F1
    F1 --> F2 --> F3
    F3 --> S1
    S1 --> S2 --> S3

    style DDD fill:#e8f4f8
    style FDD fill:#fff4e6
    style SDD fill:#f0e6ff

BDD(Behavior Driven Development):行为驱动的"沟通大师"

在介绍完 FDD 和 DDD 之后,我们不能忘记另一个重要的"D家族成员":行为驱动开发(BDD)。如果说 DDD 是"哲学家",FDD 是"实干派",那么 BDD 就是"沟通大师"——它擅长用大家都能听懂的语言描述系统行为。

BDD 的特点: - 以用户行为和业务价值为中心 - 使用自然语言(Given-When-Then)描述场景 - 强调协作:业务人员、测试人员、开发人员共同定义行为 - 测试用例即需求文档

BDD 的核心模式:Given-When-Then

Feature: 用户登录

  Scenario: 用户使用正确的凭证登录
    Given 用户已经注册了账号 "user@example.com"
    When 用户输入正确的邮箱和密码
    Then 用户应该成功登录
    And 系统应该返回用户信息和访问令牌

  Scenario: 用户使用错误的密码登录
    Given 用户已经注册了账号 "user@example.com"
    When 用户输入错误的密码
    Then 登录应该失败
    And 系统应该返回 "密码错误" 的提示

SDD vs BDD:契约 vs 行为

维度 SDD BDD
关注点 接口契约和数据结构 用户行为和业务场景
描述方式 技术规范(OpenAPI、JSON Schema) 自然语言(Gherkin、Given-When-Then)
主要用户 开发人员、架构师 业务分析师、测试人员、开发人员
输出物 API 文档、代码框架 可执行的测试用例
验证方式 接口测试、类型检查 端到端测试、集成测试

相似点: - 都强调"规范先行"的理念 - 都试图弥合需求和实现之间的鸿沟 - 都可以自动生成测试或代码

不同点: - SDD 说:"这个 API 接受 JSON 格式,字段包括 email、password..." - BDD 说:"当用户输入正确的邮箱和密码时,系统应该返回成功..."

举个例子:同一个功能的不同视角

SDD 视角(技术规范):

paths:
  /api/v1/users/login:
    post:
      requestBody:
        schema:
          type: object
          properties:
            email: {type: string, format: email}
            password: {type: string, minLength: 8}
      responses:
        '200':
          schema:
            properties:
              token: {type: string}
              userId: {type: string}

BDD 视角(行为场景):

Scenario: 成功登录
  Given 存在用户 "alice@example.com" 密码为 "SecurePass123"
  When POST /api/v1/users/login
    """
    {"email": "alice@example.com", "password": "SecurePass123"}
    """
  Then 响应状态码应该是 200
  And 响应包含 "token" 和 "userId" 字段

它们如何配合使用?

graph LR
    A[业务需求<br/>Business Requirement] --> B[BDD 场景<br/>Behavior Scenarios]
    B --> C[SDD 规范<br/>API Specification]
    C --> D[代码实现<br/>Implementation]
    D --> E[BDD 测试<br/>Acceptance Tests]
    E --> F{测试通过?}
    F -->|否| D
    F -->|是| G[交付<br/>Delivery]

    style B fill:#e8f4f8
    style C fill:#f0e6ff
    style E fill:#e1ffe1

实践中,BDD 和 SDD 可以完美配合: 1. BDD 定义"做什么":用 Given-When-Then 描述用户期望的行为 2. SDD 定义"怎么做":用技术规范描述 API 的细节 3. BDD 验证"做对了吗":用自动化测试验证行为是否符合预期

驱动开发方法全面对比

为了让大家更清晰地理解各种方法,这里提供一个全面的对比表:

特性 SDD BDD TDD DDD FDD
核心理念 规范即文档 行为即需求 测试先行 领域建模 功能交付
主要用户 全栈开发者 全团队 开发者 架构师 项目经理
起始点 接口规范 用户故事 测试用例 领域模型 功能列表
输出物 API文档+代码 可执行测试 测试+代码 领域模型 功能模块
验证方式 规范一致性 行为验证 单元测试 模型验证 功能验收
学习曲线 ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐
工具依赖 中等 中等
适用规模 中大型 任意 任意 大型 中大型
团队协作 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐

如何选择? - 🎯 API 开发 → SDD 首选 - 🎯 需求不明确 → BDD 首选 - 🎯 代码质量 → TDD 首选 - 🎯 复杂业务 → DDD 首选 - 🎯 快速交付 → FDD 首选

推荐组合: - 小型项目:TDD + SDD(轻量级) - 中型项目:BDD + SDD + TDD - 大型项目:DDD + FDD + SDD + BDD + TDD

规范驱动开发与文学编程的对比

文学编程(Literate Programming)是 Donald Knuth 在 1984 年提出的概念,它的核心理念是:程序应该像文学作品一样可读

文学编程的特点

  • 代码和文档交织在一起
  • 按照人类的思维逻辑组织代码,而非编译器的要求
  • 使用工具(如 nowebCWEB)将文档和代码分离

文学编程的例子:

<<用户认证函数>>=
/**
 * 用户登录验证
 * 
 * 这个函数负责验证用户的登录凭证。
 * 如果验证成功,返回用户信息;否则返回错误。
 */
int authenticate_user(const char* username, const char* password) {
    <<验证用户名和密码>>
    <<查询数据库>>
    <<生成 token>>
    return result;
}

SDD vs 文学编程

维度 文学编程 SDD
关注点 代码的可读性 规范的完整性
组织方式 按逻辑顺序 按接口结构
工具支持 noweb, CWEB spec-kit, OpenAPI
适用场景 复杂算法、系统程序 API 开发、微服务
文档位置 代码内部 独立规范文件

相同点: - 都强调文档的重要性 - 都试图让代码更易理解 - 都需要工具支持

不同点: - 文学编程是"代码即文档"(代码里写文档) - SDD 是"规范即文档"(规范文件就是文档)

举个例子:

文学编程风格(伪代码):

<<计算订单总价>>=
def calculate_total(order):
    """
    计算订单的总价

    这个函数会遍历订单中的所有商品,
    累加每个商品的价格乘以数量。
    """
    total = 0
    for item in order.items:
        total += item.price * item.quantity
    return total

SDD 风格(规范文件):

# order-service.spec.yaml
endpoints:
  - name: calculateTotal
    method: POST
    path: /api/orders/calculate
    request:
      schema:
        type: object
        properties:
          items:
            type: array
            items:
              price: number
              quantity: number
    response:
      schema:
        total: number
    description: |
      计算订单的总价。
      遍历订单中的所有商品,累加每个商品的价格乘以数量。

实践案例:使用 SDD 开发用户服务

通过一个实际的用户注册功能来演示 SDD 的完整流程。

系统架构概览

在开始之前,让我们先看看整个系统的架构:

graph TB
    subgraph Client[客户端层]
        Web[Web 应用]
        Mobile[移动应用]
    end

    subgraph Spec[规范层]
        OpenAPI[OpenAPI Spec<br/>user-service.yaml]
    end

    subgraph Generated[生成层]
        Models[数据模型<br/>Models]
        Handlers[处理器<br/>Handlers]
        Validators[验证器<br/>Validators]
        Tests[测试用例<br/>Tests]
    end

    subgraph Implementation[实现层]
        Business[业务逻辑<br/>Business Logic]
        DB[(数据库<br/>Database)]
    end

    Web --> OpenAPI
    Mobile --> OpenAPI
    OpenAPI -.生成.-> Models
    OpenAPI -.生成.-> Handlers
    OpenAPI -.生成.-> Validators
    OpenAPI -.生成.-> Tests

    Handlers --> Business
    Business --> DB

    style OpenAPI fill:#f9d5e5
    style Generated fill:#eeeeee
    style Implementation fill:#d5f4e6

案例:用户注册功能

第一步:编写接口规范

使用 OpenAPI 格式定义接口(也可以使用 JSON Schema、Protocol Buffers 等其他格式):

# user-service.spec.yaml
openapi: 3.0.0
info:
  title: 用户服务 API
  version: 1.0.0
  description: 提供用户注册、登录、信息查询等功能

paths:
  /api/v1/users/register:
    post:
      summary: 用户注册
      description: |
        新用户注册接口。
        需要提供邮箱、密码、昵称等信息。
        系统会验证邮箱格式和密码强度。
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - email
                - password
                - nickname
              properties:
                email:
                  type: string
                  format: email
                  description: 用户邮箱
                  example: "user@example.com"
                password:
                  type: string
                  format: password
                  minLength: 8
                  description: 密码,至少8位
                  example: "SecurePass123!"
                nickname:
                  type: string
                  minLength: 2
                  maxLength: 20
                  description: 用户昵称
                  example: "张三"
      responses:
        '201':
          description: 注册成功
          content:
            application/json:
              schema:
                type: object
                properties:
                  userId:
                    type: string
                    description: 用户ID
                  email:
                    type: string
                  nickname:
                    type: string
                  createdAt:
                    type: string
                    format: date-time
        '400':
          description: 请求参数错误
          content:
            application/json:
              schema:
                type: object
                properties:
                  error:
                    type: string
                    example: "邮箱格式不正确"
        '409':
          description: 邮箱已存在

第二步:使用代码生成工具

根据 OpenAPI 规范可以生成代码框架,常用工具包括:

  1. OpenAPI Generator(推荐)
# 安装
npm install @openapitools/openapi-generator-cli -g

# 生成 Go 代码
openapi-generator-cli generate -i user-service.spec.yaml -g go -o ./generated

# 生成 TypeScript 代码
openapi-generator-cli generate -i user-service.spec.yaml -g typescript-axios -o ./generated

# 生成 Python 代码
openapi-generator-cli generate -i user-service.spec.yaml -g python -o ./generated
  1. Swagger Codegen
# 使用 Docker
docker run --rm -v ${PWD}:/local swaggerapi/swagger-codegen-cli generate \
  -i /local/user-service.spec.yaml \
  -l go \
  -o /local/generated
  1. oapi-codegen(Go 专用,轻量级)
# 安装
go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@latest

# 生成 Go 代码
oapi-codegen -package models user-service.spec.yaml > models/user.go

生成的 Go 代码框架示例:

// generated/models/user.go
package models

type RegisterRequest struct {
    Email    string `json:"email" validate:"required,email"`
    Password string `json:"password" validate:"required,min=8"`
    Nickname string `json:"nickname" validate:"required,min=2,max=20"`
}

type RegisterResponse struct {
    UserID    string `json:"userId"`
    Email     string `json:"email"`
    Nickname  string `json:"nickname"`
    CreatedAt string `json:"createdAt"`
}

// generated/handlers/user_handler.go
package handlers

func RegisterUser(w http.ResponseWriter, r *http.Request) {
    // TODO: 实现注册逻辑
    // 1. 解析请求体
    // 2. 验证邮箱格式和密码强度
    // 3. 检查邮箱是否已存在
    // 4. 创建用户
    // 5. 返回响应
}

第三步:实现业务逻辑

在生成的框架基础上实现具体逻辑:

func RegisterUser(w http.ResponseWriter, r *http.Request) {
    // 1. 解析请求体
    var req models.RegisterRequest
    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        respondError(w, http.StatusBadRequest, "请求参数错误")
        return
    }

    // 2. 验证邮箱格式和密码强度
    if !isValidEmail(req.Email) {
        respondError(w, http.StatusBadRequest, "邮箱格式不正确")
        return
    }

    // 3. 检查邮箱是否已存在
    if userRepo.Exists(req.Email) {
        respondError(w, http.StatusConflict, "邮箱已存在")
        return
    }

    // 4. 创建用户
    user := &models.User{
        Email:    req.Email,
        Password: hashPassword(req.Password),
        Nickname: req.Nickname,
    }
    if err := userRepo.Create(user); err != nil {
        respondError(w, http.StatusInternalServerError, "创建用户失败")
        return
    }

    // 5. 返回响应
    respondJSON(w, http.StatusCreated, models.RegisterResponse{
        UserID:    user.ID,
        Email:     user.Email,
        Nickname:  user.Nickname,
        CreatedAt: user.CreatedAt.Format(time.RFC3339),
    })
}

第四步:验证规范一致性

修改代码后,通过验证工具确保实现与规范保持一致:

# 验证 OpenAPI 规范文件格式
swagger-cli validate user-service.spec.yaml

# 使用 Spectral 进行更严格的校验
spectral lint user-service.spec.yaml

# 生成文档(验证规范可用性)
redoc-cli bundle user-service.spec.yaml -o docs/api.html

规范驱动开发的工具生态

在 SDD 的实践中,有两类主要的工具:API 规范工具项目规范工具。它们各有侧重点,可以互补使用。

GitHub Spec-Kit:AI 驱动的规范工具

GitHub Spec-Kit 是 GitHub 官方开源的规范驱动开发工具包(46.5k+ stars),专门用于与 AI 编程助手(如 Claude Code)协同工作,将需求规范转化为可执行代码。

Spec-Kit 的核心理念

Spec-Kit 采用了一种人类定义规范、AI 执行实现的工作模式:

graph LR
    A[0. 初始化项目<br/>specify init] --> B[1. 建立宪章<br/>/speckit.constitution]
    B --> C[2. 定义规范<br/>/speckit.specify]
    C --> D[AI:生成规范文档<br/>spec.md]
    D --> E[3. 技术方案<br/>/speckit.plan]
    E --> F[AI:创建方案<br/>plan.md]
    F --> G[4. 任务列表<br/>/speckit.tasks]
    G --> H[AI:生成任务<br/>tasks.md]
    H --> I[5. 执行实现<br/>/speckit.implement]
    I --> J[AI:实现代码]

    style A fill:#e1f5ff
    style B fill:#ffe1e1
    style C fill:#fff4e6
    style E fill:#f0e6ff
    style G fill:#e6ffe6
    style I fill:#ffe6e6

Spec-Kit 的工作流程

初始化项目

在项目目录中初始化 Spec-Kit:

# 在当前目录初始化项目
specify init --here --force --ai cursor-agent

# 或者创建新项目目录
specify init my-project --ai cursor-agent

这个命令会创建: - 项目模板和目录结构 - CLAUDE.md 文件(AI 助手配置) - memory/ 目录(存储项目记忆) - specs/ 目录(存储功能规范) - templates/ 目录(规范模板) - scripts/ 目录(辅助脚本)

建立项目宪章

在编写功能规范之前,先定义项目的基本原则和约束,作为后续实现的指导方针:

/speckit.constitution Create principles focused on code quality, testing standards, 
user experience consistency, and performance requirements

AI 会在 memory/constitution.md 中生成项目宪章,典型内容包括:

# 项目宪章 (Project Constitution)

## 代码质量原则
- 所有代码必须遵循 SOLID 原则
- 函数单一职责,最大长度不超过 50 行
- 必须有清晰的命名和注释
- 代码覆盖率不低于 80%

## 测试标准
- 所有公共 API 必须有单元测试
- 关键业务逻辑必须有集成测试
- 遵循 TDD 开发模式:先写测试,再写实现
- 测试命名格式:Should_ExpectedBehavior_When_Condition

## 用户体验一致性
- 所有界面必须支持响应式设计
- 加载时间不超过 3 秒
- 错误信息必须清晰且可操作
- 支持键盘快捷键操作

## 性能要求
- API 响应时间 < 200ms (P95)
- 数据库查询必须有索引优化
- 静态资源必须启用缓存
- 支持水平扩展

## 安全要求
- 所有输入必须验证和消毒
- 敏感数据必须加密存储
- 使用 HTTPS 传输
- 定期进行安全审计

这个宪章文件贯穿整个开发过程,AI 生成代码时会参考这些原则。

定义功能规范

描述需要构建的功能,专注于业务需求而非技术细节:

我想创建一个任务管理应用 Taskify,具有以下功能:
- 用户可以创建、编辑、删除任务
- 任务可以分配给团队成员
- 支持任务的优先级和截止日期
- 实时通知和更新

AI 会生成规范文档(spec.md),包含用户故事、验收标准等,并参考项目宪章中定义的原则。

创建技术方案

在规范基础上,指定技术栈和架构:

我们将使用 .NET Aspire 和 Postgres 数据库。
前端使用 Blazor Server,支持拖拽式任务面板和实时更新。
创建 REST API,包括项目 API、任务 API 和通知 API。

AI 会生成: - 实现计划(plan.md) - 数据模型(data-model.md) - API 规范(api-spec.json) - 技术研究(research.md

AI 确保方案符合项目宪章中的质量标准和性能要求。

生成任务列表

自动将技术方案分解为可执行的任务:

/speckit.tasks

生成的 tasks.md 包含: - 按用户故事组织的任务 - 任务之间的依赖关系 - 可并行执行的任务标记 [P] - 具体的文件路径 - TDD 测试任务(如果宪章中要求 TDD)

执行代码实现

AI 按照任务列表自动实现代码:

/speckit.implement

AI 会: - 验证所有前置条件(constitution、spec、plan、tasks) - 按正确顺序执行任务 - 遵循项目宪章中定义的开发方法(如 TDD) - 自动检查代码是否符合质量标准 - 执行必要的 CLI 命令(测试、构建等) - 提供进度更新和错误处理

Spec-Kit 的项目结构

.
├── CLAUDE.md                    # AI 助手配置(由 specify init 创建)
├── memory/
│   └── constitution.md          # 项目宪章(原则和约束)⭐️
├── specs/
│   └── 001-create-taskify/
│       ├── spec.md              # 功能规范
│       ├── plan.md              # 实现计划
│       ├── tasks.md             # 任务列表
│       ├── data-model.md        # 数据模型
│       ├── research.md          # 技术研究
│       ├── quickstart.md        # 快速开始指南
│       └── contracts/
│           ├── api-spec.json    # API 规范(可转为 OpenAPI)
│           └── signalr-spec.md  # SignalR 规范
├── scripts/
│   ├── check-prerequisites.sh   # 检查前置条件
│   ├── setup-plan.sh            # 规划脚本
│   ├── create-new-feature.sh    # 功能创建脚本
│   ├── update-claude-md.sh      # 更新 AI 配置
│   └── common.sh                # 通用工具函数
└── templates/
    ├── CLAUDE-template.md       # AI 配置模板
    ├── spec-template.md         # 规范模板
    ├── plan-template.md         # 计划模板
    └── tasks-template.md        # 任务模板

关键文件说明:

  • constitution.md - 定义项目的开发原则和约束
  • CLAUDE.md - AI 助手的配置文件
  • spec.md - 功能规范文档
  • plan.md - 技术实现方案
  • tasks.md - 任务列表

Spec-Kit vs 传统 SDD 工具

维度 Spec-Kit OpenAPI 工具
定位 项目级规范 API 级规范
使用场景 完整应用开发 API 接口设计
工作方式 AI 协同开发 代码生成
规范格式 Markdown 文档 YAML/JSON
生成内容 完整代码实现 接口骨架
适合对象 新项目开发 API 开发和文档

工具选择建议

Spec-Kit 适用场景: - 从零开始的新项目 - 需要 AI 助手协同开发 - 强调用户故事和需求验收 - 快速原型和 MVP 开发

OpenAPI 工具适用场景: - 专注于 API 设计和文档 - 需要跨语言客户端 SDK - 需要 Mock 服务和测试 - API 优先的开发模式

两者结合使用:

你可以在同一个项目中同时使用两种方法:

# 0. 初始化 Spec-Kit 项目
specify init --here --force --ai cursor-agent

# 1. 建立项目原则(定义代码质量、测试、性能等标准)
/speckit.constitution Create principles focused on code quality, testing standards, 
user experience consistency, and performance requirements

# 2. 使用 Spec-Kit 定义项目规范
/speckit.specify

# 3. 使用 Spec-Kit 创建技术方案(包括 API 规范)
/speckit.plan

# 4. 从 Spec-Kit 生成的 API 规范创建 OpenAPI 文档
cp specs/001-feature/contracts/api-spec.json openapi.yaml

# 5. 用 OpenAPI 工具生成客户端 SDK
openapi-generator-cli generate -i openapi.yaml -g typescript-axios -o ./client

# 6. 生成任务列表
/speckit.tasks

# 7. 用 Spec-Kit 实现服务端代码(AI 会遵循 constitution 中的原则)
/speckit.implement

# 8. 用 OpenAPI 工具生成 API 文档
redoc-cli bundle openapi.yaml -o docs/api.html

# 9. 启动 Mock 服务(前端开发可以并行进行)
prism mock openapi.yaml

这种组合的优势: - Spec-Kit 负责整体项目管理和服务端实现 - OpenAPI 提供标准化的 API 文档和客户端 SDK - Constitution 确保代码质量和一致性 - 前后端可以并行开发(通过 Mock 服务)

OpenAPI 工具生态:API 规范的标准方案

对于 API 开发,OpenAPI 提供了成熟的工具生态。

核心工具分类

OpenAPI 工具生态可以分为以下几类:

1. 代码生成工具

生成客户端 SDK、服务端框架代码:

# OpenAPI Generator(支持 50+ 语言)
openapi-generator-cli generate -i api.yaml -g go -o ./client

# Swagger Codegen(老牌工具)
swagger-codegen generate -i api.yaml -l java -o ./client

# oapi-codegen(Go 专用,轻量高效)
oapi-codegen -package api api.yaml > api/generated.go

2. 文档生成工具

生成漂亮的 API 文档:

# Swagger UI(最流行)
docker run -p 8080:8080 -e SWAGGER_JSON=/api.yaml -v ${PWD}:/api swaggerapi/swagger-ui

# Redoc(更现代的风格)
redoc-cli bundle api.yaml -o docs/index.html

# Stoplight Elements(交互式文档)
npx @stoplight/elements-dev-portal api.yaml

3. Mock 服务器

根据规范生成模拟 API:

# Prism(推荐,功能强大)
prism mock api.yaml

# Mockoon(GUI 工具)
mockoon-cli start --data api.yaml

# json-server + OpenAPI
openapi-backend mock api.yaml --port 3000

4. 验证和校验工具

检查规范文件的正确性:

# Swagger CLI(基础验证)
swagger-cli validate api.yaml

# Spectral(规则引擎,可自定义校验规则)
spectral lint api.yaml

# OpenAPI Enforcer(严格校验)
openapi-enforcer validate api.yaml

常用工作流

方案一:完全自动化(推荐用于团队协作)

# 1. 编写/更新规范
vim api.spec.yaml

# 2. 验证规范
spectral lint api.spec.yaml

# 3. 生成代码框架
openapi-generator-cli generate -i api.spec.yaml -g go -o ./generated

# 4. 生成文档
redoc-cli bundle api.spec.yaml -o docs/api.html

# 5. 启动 Mock 服务(供前端开发)
prism mock api.spec.yaml &

# 6. 实现业务逻辑
vim src/handlers/user.go

# 7. 运行测试
go test ./...

方案二:半自动化(适合小团队)

# 使用 Makefile 简化流程
cat > Makefile << 'EOF'
.PHONY: validate generate docs mock

validate:
    spectral lint api.yaml

generate:
    openapi-generator-cli generate -i api.yaml -g go -o ./generated

docs:
    redoc-cli bundle api.yaml -o docs/api.html

mock:
    prism mock api.yaml

all: validate generate docs
EOF

# 然后只需要
make all

方案三:CI/CD 集成

# .github/workflows/openapi.yml
name: OpenAPI Workflow

on: [push, pull_request]

jobs:
  validate-and-generate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Validate OpenAPI Spec
        run: |
          npm install -g @stoplight/spectral-cli
          spectral lint api.yaml

      - name: Generate Code
        run: |
          docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
            -i /local/api.yaml \
            -g go \
            -o /local/generated

      - name: Generate Docs
        run: |
          npm install -g redoc-cli
          redoc-cli bundle api.yaml -o docs/api.html

      - name: Commit Generated Files
        run: |
          git add generated/ docs/
          git commit -m "Auto-generated from OpenAPI spec" || true

完整开发流程时序图

sequenceDiagram
    participant PM as 产品经理
    participant BE as 后端开发
    participant FE as 前端开发
    participant Spec as 规范文件
    participant Tool as spec-kit
    participant CI as CI/CD

    PM->>BE: 提出需求
    BE->>Spec: 编写 API 规范
    BE->>Tool: 生成代码框架
    Tool-->>BE: 返回代码骨架

    par 并行开发
        BE->>BE: 实现业务逻辑
    and
        Tool->>FE: 生成 Mock 服务
        FE->>FE: 前端开发与联调
    end

    BE->>Tool: 生成 API 文档
    Tool-->>FE: 提供最新文档

    BE->>BE: 完成实现
    BE->>Tool: 验证规范一致性
    Tool-->>BE: 验证通过

    BE->>CI: 提交代码
    CI->>Tool: 自动验证规范
    Tool-->>CI: 验证通过
    CI->>CI: 部署到测试环境

    FE->>BE: 联调真实 API
    FE-->>BE: 反馈问题
    BE->>Spec: 更新规范
    Note over BE,Spec: 规范变更,<br/>重新生成代码

    style Spec fill:#f9d5e5
    style Tool fill:#d5f4e6
    style CI fill:#eeeeee

SDD 的简化实践方案

对于不需要复杂工具的场景,可以采用更轻量级的方式:

graph TB
    Start{项目规模?}
    Start -->|大型/企业级| A[完整 SDD 工具链<br/>spec-kit + OpenAPI]
    Start -->|中型/团队项目| B[轻量级方案<br/>Markdown + 结构化注释]
    Start -->|小型/个人项目| C[极简方案<br/>测试即规范]

    A --> A1[自动代码生成<br/>多语言支持<br/>Mock 服务器<br/>完整文档]
    B --> B1[手动代码框架<br/>文档模板<br/>脚本辅助]
    C --> C1[测试驱动<br/>代码注释<br/>最小化文档]

    style A fill:#ff6b6b
    style B fill:#ffd93d
    style C fill:#6bcf7f
    style A1 fill:#ffe5e5
    style B1 fill:#fff8e1
    style C1 fill:#e8f5e9

方法一:Markdown + 代码注释

使用 Markdown 文档配合代码注释:

# user-service-api.md

## 用户注册接口

**路径:** POST /api/v1/users/register

**请求:**
```json
{
  "email": "user@example.com",
  "password": "SecurePass123!",
  "nickname": "张三"
}

响应:

{
  "userId": "123",
  "email": "user@example.com",
  "nickname": "张三",
  "createdAt": "2025-11-09T20:20:00Z"
}

错误码: - 400: 请求参数错误 - 409: 邮箱已存在

然后在代码中引用:

```go
// 实现规范:user-service-api.md#用户注册接口
func RegisterUser(w http.ResponseWriter, r *http.Request) {
    // 按照规范实现...
}

方法二:结构化注释

在代码中使用结构化注释定义规范:

// @spec: User Registration API
// @method: POST
// @path: /api/v1/users/register
// @request:
//   email: string (required, email format)
//   password: string (required, min 8 chars)
//   nickname: string (required, 2-20 chars)
// @response:
//   201: { userId, email, nickname, createdAt }
//   400: { error: "请求参数错误" }
//   409: { error: "邮箱已存在" }
func RegisterUser(w http.ResponseWriter, r *http.Request) {
    // 实现...
}

然后用简单的脚本提取这些注释生成文档。

方法三:测试即规范

使用测试用例来定义规范:

func TestUserRegistration(t *testing.T) {
    // 规范:用户注册成功
    t.Run("注册成功", func(t *testing.T) {
        req := RegisterRequest{
            Email:    "user@example.com",
            Password: "SecurePass123!",
            Nickname: "张三",
        }
        resp := RegisterUser(req)
        assert.Equal(t, 201, resp.StatusCode)
        assert.NotEmpty(t, resp.UserID)
    })

    // 规范:邮箱格式错误
    t.Run("邮箱格式错误", func(t *testing.T) {
        req := RegisterRequest{
            Email:    "invalid-email",
            Password: "SecurePass123!",
            Nickname: "张三",
        }
        resp := RegisterUser(req)
        assert.Equal(t, 400, resp.StatusCode)
        assert.Contains(t, resp.Error, "邮箱格式")
    })

    // 规范:邮箱已存在
    t.Run("邮箱已存在", func(t *testing.T) {
        // 先创建一个用户
        RegisterUser(RegisterRequest{Email: "existing@example.com", ...})

        // 再次注册相同邮箱
        req := RegisterRequest{
            Email:    "existing@example.com",
            Password: "SecurePass123!",
            Nickname: "李四",
        }
        resp := RegisterUser(req)
        assert.Equal(t, 409, resp.StatusCode)
    })
}

这种方法的优势在于测试即规范,规范即测试。代码和规范的一致性由测试来保证,不一致时测试会失败。

方法四:GitHub Issues + 代码

使用 GitHub Issues 管理规范:

  1. 创建一个 Issue 模板:
## API 规范

### 接口名称
[描述]

### 请求格式
[格式]

### 响应格式
[格式]

### 实现
- [ ] 代码实现
- [ ] 测试用例
- [ ] 文档更新
  1. 每个功能创建一个 Issue
  2. 实现时引用 Issue:Closes #123
  3. Issue 关闭时,规范就完成了

实用技巧

1. 从现有代码生成规范

如果你已经有代码了,可以反向生成规范:

# 使用工具从代码提取 API 信息
swagger-codegen generate -i existing-code -o spec.yaml

# 或手动整理
# 1. 列出所有接口
# 2. 提取请求/响应结构
# 3. 整理成规范格式

2. 规范版本管理

规范文件也要版本控制:

# api.v1.spec.yaml
openapi: 3.0.0
info:
  version: 1.0.0

# api.v2.spec.yaml  
openapi: 3.0.0
info:
  version: 2.0.0

3. 规范审查

像代码审查一样审查规范:

## 规范审查清单

- [ ] 接口命名是否清晰?
- [ ] 请求/响应格式是否完整?
- [ ] 错误处理是否全面?
- [ ] 是否有安全考虑?
- [ ] 是否有性能要求?

4. 渐进式采用

不需要一次性重构所有代码,可以渐进式采用:

  1. 新功能用 SDD:所有新功能都先写规范
  2. 重构时补规范:重构旧代码时补充规范
  3. 重要接口优先:核心接口先规范化

总结与建议

规范驱动开发不是万能解决方案,但在合适的场景下能够有效提升开发效率。

SDD 的主要优势: - 保持代码和文档同步 - 规范作为前后端协作的契约 - 自动生成代码框架,减少重复劳动 - 规范本身就是文档,降低维护成本 - 可提供 Mock 服务,支持并行开发

适用场景: - API 开发(RESTful、GraphQL、gRPC) - 微服务架构 - 前后端分离项目 - 需要严格接口约定的项目 - 多团队协作的大型项目

实施建议: - 可以从轻量级方案开始(Markdown + 注释) - 使用测试来保证规范一致性 - 渐进式采用,新功能优先使用 SDD - 根据项目规模选择合适的工具

各种方法的协同关系

实用工具推荐

根据不同需求,这里是我的工具推荐:

需求 推荐工具 原因
代码生成 OpenAPI Generator 支持语言最多,社区活跃
Go 代码生成 oapi-codegen 轻量、快速、符合 Go 惯例
文档生成 Redoc 美观现代,单文件输出
Mock 服务 Prism 功能强大,支持各种场景
规范验证 Spectral 可自定义规则,IDE 集成好
在线编辑 Swagger Editor 实时预览,错误提示

各种方法的协同关系

graph LR
    subgraph 需求阶段
        BDD[BDD<br/>定义行为]
    end

    subgraph 设计阶段
        DDD[DDD<br/>领域建模]
        FDD[FDD<br/>功能拆分]
    end

    subgraph 实现阶段
        SDD[SDD<br/>接口规范]
        TDD[TDD<br/>测试驱动]
    end

    subgraph 交付阶段
        CI[持续集成<br/>CI/CD]
    end

    BDD --> DDD
    DDD --> FDD
    FDD --> SDD
    SDD --> TDD
    TDD --> CI

    style BDD fill:#e8f4f8
    style DDD fill:#e8f4f8
    style FDD fill:#fff4e6
    style SDD fill:#f0e6ff
    style TDD fill:#e1ffe1
    style CI fill:#d4edda

选择工具的原则是实用性优先。复杂工具不适合就用简单方案,关键是让规范和代码保持同步。方法论是手段,解决实际问题才是目的。

延伸阅读

规范和标准

工具和框架

设计方法论

开发方法论

文学编程

工具和实践

💬 最后的思考

软件开发从来没有银弹,但好的方法论可以让我们少走弯路。SDD 的核心价值不在于工具有多酷炫,而在于它倡导的理念:

让规范成为开发的起点,而不是终点的补充。

无论你选择使用完整的工具链,还是简单的 Markdown 文档,关键是找到适合你团队的方式,并坚持下去。

记住这三个原则: 1. 规范先行 - 在写代码之前先思考接口设计 2. 保持同步 - 让规范和代码始终一致 3. 持续改进 - 随着项目演进,不断优化规范

最后,如果你觉得这篇文章对你有帮助,不妨在下一个项目中尝试一下 SDD,哪怕只是从一个简单的 API 文档开始。

Happy Coding! 🚀


🔖 快速参考卡片

# SDD 快速参考

## 基本流程
1. 编写规范 → 2. 生成代码 → 3. 实现逻辑 → 4. 验证一致性

## 工具选择
- 大型项目:OpenAPI + spec-kit
- 中型项目:Markdown + 脚本
- 小型项目:测试 + 注释

## 最佳实践
✅ 规范先于代码
✅ 规范即文档
✅ 自动化验证
✅ 版本控制
✅ 团队协作

## 常见陷阱
❌ 先写代码后补规范
❌ 规范和代码不同步
❌ 过度设计
❌ 忽视工具学习成本


本作品采用知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议进行许可。