本文为「AI 辅助编程实战指南」第6篇,完整系列持续更新中。


前言

你有没有遇到过这种情况:让 AI “帮我开发一个用户管理模块”,它一口气吐出 800 行代码——接口、模型、验证、错误处理全混在一起,还顺手加了你没要求的 WebSocket 通知功能。你一跑测试,红了一片。

这不是 AI 能力不行,而是你给它的任务太大了。AI 的上下文窗口和注意力分配机制决定了:任务越大,输出质量越不可控。真正高效的做法是把大任务拆成原子级小步,每步独立验证,再通过多轮迭代逐步逼近最终目标。

本篇学完你将掌握

  • AI 处理大任务时”翻车”的底层原因
  • 规格驱动开发(Spec-Driven Development)的核心方法论
  • 三层任务拆解模型:产品规格 → 变更规格 → 原子任务
  • 四阶段工作流:探索 → 计划 → 实现 → 提交
  • 五步迭代法:从初稿到生产级代码的完整优化路径
  • 跨会话任务续接的实用方案

一、为什么 AI 处理大任务容易”翻车”

在讲方法之前,先搞清楚问题出在哪。AI 处理大任务时翻车,不是偶然现象,而是由底层机制决定的。

1.1 三个结构性限制

限制 说明 翻车表现
注意力衰减 AI 的注意力预算有限,任务越长,后面的决策质量越差 前半段代码质量高,后半段开始”偷懒”或重复
上下文污染 长对话中,早期的关键信息被后续内容淹没 忘了前面定义的接口规范,前后代码风格不一致
缺乏全局视野 AI 只能看到当前上下文窗口内的内容,无法”纵观全局” 修改 A 模块时破坏与 B 模块的调用契约

这三个限制叠加后,会导致一个典型的恶性循环:

1
2
大任务 → AI 一次性输出大量代码 → 质量不可控 → 人工花大量时间修复
→ 修复引入新问题 → 继续修 → 越修越乱 → 推倒重来

1.2 一个典型的翻车场景

假设你对 AI 说:

1
2
帮我开发一个完整的电商商品管理系统,包括商品 CRUD、分类管理、
库存管理、价格策略和图片上传功能。

AI 大概率会:

  1. 一口气生成 15+ 个文件,包含模型、路由、控制器、服务层——但你还没确认数据模型设计
  2. 商品分类用了嵌套集合模型,但你的数据库不支持递归查询——它不知道你的技术约束
  3. 图片上传直接用了本地存储,但你部署在 Kubernetes 上——它不了解你的部署环境
  4. 价格策略里用了 float 类型——金额计算应该用 decimal
  5. 没有写任何测试——因为你没说要

根本原因:你给了一个”需求文档级别”的任务,但 AI 只能可靠地处理”函数级别”的任务。

💡 提示:Google AI 团队的 Addy Osmani 总结过一条核心原则——“给 AI 一个原子任务,审查代码,确认 OK 后提交,再做下一个。把每次 commit 当作存档点。”这个思路贯穿了整个任务拆解方法论。


二、规格驱动开发:先想清楚,再动手

任务拆解的前提是想清楚要做什么。如果你自己都没想明白,AI 更不可能帮你想明白。规格驱动开发(Spec-Driven Development)是一套在 AI 编程场景下验证过的高效方法:先用 15 分钟写好规格文档,再让 AI 按规格实现——而不是上来就让 AI 写代码。

2.1 三层规格体系

规格文档分为三个层级,从上到下逐步细化:

1
2
3
4
5
6
7
8
9
项目根目录/
├── PRODUCT_SPEC.md # 产品规格(长期维护,描述产品全貌)
├── changes/
│ ├── add-user-auth/
│ │ ├── CHANGE_SPEC.md # 变更规格(描述这次改动的目标)
│ │ └── PLAN.md # 实施计划(AI 生成,人工审核)
│ └── add-payment-module/
│ ├── CHANGE_SPEC.md
│ └── PLAN.md

第一层:产品规格(PRODUCT_SPEC.md)

描述产品的整体功能和架构,是 AI 每次会话开始时的”背景知识”。类似 README,但侧重于产品行为而非安装说明。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 商品管理系统 — 产品规格

## 产品概述
B2B 电商后台管理系统,面向运营人员,支持商品全生命周期管理。

## 技术栈
- 后端:FastAPI 0.110+、Python 3.12、PostgreSQL 16、SQLAlchemy 2.0
- 前端:React 19、TypeScript、Ant Design 5.x
- 存储:阿里云 OSS(图片)、Redis 7(缓存)

## 核心功能
- 商品 CRUD(支持草稿/上架/下架状态流转)
- 多级分类管理(最多 3 级,使用邻接表模型)
- 库存管理(支持多仓库,乐观锁防并发)
- 价格策略(阶梯价 + 会员价,金额统一用 decimal 类型)

## 架构约定
- 所有数据库操作通过 SQLAlchemy,禁止裸 SQL
- 金额字段统一使用 decimal(10,2),禁止 float
- 图片统一上传 OSS,数据库只存 OSS Key

💡 提示:产品规格的核心价值是防止 AI 做出违反产品逻辑的”优化”。比如 AI 可能把金额字段”优化”成 float,因为它不知道这是金融级系统——有了产品规格,这种翻车就能避免。

第二层:变更规格(CHANGE_SPEC.md)

描述某次具体改动的目标和约束——只写”做什么”和”为什么”,不写”怎么做”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 变更规格:新增商品批量导入功能

## 目标
运营人员通过上传 Excel 文件批量导入商品,支持 500 条以内的批量操作。

## 验收标准
- Excel 模板包含:商品名称、分类ID、价格、库存数量、图片URL
- 导入前校验数据完整性,校验失败返回详细错误行号
- 导入过程使用事务,任一行失败则全部回滚
- 导入完成后返回成功/失败/跳过的统计信息

## 约束
- 不引入新的第三方库(使用已有的 openpyxl)
- 不影响现有的商品 CRUD 接口
- 单次导入限制 500 行

第三层:实施计划(PLAN.md)

由 AI 根据变更规格生成,人工审核后作为实施指南。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 实施计划:商品批量导入

## Phase 1:数据模型和校验(预计 1 个会话)
- [ ] 创建 BulkImportResult 数据模型
- [ ] 实现 Excel 解析和数据校验逻辑
- [ ] 编写校验单元测试(覆盖:空行、格式错误、分类不存在)

## Phase 2:导入服务层(预计 1 个会话)
- [ ] 实现批量导入服务(事务控制、批量插入)
- [ ] 实现回滚机制(任一行失败全部回滚)
- [ ] 编写服务层单元测试

## Phase 3:API 接口(预计 1 个会话)
- [ ] 实现文件上传和导入接口
- [ ] 实现导入状态查询接口
- [ ] 编写接口集成测试

## 验证步骤
- [ ] 上传 500 行 Excel,确认全部导入成功
- [ ] 上传包含错误行的 Excel,确认全部回滚且返回错误详情
- [ ] 并发上传两个文件,确认无数据竞争

2.2 规格驱动的工作流

1
2
3
编写变更规格 → AI 生成实施计划 → 人工审核计划 → 逐阶段实施 → 每阶段验证 → 更新产品规格
↓ ↓ ↓ ↓ ↓
你想清楚 AI 帮你想怎么做 你把关方向 原子任务执行 保持规格最新

💡 建议:写规格文档看起来”浪费时间”,但相比 AI 一次性生成 800 行代码后再花 3 小时修复,花 15 分钟写规格文档的效率要高得多。规格文档还能在后续会话中复用,作为 AI 的上下文锚点。


三、三层任务拆解:从目标到原子任务

有了规格文档,下一步是把实施计划拆成可执行的原子任务。拆到什么粒度才算够?一个原子任务 = 一次 AI 会话能完成的工作量 = 一次 commit 的变更范围。

3.1 拆解模型

1
2
3
4
5
目标层:商品批量导入功能
↓ 拆为
功能层:数据解析 → 校验逻辑 → 导入服务 → API 接口 → 测试
↓ 拆为
步骤层:创建 BulkImportResult 模型 → 实现 Excel 解析函数 → 实现行校验函数 → ...

3.2 拆解的四个原则

原则 说明 判断标准
单一职责 每个原子任务只做一件事 能用一句话描述清楚任务目标
独立可验证 每个任务完成后能独立验证 有对应的测试或验证步骤
保持可运行 每完成一个任务,项目仍然能正常运行 不会留下”半成品”状态
边界清晰 明确任务涉及的文件和不动的文件 能列出修改范围清单

3.3 原子任务的 Prompt 模板

把原子任务转化为 AI Prompt 时,使用以下模板:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
【上下文】
参考变更规格 changes/add-bulk-import/CHANGE_SPEC.md
当前阶段:Phase 1 — 数据模型和校验

【本次任务】
创建 BulkImportResult 数据模型,用于记录批量导入的结果。

【具体要求】
1. 模型字段:id、file_name、total_rows、success_rows、failed_rows、
error_details(JSON 类型)、status(pending/processing/completed/failed)、
created_at、completed_at
2. 使用 SQLAlchemy 2.0 声明式映射
3. 字段类型遵循项目规范:金额用 decimal,时间用 datetime(timezone=True)
4. 在 models/ 目录下创建 bulk_import.py

【不要做】
- 不要修改现有的商品模型
- 不要创建迁移脚本(后续统一处理)
- 不要添加新的依赖

💡 提示:注意 Prompt 里的”不要做”部分——这是防止 AI “好心办坏事”的关键。每次给任务时,明确列出不在本次修改范围内的文件和功能。


四、四阶段工作流:先探索,再计划,最后动手

任务拆完之后,每个原子任务的执行过程也有讲究。直接让 AI 写代码是效率最低的方式——正确做法是走”探索 → 计划 → 实现 → 提交”的四阶段流程。

4.1 阶段总览

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
┌─────────────┐
│ 1. 探索阶段 │ ← 只读模式:理解现有代码和架构
│ (Plan) │
└──────┬──────┘

┌─────────────┐
│ 2. 计划阶段 │ ← AI 输出方案,人工审核调整
│ (Plan) │
└──────┬──────┘

┌─────────────┐
│ 3. 实现阶段 │ ← 按计划逐步编码
│ (Normal) │
└──────┬──────┘

┌─────────────┐
│ 4. 提交阶段 │ ← 验证通过,提交 commit
└─────────────┘

4.2 各阶段详细说明

阶段 1:探索(Plan Mode / 只读)

在这个阶段,AI 只读取代码、不写任何东西。目标是理解当前代码库的状态。

1
2
3
4
5
读取 src/models/ 目录,理解现有的数据模型结构和命名规范。
重点关注:
1. 模型基类是怎么定义的
2. 字段命名用 snake_case 还是 camelCase
3. 关系定义用 lazy loading 还是 eager loading

Claude Code 用户可以使用 Plan Mode(按 Shift+Tab 切换),这个模式下 AI 被强制禁止修改文件,只能读取和分析。Cursor 用户可以在 Chat 模式下使用 @Code 引用相关代码。

阶段 2:计划(仍在 Plan Mode)

基于探索阶段的理解,让 AI 输出实现方案。

1
2
3
4
5
基于你对现有模型的理解,设计 BulkImportResult 模型的方案:
1. 字段定义和类型选择
2. 与现有模型基类的继承关系
3. 需要新增的索引
不要写代码,只输出设计文档。

审核 AI 的方案,重点检查:

  • 字段类型是否符合项目规范
  • 是否遗漏了必要的约束(唯一性、外键等)
  • 命名是否与现有代码风格一致

阶段 3:实现(Normal / Auto-Accept Mode)

确认方案后,切换到正常模式执行:

1
2
按照刚才确认的方案,实现 BulkImportResult 模型。
创建文件 src/models/bulk_import.py。

阶段 4:提交

验证通过后立即提交:

1
2
3
4
5
6
# 运行测试确认没有破坏现有功能
python -m pytest tests/models/ -v

# 确认 OK 后提交
git add src/models/bulk_import.py
git commit -m "feat(models): 新增批量导入结果模型 BulkImportResult"

💡 建议:Claude Code 的创建者 Boris Cherny 据称将约 80% 的时间花在 Plan Mode 上——先探索、再计划、反复迭代方案,最后才切换到执行模式快速完成。这个比例值得借鉴。


五、五步迭代法:从初稿到生产级代码

原子任务完成后的代码,距离”生产级”通常还有距离。不要指望 AI 一次输出完美代码——正确的做法是通过多轮迭代逐步打磨。每一步只聚焦一个维度的优化,避免一次给太多要求。

5.1 五步迭代总览

1
2
3
第1步:功能初稿 → 第2步:细化完善 → 第3步:边界处理 → 第4步:性能优化 → 第5步:代码审查
↓ ↓ ↓ ↓ ↓
能跑就行 代码规范+测试 异常和边界case 性能瓶颈调优 安全+架构审视

5.2 每一步的 Prompt 模板

第 1 步:功能初稿

1
2
3
实现商品批量导入的 Excel 解析函数 parse_excel_import()。
功能:读取 Excel 文件,返回解析后的商品列表。
先实现正常流程即可,不用考虑异常情况。

关键词:先实现正常流程。这一步的目标是快速跑通 Happy Path。

第 2 步:细化完善

1
2
3
4
审查刚才的 parse_excel_import() 函数,补充以下内容:
1. 添加类型注解(参数和返回值)
2. 添加函数文档字符串(说明参数、返回值、异常)
3. 编写 3 个 pytest 测试用例:正常导入、空文件、格式错误

第 3 步:边界处理

1
2
3
4
5
6
为 parse_excel_import() 补充边界情况处理:
1. 文件大小超过 10MB 时的处理
2. 行数超过 500 行时的拒绝
3. 单元格包含特殊字符(换行、HTML 标签)时的清洗
4. 分类 ID 不存在时的校验
每个边界情况都要有对应的测试用例。

第 4 步:性能优化

1
2
3
4
5
分析 parse_excel_import() 的性能瓶颈:
1. 500 行 Excel 的解析时间目标:< 5 秒
2. 如果有多次数据库查询,是否可以批量化
3. 大文件解析是否可以用流式处理
请分析当前代码的性能表现,给出优化方案和代码修改。

第 5 步:代码审查

1
2
3
4
5
请从安全和架构角度审查 parse_excel_import() 的最终版本:
1. 是否有安全风险(文件类型伪造、路径遍历)
2. 是否符合项目的分层架构(解析逻辑不应包含数据库操作)
3. 错误处理是否完善(异常是否正确传播,日志是否记录)
4. 是否需要添加速率限制

5.3 迭代节奏建议

步骤 建议会话数 关键点
功能初稿 1 个会话 快速跑通,不追求完美
细化完善 1 个会话 代码规范 + 基础测试
边界处理 1-2 个会话 每个边界 case 单独验证
性能优化 0-1 个会话 不是所有功能都需要
代码审查 1 个会话 可用 code-reviewer Skill

⚠️ 注意:不要把 5 个步骤的 Prompt 合并成一条发给 AI。每步一个会话,让 AI 的上下文保持干净——这就是”用会话边界对抗注意力衰减”的具体实践(详见第7篇:上下文管理)。


六、跨会话任务管理:让 AI 在多个会话间不迷路

中大型功能不可能在一个会话中完成。当任务跨越多个会话时,最大的挑战是让新会话的 AI 知道之前做了什么、接下来该做什么

6.1 进度文件(PROGRESS.md)

在项目根目录维护一个进度文件,每次新会话开始时让 AI 读取:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 开发进度:商品批量导入功能

## 已完成
- [x] Phase 1:BulkImportResult 数据模型(commit: a1b2c3d)
- [x] Phase 1:Excel 解析函数 parse_excel_import()(commit: e4f5g6h)
- [x] Phase 1:行校验函数 validate_import_row()(commit: i7j8k9l)
- [x] Phase 2:批量导入服务 bulk_import_service()(commit: m0n1o2p)

## 进行中
- [ ] Phase 3:文件上传 API 接口(已完成路由定义,待实现控制器逻辑)

## 待完成
- [ ] Phase 3:导入状态查询接口
- [ ] 集成测试
- [ ] 更新产品规格文档

## 已知问题
- validate_import_row() 对包含换行符的单元格处理有 Bug,待修复
- 并发导入时的事务隔离级别需要确认

新会话的开场 Prompt

1
2
请先阅读 PROGRESS.md 和 changes/add-bulk-import/CHANGE_SPEC.md,
了解当前进度。然后继续完成"文件上传 API 接口"的控制器逻辑。

6.2 原子提交策略

每次 AI 完成一个原子任务后,立即提交——不要积攒多个变更一起提交。

1
2
3
4
5
6
7
# 好的做法:每完成一个原子任务就提交
git commit -m "feat(import): 实现 Excel 解析函数 parse_excel_import"
git commit -m "feat(import): 实现行校验函数 validate_import_row"
git commit -m "feat(import): 实现批量导入服务 bulk_import_service"

# 不好的做法:一堆变更混在一起
git commit -m "feat(import): 完成批量导入功能" # 包含了 15 个文件的变更

原子提交的好处:

  • 回滚方便:某一步出了问题,只回退那一步的 commit,不影响其他工作
  • 审查方便:每个 commit 的 diff 清晰可读,不是一团乱麻
  • 续接方便:新会话可以通过 git log 快速了解已完成的工作

6.3 会话续接的完整流程

1
2
3
完成当前任务 → 运行测试 → 提交 commit → 更新 PROGRESS.md
→ 关闭会话 → 开启新会话 → 让 AI 读取 PROGRESS.md
→ 继续下一个任务

💡 建议:不要在一个会话里做两件事。即使上下文预算还有剩余,切换到新任务时也应该开新会话。新鲜的上下文是免费的,但被污染的上下文是昂贵的——它会让你花更多时间修复 AI 的错误输出。


七、踩坑记录:AI “好心”重构了认证模块,测试全绿却没发现

现象
使用 AI 的 Agent 模式开发”商品导出”功能。AI 在实现导出逻辑的同时,”顺便”重构了用户权限校验模块——理由是”权限校验逻辑可以抽取为公共函数”。所有单元测试通过,但上线后部分管理员无法访问导出功能。

原因

  1. AI 把权限校验从内联逻辑重构为公共函数时,改变了参数传递方式
  2. 单元测试 mock 了权限校验函数,所以测试能通过
  3. 但实际的权限校验逻辑在新函数里少了一个角色判断条件
  4. 由于是 Agent 模式(完全自主),AI 在修改认证模块时没有经过人工确认

解决方案

  1. 立即回滚权限校验模块的变更(git revert
  2. src/auth/src/middleware/ 加入文件保护清单(详见第5篇
  3. 为权限校验补充集成测试(不是 mock,是真实调用)
  4. 后续 AI 任务在 Prompt 中明确标注:”不要修改 auth/ 和 middleware/ 目录下的任何文件”

避坑建议

  • 任务拆解时,明确列出”不在本次修改范围内”的文件和目录
  • Agent 模式效率虽高,但涉及核心模块时必须降级为受限编辑模式
  • 测试通过不等于没有问题——单元测试的 mock 可能掩盖真实 Bug,权限和安全模块必须有集成测试
  • AI 的”顺手优化”是双刃剑:如果优化不在你的计划内,先拒绝,单独开一个会话评估

总结与回顾

核心要点 关键结论
翻车根因 AI 的注意力衰减、上下文污染和缺乏全局视野,决定了大任务必须拆解
规格驱动 产品规格 → 变更规格 → 实施计划,三层文档锚定 AI 的方向
任务拆解 拆到”一次会话能完成 = 一次 commit 的范围”才算原子任务
四阶段工作流 探索 → 计划 → 实现 → 提交,先读后写,先想后做
五步迭代法 初稿 → 细化 → 边界 → 性能 → 审查,每步只聚焦一个维度
跨会话管理 PROGRESS.md + 原子提交 + 新会话读取进度,三件套搞定续接
核心原则 一个会话只做一件事,完成后立即提交,不要在”还有预算”时继续加任务

延伸阅读


本文为「AI 辅助编程实战指南」第6篇,完整系列持续更新中。