先让 AI 出方案,再让它写代码:新手也能使用的设计习惯

前一篇文章中,我们学习了如何让 AI 帮助拆分一个功能需求。

我们把"商品列表增加搜索和分类筛选"拆成了:

  • 页面任务。
  • 接口任务。
  • 数据任务。
  • 测试任务。

拆分需求之后,还有一个很容易被忽略的步骤:

在开始修改代码之前,先让 AI 给出实现方案。

很多初学者拿到任务清单后,会马上说:

text 复制代码
请根据上面的需求生成完整代码。

这样做不一定错,但很容易出现下面的问题:

  • AI 一次修改太多文件。
  • 代码结构和项目现状不匹配。
  • 方案中的关键假设没有被发现。
  • 一个小功能被实现得过于复杂。
  • 代码写完后才发现数据结构不合理。
  • 出现问题时,不知道应该回退哪一步。

今天我们就来学习一个非常实用的开发习惯:

text 复制代码
先理解需求
  ↓
再设计方案
  ↓
确认方案
  ↓
最后编写代码

这不是增加无意义的文档工作,而是用几分钟的思考,减少后面几十分钟甚至几个小时的返工。

一、什么是"先出方案,再写代码"

这里说的"方案",不一定是一份很正式的架构设计文档。

对于一个小功能来说,一份合格的方案通常只需要回答下面几个问题:

  • 这个功能要解决什么问题。
  • 用户会按照什么流程操作。
  • 数据从哪里来,保存到哪里。
  • 需要修改哪些文件。
  • 每个文件分别负责什么。
  • 可能出现哪些异常情况。
  • 应该按照什么顺序实现。
  • 完成后如何验证。

例如,我们有一个待办事项页面,现在希望实现:

刷新页面后,之前添加的待办事项仍然保留。

如果直接写代码,可能马上想到 localStorage

但真正实现之前,还应该先确认:

  • 保存的是全部待办,还是只保存未完成待办。
  • 页面打开时什么时候读取数据。
  • 添加、完成、删除之后是否都要重新保存。
  • localStorage 中没有数据时使用什么默认值。
  • 保存的数据损坏时如何处理。
  • 是否需要限制待办数量。

方案的作用,就是先把这些问题理清楚。

二、为什么直接写代码容易返工

1. 代码会掩盖需求问题

当 AI 直接输出代码时,很多设计决定已经悄悄被写进去了。

例如:

javascript 复制代码
localStorage.setItem("todos", JSON.stringify(todos));

这行代码看起来很简单,但它已经默认了:

  • 存储键名叫 todos
  • todos 是一个可以被 JSON 序列化的数组。
  • 所有待办都保存在浏览器本地。
  • 没有考虑数据格式变化。

如果这些决定没有提前确认,后面再修改时就可能需要同时改读取、保存、初始化和删除逻辑。

2. 一次改动太多,问题难以定位

AI 可能一次性修改:

  • HTML 结构。
  • CSS 样式。
  • JavaScript 数据逻辑。
  • 工具函数。
  • 配置文件。

如果最后页面出现问题,你很难判断:

  • 是页面元素没有找到。
  • 是数据没有正确读取。
  • 是保存时机不对。
  • 还是 AI 修改了原本正常的代码。

3. 设计不合理时,后续功能会越来越难加

如果一开始没有想清楚数据结构,后面增加编辑、筛选、排序等功能时,可能需要重新改动大量代码。

方案不一定能保证第一次就完美,但它能让我们提前看见主要的设计选择。

三、一个简单方案应该包含哪些内容

对于初学者,可以使用下面这 8 个部分:

text 复制代码
1. 需求理解
2. 功能范围
3. 用户操作流程
4. 数据结构
5. 文件和模块改动
6. 异常和边界情况
7. 实现步骤
8. 验收标准

下面逐项说明。

1. 需求理解

先让 AI 用自己的话复述需求。

例如:

text 复制代码
用户可以在待办事项页面添加、完成和删除任务。
刷新页面后,之前的数据仍然可以恢复。
数据只保存在当前浏览器中,不接入服务器和数据库。

这一步可以帮助我们发现 AI 是否理解错了目标。

2. 功能范围

明确这次做什么,以及暂时不做什么。

例如:

text 复制代码
本次要做:
- 页面加载时读取本地待办。
- 新增待办后保存数据。
- 标记完成后保存数据。
- 删除待办后保存数据。

本次不做:
- 不接入后端接口。
- 不做多设备同步。
- 不做用户登录。
- 不做数据导出。

范围越清楚,AI 越不容易自行扩展。

3. 用户操作流程

把用户的操作写成步骤:

text 复制代码
打开页面
  ↓
读取本地数据
  ↓
有数据就展示,无数据就展示空列表
  ↓
用户新增、完成或删除待办
  ↓
更新页面
  ↓
保存最新数据

流程图不需要很复杂,重点是让数据变化过程清楚。

4. 数据结构

先确定数据长什么样。

例如:

javascript 复制代码
[
  {
    "id": "todo-001",
    "title": "学习 AI 编程",
    "completed": false,
    "createdAt": "2026-08-23T09:00:00.000Z"
  }
]

每个字段都应该说明用途:

字段 类型 作用
id string 唯一标识一条待办
title string 待办内容
completed boolean 是否已完成
createdAt string 创建时间

5. 文件和模块改动

提前列出可能修改的文件:

text 复制代码
可能修改:
- index.html:不需要修改结构,确认已有输入框和列表容器。
- src/todo-storage.js:新增读取和保存本地数据的方法。
- src/todo.js:在新增、完成、删除后调用保存方法。
- src/render.js:继续负责页面渲染,不混入存储细节。

如果是一个简单练习,也可以只有一个 HTML 文件。

重要的是:先让 AI 说明"为什么要改这些文件",而不是让它随意创建文件。

6. 异常和边界情况

至少提前考虑:

  • 本地没有数据。
  • 本地数据格式不正确。
  • 待办内容为空。
  • 待办内容只有空格。
  • localStorage 保存失败。
  • 待办数量过多。
  • 数据字段缺失。

不一定所有情况都要在第一版处理,但应该明确哪些要做,哪些暂时忽略。

7. 实现步骤

将方案变成有顺序的步骤:

text 复制代码
第一步:定义待办数据结构。
第二步:实现读取本地数据的方法。
第三步:实现保存本地数据的方法。
第四步:页面加载时读取并渲染数据。
第五步:在新增操作后保存数据。
第六步:在完成和删除操作后保存数据。
第七步:补充空值和数据格式校验。
第八步:按照验收标准逐项测试。

8. 验收标准

方案最后要说明什么情况下算完成:

text 复制代码
验收标准:
1. 新增一条待办后刷新页面,待办仍然存在。
2. 标记一条待办完成后刷新,完成状态保持不变。
3. 删除一条待办后刷新,被删除的事项不会重新出现。
4. 输入为空或只有空格时,不新增待办。
5. 本地没有历史数据时,页面可以正常打开。
6. 本地数据格式异常时,页面不会直接崩溃。

四、完整案例:为待办事项增加本地存储

下面用一个简单案例演示如何让 AI 先出方案。

原始需求

text 复制代码
请给待办事项增加本地存储,刷新页面后数据不要丢失。

这句话仍然不够完整。

我们可以补充项目背景:

text 复制代码
项目背景:
- 使用原生 HTML、CSS 和 JavaScript。
- 当前已经实现新增、标记完成和删除待办。
- 待办数据保存在 JavaScript 数组 todos 中。
- 页面通过 renderTodos 函数重新渲染列表。
- 本次只使用浏览器 localStorage,不新增第三方依赖。

不推荐的提问方式

text 复制代码
帮我加 localStorage。

这个提问会让 AI 自行决定:

  • 保存逻辑放在哪里。
  • 使用什么键名。
  • 什么时候读取。
  • 什么时候写入。
  • 如何处理旧数据。

推荐的提问方式

text 复制代码
我有一个原生 JavaScript 待办事项页面,
当前已经实现新增、标记完成和删除功能。

当前数据结构是:
[
  {
    id: "todo-001",
    title: "学习 AI 编程",
    completed: false
  }
]

本次需求:
1. 使用浏览器 localStorage 保存待办数据。
2. 页面打开时读取历史数据。
3. 新增、标记完成和删除后都保存最新数据。
4. 本地没有数据时使用空数组。
5. 本地数据格式错误时不要让页面崩溃。

限制:
1. 不新增第三方依赖。
2. 不修改现有页面样式。
3. 不重写已有的新增、完成和删除逻辑。
4. 先不要写代码。

请先输出:
1. 你对需求的理解。
2. 数据读写流程。
3. 需要修改的函数或文件。
4. 异常情况处理方案。
5. 分步骤实现计划。
6. 可执行的验收标准。

这次 AI 的任务不是"马上写代码",而是先交付一份可以检查的方案。

五、如何审查 AI 给出的方案

拿到方案后,不要直接回复"开始写代码"。

先使用下面 6 个问题检查。

1. 方案是否解决了真正的需求

原始需求是:

刷新页面后数据不要丢失。

方案至少应该包含:

  • 页面加载时读取数据。
  • 数据变化后保存数据。
  • 保存的数据能够在下一次加载时恢复。

如果 AI 只说"新增一个保存按钮",就没有解决真正的问题。

2. 方案是否符合当前技术栈

如果项目是原生 JavaScript,方案却引入 Redux、Pinia 或数据库,就需要让 AI 缩小范围。

可以这样回复:

text 复制代码
当前只是原生 JavaScript 入门练习,
请删除框架、后端和第三方库相关内容,
只保留浏览器 localStorage 的实现方案。

3. 是否修改了不必要的内容

本次需求是增加数据持久化。

如果方案提出同时重写渲染函数、修改 CSS、替换 HTML 结构,就应该要求 AI 说明必要性。

可以这样问:

text 复制代码
请把方案中的改动分为"必须修改"和"可以不修改"两类,
并解释每项改动的原因。

4. 数据流是否清楚

需要看清楚数据怎样流动:

text 复制代码
localStorage
  ↓ 读取
todos 数组
  ↓ 渲染
页面列表

用户操作
  ↓ 修改
todos 数组
  ↓ 保存
localStorage

如果方案没有说明读取、修改、渲染和保存之间的关系,后面很容易出现页面显示正确但刷新后丢数据的问题。

5. 异常情况是否有处理方式

至少要问 AI:

  • 没有数据怎么办。
  • 数据不是合法 JSON 怎么办。
  • JSON 格式正确但不是数组怎么办。
  • 保存失败怎么办。
  • 数据中缺少字段怎么办。

不一定所有异常都要复杂处理,但不能完全没有考虑。

6. 每一步是否能够单独验证

例如:

text 复制代码
实现读取方法后,如何确认读取结果正确?
实现保存方法后,如何查看 localStorage 中的数据?
页面加载恢复后,如何验证完成状态没有丢失?

如果每一步都有验证方法,AI 生成代码后就更容易逐步检查。

六、把方案交给 AI 后,如何分阶段写代码

方案确认后,也不要马上要求 AI 输出整个项目。

可以按照"一个目标、一次验证"的方式推进。

第一步:先实现数据读取

text 复制代码
请只实现读取 localStorage 的方法。

要求:
1. 使用固定键名保存待办。
2. 没有数据时返回空数组。
3. JSON 解析失败时返回空数组,并保留一个可查看的错误提示。
4. 如果解析结果不是数组,也返回空数组。
5. 不修改页面渲染和用户操作代码。

请先说明实现思路,再给出代码和测试方法。

完成后验证:

javascript 复制代码
localStorage.removeItem("todos");
console.log(loadTodos());

预期结果是:

text 复制代码
[]

第二步:再实现数据保存

text 复制代码
请在现有读取方法的基础上,
只增加保存待办数组的方法。

要求:
1. 接收 todos 数组作为参数。
2. 使用 JSON.stringify 保存。
3. 不修改读取逻辑。
4. 给出一个最小测试示例。

验证方法:

javascript 复制代码
const testTodos = [
  {
    id: "todo-001",
    title: "测试保存",
    completed: false
  }
];

saveTodos(testTodos);
console.log(localStorage.getItem("todos"));

第三步:接入页面加载

text 复制代码
请将 loadTodos 接入页面初始化流程。

要求:
1. 页面加载时先读取本地数据。
2. 将读取结果赋值给现有 todos 数组。
3. 继续调用现有 renderTodos 方法。
4. 不修改新增、完成和删除功能。
5. 说明页面初始化的执行顺序。

第四步:接入用户操作

分别让 AI 处理新增、完成和删除后的保存。

例如:

text 复制代码
请只修改新增待办的处理函数。

要求:
1. 保留现有的空输入校验。
2. 新增成功后继续调用 renderTodos。
3. 渲染完成后调用 saveTodos(todos)。
4. 不修改完成和删除逻辑。
5. 给出修改前后的关键差异。

完成新增后,再分别处理完成和删除。

第五步:补充异常处理

最后再让 AI 检查:

text 复制代码
请检查当前 localStorage 持久化实现,
重点关注:
1. 数据为空。
2. JSON 格式损坏。
3. 解析结果不是数组。
4. 待办对象缺少字段。
5. 保存失败。

请只列出风险和测试建议,
暂时不要重写代码。

这种分阶段方式比"一次生成全部代码"更容易理解和回退。

七、方案中要特别关注数据流

很多代码问题,本质上不是语法问题,而是数据流没有设计清楚。

以待办本地存储为例,应该明确下面几个时机:

页面首次打开

text 复制代码
读取 localStorage
  ↓
解析数据
  ↓
校验数据结构
  ↓
赋值给 todos
  ↓
调用 renderTodos

新增待办

text 复制代码
读取输入内容
  ↓
校验不能是空内容
  ↓
创建新的待办对象
  ↓
加入 todos 数组
  ↓
调用 renderTodos
  ↓
调用 saveTodos

标记完成

text 复制代码
找到对应 id
  ↓
修改 completed
  ↓
调用 renderTodos
  ↓
调用 saveTodos

删除待办

text 复制代码
根据 id 删除数据
  ↓
调用 renderTodos
  ↓
调用 saveTodos

如果方案只说明"使用 localStorage",但没有说明这些时机,代码很可能只保存了新增,没有保存完成和删除。

八、什么时候应该让 AI 重新出方案

以下情况出现时,不要急着继续改代码,最好回到方案阶段:

  • 需求发生了明显变化。
  • 需要更换技术方案。
  • 发现原来的数据结构不够用。
  • 修改范围从一个文件扩大到多个模块。
  • AI 连续给出互相矛盾的建议。
  • 修复一个问题导致多个旧功能异常。
  • 你已经无法解释当前代码的执行流程。

可以这样要求 AI:

text 复制代码
当前实现已经和最初方案有较大差异。
请不要继续直接修改代码,
先根据当前代码和新需求重新整理一份方案。

请重点说明:
1. 原方案哪些地方已经不适用。
2. 当前数据流是什么。
3. 哪些文件需要修改。
4. 如何避免影响已有功能。
5. 重新实现的步骤和验收标准。

重新规划不是失败。

当需求、数据或技术约束发生变化时,重新出方案本来就是正常的开发动作。

九、不要把方案设计成过度复杂的架构

先出方案,不代表每个小功能都要设计成大型系统。

初学者尤其要注意"过度设计":

  • 只是本地练习,却设计微服务。
  • 只有一个页面,却引入复杂状态管理。
  • 只有几条数据,却提前设计分布式缓存。
  • 只需要一个工具函数,却创建很多抽象层。
  • 还没有真实问题,就先增加大量配置。

可以让 AI 遵循一个原则:

text 复制代码
请优先给出最小可行方案。
只增加当前需求必须的文件、依赖和抽象。
如果存在进阶方案,请单独列出,不要混入第一版实现。

方案的好坏,不是看内容有多复杂,而是看它是否:

  • 解决当前问题。
  • 容易理解和验证。
  • 与项目现状匹配。
  • 为后续扩展保留合理空间。

十、一个适合新手的方案确认清单

AI 输出方案后,可以逐项检查:

text 复制代码
[ ] 我能用自己的话说清楚这份方案要解决什么问题
[ ] 方案符合当前项目使用的语言和框架
[ ] 方案明确了本次做什么和不做什么
[ ] 方案说明了数据从哪里来、到哪里去
[ ] 方案列出了需要修改的文件或模块
[ ] 方案考虑了至少一个异常情况
[ ] 方案没有引入不必要的依赖
[ ] 方案没有修改无关功能
[ ] 每个实现步骤都可以单独验证
[ ] 方案包含明确的验收标准

如果有两三项无法确认,就先不要让 AI 写代码。

可以继续追问:

text 复制代码
请针对我无法确认的第 [编号] 项,
用更简单的语言解释,并给出一个小例子。

十一、可直接复用的"先方案后代码" Prompt 模板

下面这份模板可以用于大多数功能开发任务:

text 复制代码
我需要在一个现有项目中开发新功能,
请先出方案,不要直接写完整代码。

项目背景:
- 项目类型:[例如:管理后台、个人练习项目]
- 前端技术:[框架和版本]
- 后端技术:[语言/框架和版本]
- 数据库:[数据库类型,没有则填写"无"]
- 当前相关文件或模块:[文件路径和作用]

需求描述:
[粘贴原始需求]

本次目标:
[明确希望用户最终完成什么]

本次范围:
- 要做:[必须完成的内容]
- 不做:[明确排除的内容]

已知约束:
- [例如:不能新增第三方依赖]
- [例如:兼容当前项目版本]
- [例如:不能修改已有接口]

请按下面结构输出:
1. 需求理解
2. 需要确认的问题和你的最小可行假设
3. 用户操作流程
4. 数据结构和数据流
5. 文件或模块改动清单
6. 异常和边界情况
7. 分阶段实现步骤
8. 每一步的验证方法
9. 最终验收标准

请遵守:
- 不要扩大需求范围。
- 不要虚构不存在的文件和依赖。
- 优先选择简单、容易验证的方案。
- 对不确定的内容明确标注,不要假装确定。
- 等我确认方案后,再开始写代码。

当方案确认后,可以继续发送:

text 复制代码
方案可以开始实施。
请只完成第 1 步:
[粘贴第 1 步]

要求:
1. 先说明本次会修改哪些文件。
2. 只修改与当前步骤相关的内容。
3. 给出完整代码或最小修改片段。
4. 说明运行和验证方法。
5. 不要提前实现后续步骤。

这段补充 Prompt 可以帮助 AI 控制修改范围,避免一次写出大量未经验证的代码。

十二、总结

"先让 AI 出方案,再让它写代码"是一种很适合新手的设计习惯。

  • 方案可以帮助我们先确认 AI 是否理解了需求。
  • 方案可以提前暴露数据结构、文件范围和异常处理问题。
  • 方案可以把大功能拆成多个可以独立验证的小步骤。
  • 方案可以减少一次性大范围修改带来的风险。
  • 方案不需要复杂,优先选择简单、匹配当前项目的最小可行方案。
  • 方案确认后,再按步骤让 AI 编写代码并逐步测试。

可以把今天的内容浓缩成一句话:

先用方案确认"怎么做",再用代码验证"做得对不对"。

当你养成这个习惯后,AI 就不只是一个代码生成器,而会变成参与需求理解、设计讨论、实现和验证的开发助手。

下一篇文章,我们将继续学习:

《用 AI 生成单元测试:从第一个测试用例开始》


✍坚持原创,求关注,点赞,收藏

相关推荐
long3161 小时前
封装(Encapsulation)
java·人工智能·ai·ai编程
Rocky Ding*2 小时前
【三年面试五年模拟】2026-08-18_哔哩哔哩AI应用岗Agent开发一面面经全解析(含完整答案)
论文阅读·人工智能·深度学习·机器学习·aigc·ai-native·ai agent
zandy10112 小时前
AI编程工具技术测评2026:Kimi Code、Cursor等6款常见编程软件选型清单
ai编程
就叫飞六吧2 小时前
两道门:X-Frame-Options 和 SameSite 到底谁管什么
开发语言·chrome·ai编程
VIP_CQCRE3 小时前
用 Ace Data Cloud 快速接入 MiniMax H3:把 AI 视频生成能力变成可调用的生产力
ai·aigc·api·视频生成·acedatacloud
Web3_Basketball3 小时前
动手玩DeepSeek视觉版:多模态OCR实战代码
ai编程
Dawson Zhu3 小时前
Agent自我纠错死循环:从原理剖析到工程化防御体系构建
人工智能·语言模型·架构·aigc
leeyi3 小时前
MultiAgent Host 源码 + ADK prebuilt 三种预制模式(第92篇-E78)
人工智能·aigc·agent
奈斯先生Vector4 小时前
OpenScience 安装失败怎么办?Windows 环境、API 配置与本地服务排错指南
人工智能·windows·架构·开源·aigc·midjourney