大家应该有遇到过这种情况:接到一个需求,图省事,直接一句话甩给 AI ——"帮我实现 xxx",然后它"啪"地给你写了一大坨代码。
乍一看挺像样,但细看就会冒出一些问题:它可能顺手改了几个你没让它动的文件、自己脑补了一些你没交代过的边界处理、或者明明项目里已经有现成的工具函数,它非要自己再写一个。最后你花在"读它到底写了啥、再把多余的改动择出去"上的时间,未必比自己写少多少。
这不是 AI 不行,而是它在信息不全的时候只能靠猜。我们没把"要做什么、不要做什么"讲清楚,它就只好替我们做主。
2. Spec-First 工作流:先约定,再实现
2.1 一句话定义
做需求前,先让 AI 输出一份可被人工 review 的实现方案(spec),人工确认后再让它按方案写代码。
注意三个关键词:
- 可被 review:方案是中文说明,不是直接的代码,其他同学也能都看得懂
- 人工确认:spec 要通过确认后才能让 AI 去执行,避免在错误前提上累积工作量
- 按方案写:第二轮 prompt 把 spec 喂回去,让 AI 按既定方案写,约束自由发挥的空间
2.2 五步概览
1. 喂上下文:提示词、产品需求说明、设计稿、AGENTS.md、相关代码/文档、... 2. 出方案:让 AI 输出 spec 3. Review 改方案:重要的一步,人工主导,必须经人工确认后才可进行下一步 4. 按方案实现:让 AI 严格依据 spec 编码 5. 验收 reveiw:AI reveiw + 人工 reveiw2.3 适用 / 不适用
| 场景 | 是否适用 | 备注 |
|---|---|---|
| 新功能开发 | ✅ | 最佳场景 |
| 旧模块重构 | ✅ | spec 阶段需要先对齐边界 |
| 技术方案调研 | ✅ | spec 就是调研报告本身 |
| Bug 修复 | ⚠️ | 修复 bug 主要在于问题排查,改动往往是小范围的,效果有限 |
| 纯 Code Review | ❌ | 代码审查是为了提前发现问题,没有必要 |
3. 完整案例
Step 1 · 给 AI 足够的上下文
AI 出方案之前,先要让它"看到"足够的信息。对于一个常规需求,我们的输入主要有:
- 用户提示词(手动书写,需要包含基本的一些描述)
- 需求说明(形式可以为截图或文本描述,需要注意脱敏)
- figma 设计稿(形式可以是截图或 MCP 读取,推荐使用 MCP)
- AGENTS.md(agent 自动读取)
Step 2 · 让 AI 出方案
上下文准备好之后,这一轮的目标不是写代码,是写方案。给 AI 的提示词大致是这样:
我要在菜单下,新增一个模块: - 需求原型见上传的截图(需要手动上传) - figma设计稿如下: https://www.figma.com/xxx 请根据需求原型、figma设计稿和当前代码上下文输出详细实现的方案。 注意: - 需求原型截图和figma设计稿中的顶部导航栏和侧边菜单栏是已有的,不需要实现 - 原型截图中的红色文案是业务逻辑相关描述,要重点关注 - 不清楚的地方需要和我进行确认,禁止随意推测可以指定编程工具当前为 plan 模式(这个 claude、codex、cursor 都支持),输出实现方案。
AI 输出方案示例:
Step 3 · 人工 Review 并修正方案
我们 review 方案的时候通常会改这几类东西:
- 需求理解偏差:AI 复述的需求和我们想的不一样,及时纠正,spec 阶段发现成本最低
- 越界改动:AI 顺手要改一些跟当前需求无关的文件,要砍掉,保持最小范围
- 复用顺序错:AI 想自己新写一个工具函数,但目前项目里已经有了
- 假设没说明:AI 默默地假设了一些边界条件,要让它显式写出来或主动进行确认
- 遗漏边缘情况:加载状态、空状态、权限、异常分支等
Review 完后让 AI 重新生成 spec,再进行确认,直到 spec 双方都认可,才进入 Step 4。
示例:
Step 4 · 让 AI 按方案实现
第二轮的提示词示例:
请严格按照上面确认的方案实现。 - 不引入方案之外的改动 - 实现完成后,请按方案的"实现步骤"逐条说明你做了什么 - 如果实现过程中发现方案有问题,先停下来告诉我,不要自行调整或者有的 AI 工具直接提供了 spec 的 build 按钮,可以不需要额外提示词。
AI 生成代码示例:
import React, { useCallback, useEffect, useState } from 'react'; import OverviewPanel from './components/overviewPanel'; import RecordTable from './components/recordTable'; // ...省略 const ApiMonitor: React.FC = () => { const [overviewData, setOverviewData] = useState<IApiMonitorOverview>(); const [overviewLoading, setOverviewLoading] = useState(false); // ...省略 return ( <div className="api-monitor"> <OverviewPanel data={overviewData} loading={overviewLoading} /> <RecordTable data={recordData} loading={recordLoading} total={total} current={listParams.current ?? 1} pageSize={listParams.size ?? DEFAULT_PAGE_SIZE} sortField={sortField} sortOrder={sortOrder} searchForm={ <SearchForm callerOptions={callerOptions} onSearch={handleSearch} onReset={handleReset} /> } onPageChange={handlePageChange} onTableChange={handleTableChange} /> </div> ); }; export default ApiMonitor;页面效果: