返回笔记首页

Agent时代,软件开发的范式

主题配置

**辅助开发&工程化:**Claude Code / Cursor / GitHub Copilot;掌握 **SDD(规范驱动开发)**方法论,通过 Spec 文件驱动 AI 生成符合团队规范的代码,管理系统模块开发效率提升约 60%

Agent时代,软件开发的范式

开发中 SDD(Spec-Driven Development)的实际案例

Agent时代,软件开发的范式

下面是四个案例的详细话术,面试时可以直接讲:

案例 1 — 搜索组件

"以前开发一个搜索组件,我直接打开 IDE 开始写,遇到问题就问 AI,复制粘贴进来调。但后来我改成 SDD 的方式:先写一份 search.spec.md,里面定义输入 props、防抖时间、空结果 / loading / error 三种状态的 UI 行为、以及无障碍访问要求。Spec 写完后,直接把它喂给 Claude Code,组件一次生成,符合预期。最关键的是,三个月后再改需求,我只需要改 Spec,意图不会丢。"

案例 2 — API 接口变更

"后端改了一个用户信息接口,把 userName 拆成 firstName + lastName。传统做法我要全局搜索、一个个改、还怕漏。SDD 做法是先把改动更新到 user-api.spec.md,包括请求/响应结构、错误码、分页边界。然后让 AI 重新读 Spec 生成 service 层,整个过程可控、可追溯,不依赖我记住'当时 AI 是怎么写的'。"

案例 3 — 多人协作表单

"我们三个人分别写一个申请流程里的表单模块,最后合进去风格不一:有人用 ElForm、有人手写校验、错误提示格式也不同。后来统一改成 SDD:先把表单规范写进共享的 form.spec.md,字段名、校验规则、错误提示模板都定好,大家各自让 AI 读同一份 Spec 生成代码。结果风格高度一致,新同学接手直接看 Spec,不用猜代码。"

案例 4 — AI Agent 项目(最有说服力)

"我做极速购 AI 客服系统时,早期 Agent 逻辑都是在 Cursor 对话里一点点迭代出来的,意图散落在聊天记录里。后来改成 SDD:先写 agent-flow.spec.md,定义用户意图的分类(查订单 / 退款 / 问产品)、每种意图对应哪个 Tool、失败时的 fallback 策略。这份 Spec 变成 Agent 的'说明书',需求一变,改 Spec 就行,AI 重新生成代码有理有据,团队协作也不会因为'AI 当时怎么想的'而撕扯。"

具体的实操案例

搜索组件开发

从需求到可运行组件,全程 Spec 驱动

Step 1 — 写 Spec 文件(不碰代码)

新建 search.spec.md,用自然语言把组件的所有"意图"写清楚

markdown
# search.spec.md

## 组件职责

用户输入关键词,300ms 防抖后触发搜索,结果列表展示

## Props

- modelValue: string — 当前搜索词(v-model)
- placeholder?: string — 默认"请输入关键词"
- debounce?: number — 防抖时间,默认 300ms

## Emits

- search(keyword: string) — 触发搜索
- clear() — 清空输入框

## 状态定义

| 状态    | 触发条件      | UI 表现          |
| ------- | ------------- | ---------------- |
| idle    | 初始/清空后   | 显示 placeholder |
| loading | search 触发后 | 输入框右侧转圈   |
| empty   | 返回结果为空  | 显示"暂无结果"   |
| error   | 接口报错      | 显示错误提示     |

## 边界场景

- 输入纯空格 → 不触发 search
- 连续输入期间只取最后一次
Step 2 — 把 Spec 喂给 AI 生成组件

打开 Claude Code 或 Cursor,用以下 Prompt:

markdown
请阅读 @search.spec.md,基于 Vue3 + TypeScript + Element Plus
生成 SearchBar.vue 组件,严格按照 Spec 中的 Props / Emits /
状态定义实现,不要添加 Spec 中未描述的功能。
Step 3 — 生成单元测试

继续让 AI 读同一份 Spec 生成测试,测试覆盖所有边界场景

markdown
请基于 @search.spec.md 中的"边界场景"和"状态定义",
生成 SearchBar.test.ts(Vitest + Vue Test Utils)
Step 4 — 需求变更只改 Spec

产品说要加"历史搜索记录"→ 在 Spec 里加一节,再跑一次 Step 2,代码自动更新,意图永远可查

API 接口字段变更

后端改字段,前端如何可控地跟进

Step 1 — 项目初期就建 api.spec.md

和后端对接时,第一件事不是写代码,而是把接口写进 Spec

markdown
# user-api.spec.md

## GET /api/user/profile

### 请求

无需参数(从 token 解析用户)

### 响应(200)

````json
{
  "userId": "string",
  "userName": "string",      ← 旧字段
  "email": "string",
  "avatar": "string | null"
}
```text

### 错误码

- 401: token 失效,前端跳登录页
- 404: 用户不存在,显示"账号异常"
text

##### **Step 2 — 后端改字段,先更新 Spec**

收到后端通知 `userName` 拆为 `firstName + lastName`,先改 Spec,再动代码

```markdown
- "userName": "string" ← 删除

* "firstName": "string" ← 新增
* "lastName": "string" ← 新增
* "displayName": "string" ← 新增(firstName + lastName 拼接)
```

##### **Step 3 — 让 AI 根据新 Spec 重新生成 service 层**

```markdown
@user-api.spec.md 已经更新,请重新生成:

1. userService.ts 中的 getUserProfile() 方法
2. 对应的 TypeScript interface UserProfile
3. 检查 UserCard.vue / UserAvatar.vue 是否用到
   旧字段 userName,如有,同步更新
```

##### **Step 4 — 用 TypeScript 做编译期兜底**

生成完成后跑 `tsc --noEmit`,所有还在用 `userName` 的地方会报类型错误,一个不漏

#### **多人协作大型表单**

3 人同时开发,风格统一不撕扯

##### **Step 1 — 开工前写共享 form.spec.md(负责人写)**

```markdown
# apply-form.spec.md

## 通用规范(所有人遵守)

- 校验时机:失焦 onBlur 触发,不是 onChange
- 错误提示:字段下方红色 12px 文字,不用 alert
- 必填标识:label 后加红色 \*,不在 placeholder 里写"必填"
- 提交按钮:loading 状态期间禁用 + 显示 spinner

## 模块分工

- 模块 A(小张):基本信息 — 姓名/手机/邮箱
- 模块 B(小李):教育经历 — 动态增删列表
- 模块 C(小王):附件上传 — 简历/证书,最大 5MB

## 字段规范示例(每人按此格式补充自己模块)

| 字段名 | 类型   | 必填 | 校验规则         |
| ------ | ------ | ---- | ---------------- |
| name   | string | 是   | 2~20个汉字或字母 |
| phone  | string | 是   | 11位手机号       |
| email  | string | 否   | 标准邮箱格式     |
```

##### **Step 2 — 每人各自补充自己模块的 Spec**

小李负责"教育经历"模块,在 Spec 里追加自己的字段和交互说明,PR 合入主 Spec 后再写代码

```markdown
Step 3 — 各自让 AI 读同一份 Spec 生成模块
```

```markdown
请阅读 @apply-form.spec.md 中的【通用规范】 和【模块 B:教育经历】部分,
生成 EduForm.vue 注意:校验时机、错误提示、提交按钮行为
必须严格遵循通用规范,不得自行决定
```

##### **Step 4 — Code Review 只审"是否符合 Spec"**

Review 标准清晰:对着 Spec 逐条检查,不再靠个人风格争论。新人接手直接读 Spec,5 分钟上手

#### **AI 客服 Agent 系统(最有说服力)**

LangChain.js 项目,意图不丢失在聊天记录里

##### **Step 1 — 写 agent-flow.spec.md(上代码之前)**

```markdown
# agent-flow.spec.md(极速购 AI 客服系统)

## Agent 职责

接收用户消息 → 识别意图 → 调用对应 Tool → 返回结果

## 意图分类与路由

| 用户意图      | 关键词示例         | 调用 Tool         |
| ------------- | ------------------ | ----------------- |
| 查订单状态    | 我的订单、物流在哪 | queryOrderTool    |
| 申请退款      | 退款、不想要了     | refundApplyTool   |
| 商品咨询      | 这个多少钱、有没有 | productSearchTool |
| 闲聊/无法识别 | 其他               | fallbackTool      |

## Tool 输入输出规范

### queryOrderTool

- 输入:{ orderId: string }
- 输出:{ status, estimatedDelivery, logistics[] }
- 失败:orderId 不存在 → 返回"未找到订单,请确认订单号"

## Fallback 策略

1. Tool 调用失败(网络/超时)→ 重试 1 次
2. 重试仍失败 → 回复"稍后再试",不暴露错误详情
3. 意图置信度 < 0.6 → 转人工客服

## Memory 设计

保留最近 6 轮对话作为上下文,避免用户重复说订单号
```

##### **Step 2 — 让 AI 读 Spec 生成 Agent 骨架**

```markdown
请阅读 @agent-flow.spec.md,使用 LangChain.js + DeepSeek API
生成以下文件:

1. tools/queryOrderTool.ts
2. tools/refundApplyTool.ts
3. agent/customerServiceAgent.ts(包含意图路由和 Memory)
   严格按照 Spec 中的输入输出规范和 Fallback 策略实现
```

##### **Step 3 — 新增 Tool 只需在 Spec 加一行**

产品说要加"积分查询"功能 → 在 Spec 的意图分类表里加一行,写清楚输入输出 → AI 生成新 Tool → 自动接入路由,不用翻之前的聊天记录

##### **Step 4 — Spec 即文档,对接后端直接共享**

把 `agent-flow.spec.md` 发给后端/产品,所有人对齐同一份"事实",不再靠口头沟通和 IM 截图

#### **最容易被追问的问题及答法:**

面试官问"Spec 谁来写,写多细?"→ 答:由负责人在开工前写,细到能让 AI 直接生成可运行代码为止——不够细的地方说明你自己也没想清楚需求。

面试官问"Spec 和注释有什么区别?"→ 答:注释解释代码"怎么做",Spec 定义系统"应该做什么"。Spec 是意图,代码是实现,意图不能丢在代码里,因为代码随时会被重写。

面试官问"实际团队推广难不难?"→ 答:难点在习惯,不在技术。我的做法是先在自己负责的模块跑通,拿可量化的结果说话——比如接口改字段那次,传统方式找漏改的地方花了半天,SDD 方式 10 分钟跑完 `tsc` 全部暴露。