说实话,我见过太多人打开 AI 编程助手,第一句话就是“帮我写一个订单查询接口”。AI 秒回一段看起来像模像样的代码,贴进项目,编译通过,接口也能返回数据。然后呢?没鉴权、缓存该失效时不失效、数据库连接串是假的、异常被吞得干干净净。于是很多人得出结论:AI 写代码根本不靠谱。但我自己这段时间的实测结论恰好相反——问题不在 AI,而在你跳过了整个流程里最关键的一步:先让它写方案,再让它写代码。
这篇文章说的就是“AI 先写方案,再写代码”这套工作流。我会用最近改造一个后端订单查询模块的真实过程当例子,把方案阶段、编码阶段分别该怎么提问、一份合格方案该包含哪些内容、以及哪些项目根本不用走这套流程,全部拆开讲。不管你用的是 ChatGPT、Claude、Codex,还是国内任何大模型,这套思路都通用。如果你已经被“一句话生成代码”坑过,这篇文章大概率能帮你下次开工少走一大截弯路。
1. 一句话直出代码带来的返工信号:一次订单接口实验复盘
1.1 同一句话提问,AI 交出的标准答案
我先做了一个对照实验:让模型直接写“订单查询接口”,上下文里什么都不给。几个主流模型给出来的代码高度相似,基本长这样:
def get_order(order_id: int): order = db.session.query(Order).filter(Order.id == order_id).first() return order看着挺正常对吧?但拿这个去上生产,问题一串:
- 没有写清 Order 的表结构,字段完全是默认假设,跟真实模型大概率对不上
- 没有鉴权,任何拿到接口地址的人都能查任意订单
- 没有缓存,跟“高并发场景”的需求完全不搭边
- 没有超时、限流、幂等控制,后端接口最容易踩的坑一个没躲开
- 异常处理随意,查不到订单时不知道抛什么错误,调用方也没法精确处理
这不是某一个模型的个例,而是“信息严重不足时所有模型都会有的平均发挥”。更麻烦的是,这种代码不仅功能缺位,连命名风格都和你项目里其他人的代码对不上,接手的人一眼就能看出这是 AI 生成的。你贴完代码,回头还得花时间解释“这段不是我写的,是 AI 写的” —— 这在团队 review 里就是妥妥的返工信号。
1.2 真正的问题不在编码,在信息完整性
大模型的工作原理决定了它在你信息给得越少时,越倾向于填充“统计上最普遍”的细节,而不是“你的系统里最正确”的细节。这跟你让一个新同事不看设计文档直接写代码是一个道理——他只能按行业通用套路来,写出来的东西四平八稳,但跟你项目的实际约束处处打架。
所以我把这个失败归结为:故障不出在编码环节,而出在输入信息的完整性环节。想通这一点后,后面所有流程都变了。这就引出了本文最核心的动作——把“编码请求”拆成“方案请求”和“按方案编码请求”两步。本质上是把人类开发者的工作方式迁移给 AI:先需求分析,再技术选型,再接口设计,最后才是写代码。跳过了前几步,AI 就只能用“平均水准”回馈你。
2. 方案阶段的信息四件套:让大模型不再替你拍脑袋
2.1 一个方案请求里必须塞进去的四类信息
给 AI 提方案需求,不是简单说一句“给我写个方案”就完事。我实测下来,下面四类信息缺一不可,按重要程度排序:
- 业务目标:这个功能解决什么问题、调用方是谁、调用量大概多大
- 硬性约束:必须用的语言/框架/中间件、性能指标、明确不能引入的东西
- 已知边界:哪些事明确不做,比如不做分布式事务、不做跨机房强一致
- 交付格式:要的是技术方案文档,不是代码
第一类信息决定方向,第二三类给模型装上“边界盒”,第四类决定输出形态。很多人只给第一类,所以 AI 只能发挥到“看起来合理”的程度。我自己早期踩过最深的坑就是漏掉“已知边界”——AI 把订单模块能想到的功能全给你设计上了,什么批量查询、消息推送、异步对账,方案洋洋洒洒三大页,评审时全得砍掉,白费时间。
2.2 我当时实际发出去的一段方案 Prompt
我在订单查询模块上,直接用了下面这段提示词:
背景:我们有一个订单服务,需要提供一个订单查询接口,调用方是内部管理后台和 APP 端。数据库是 MySQL 8.0,缓存是单机 Redis,服务用 Python FastAPI 部署在 K8s,峰值查询约每秒 800 次,其中大部分集中在一批热订单上。 约束:接口必须做鉴权和限流;查询结果允许最多 5 秒的缓存延迟;不允许引入新的中间件;持久层用 SQLAlchemy。 已知边界:不需要做订单列表的分页查询;不做订单状态变更;不做消息通知。 请输出一份可评审的技术方案,包含接口定义、缓存设计、异常处理策略、风险与回退方案。不要写代码,只要方案。
这段 Prompt 里最容易被忽略的是最后那句“不要写代码”。为什么必须加?因为方案阶段我要的是 AI 的分析能力,一旦允许它写代码,它会立刻钻进实现细节,把架构层面的选择抛到脑后。这就像开需求评审会,没人会在会上突然低头开始写业务代码。
AI 返回的方案里确实给了接口定义、缓存 key 设计、失效策略、兜底逻辑,还主动指出了热点 key 和缓存击穿两个风险。这些东西如果直接问“怎么写代码”,几乎不可能出现在同一个会话里。方案模式下,AI 会先整体盘一遍问题空间,把所有影响因素摊开给你看,这个信息密度是直接生成代码完全比不了的。
3. 把 AI 的方案压成施工图:我砍掉的无效设计和补上的关键约束
3.1 方案评审时砍掉的几样东西
AI 出的方案有个通病:大而全,什么都想覆盖。我拿到第一版方案后做了不少删减:
- 缓存策略采用“缓存删除”而不是“更新缓存”。更新缓存要先查一次库,等于把读路径的代价转移到了写路径;删除只产生一次失效,读路径回源再建。这是缓存工程里很经典的结论,AI 方案里两种都写了,你得会判断到底选哪种
- 砍掉了“订单缓存预加载”这种优化项。峰值 800 QPS 的量级根本不需要预热,加了只会增大运维复杂度
- 把缓存 TTL 从 AI 建议的 5 分钟改成 60 秒。调用方允许最多 5 秒延迟,60 秒 TTL 已经足够保守,再长会导致刚更新的订单长时间显示旧状态
- 补上了一个 AI 没有强调的约束:Redis 客户端超时必须设得很短(80ms),缓存不可用就直接查库,绝不因为 Redis 抖动拖垮整个接口
后端场景里,鉴权、超时、限流、日志、幂等这些点,AI 方案里通常会涉及但不一定完整,评审时我习惯逐条对照。特别是超时和降级,AI 默认不会主动设计,你要么在约束里写明,要么在评审清单里强制补上,否则生产环境一抖动就垮。
3.2 每个关键选择都要它给理由
我还有一个强制习惯:方案里凡是关键选择,必须让 AI 写清楚“为什么选这个而不是那个”。比如它选了 Redis 而不是进程内缓存,就追问一句:如果订单服务扩容到 3 个 Pod,进程内缓存的一致性问题怎么处理?让 AI 解释清楚之后,方案的可靠性会高很多。
这一步同时也是在反幻觉。AI 编造不存在的命令、推荐过时库的情况,我至少遇到过五六次。审查方案时的原则很简单:它给的每一项技术结论,都值得你花 30 秒去官方文档核对一遍。真出问题通常不是 AI 设计得不够多,而是评审环节跳得太快。
方案定稿后,我会把它存成一份简短的 Markdown 文档放进项目目录,命名就叫docs/design-order-query.md。后续编码过程中如果发现某个方案细节与实际有出入,先改文档再改代码,保持方案和实现同步。这一步很多人嫌麻烦跳过,但等到需要 review 或交接时,这份文档的价值会成倍放大——别人看你的代码不用猜,直接看方案就知道你当时为什么这么设计。
4. 编码阶段的反向操作:把方案贴回去,把任务拆到不能再小
4.1 按图施工而不是重新即兴创作
方案定稿后,编码阶段的玩法完全变了。我不再跟 AI 说“写一个订单接口”,而是把方案里相关章节的内容直接贴回去,然后一次只让它写一个小单元:
以下是已评审通过的方案摘录: 缓存设计:Redis key 为 order:{order_id},TTL 60 秒,更新订单时主动删除缓存;Redis 客户端超时 80ms,超时直接查库,禁止等待。 请只实现订单查询的 service 层函数 get_order_with_cache(order_id),要求:1. 入参校验;2. 超时降级;3. 注释保持简洁;4. 不要实现路由和鉴权,这部分我会单独处理。
这个写法的好处是:方案已经替 AI 做完了架构决策,代码生成只需要解决实现层面的问题;每个小单元都能单独编译、单独测试;某个单元写坏了,回滚范围也就一个函数,不会牵连一整片。
编码过程中,我每拿到一段代码会先对照方案里的对应条目逐项核对,比如“参数校验写了没”“超时值是不是 80ms”“是不是主动删缓存而不是更新缓存”。核对通过后才粘贴进项目。这一步叫“验收闭环”,别把 AI 的代码当成品,当它是个很聪明的候选实现,你才是最终把关人。
4.2 上下文比模型本身更决定上限
经常有人问我“哪个 AI 写代码厉害”,我的回答一直是:可能都有差距,但顶层天花板主要取决于上下文。你给方案、给约束、给边界,拿入门模型也能写出能用的代码;你什么都不给,拿最强的模型也只能写出一段“看起来通用”的代码。
AI 编程插件方面,不管是 VS Code 里的 Copilot、Claude Code,还是 Cursor、Codex,核心都是对话加文件上下文。实测下来,只要把方案摘录贴进对话,各家完成度差距很小。有些人纠结 IDE 选型,其实选哪个顺手就行,真正的差异在你能不能组织出一份高质量方案。
编码时我会顺手要求 AI 给最小测试用例,比如 3 个边界条件。这步不是形式主义,是用来验证它是否真的理解了方案的约束。如果连边界用例都对不上方案,说明它对约束的理解还停留在表面,这时候需要重新贴一段更具体的方案摘录,而不是硬改代码。
5. 可以直接抄走的方案优先提示词与组合用法
5.1 三个常用的 Prompt
我把这套流程最终沉淀成三个模板,直接复制就能用。
【方案生成】 背景:{项目背景、调用方、数据规模、部署环境} 硬性约束:{语言/框架/中间件/性能指标/不可引入的技术} 已知边界:{明确不做什么} 请输出一份可评审的技术方案,包含核心结构、接口定义、关键机制、风险与回退方案。不要写代码。 【方案评审】 这是 AI 生成的方案: {方案全文} 请以技术负责人的视角评审,指出:1. 哪些设计超出当前需求;2. 哪些约束被忽略;3. 哪些假设需要人工验证;4. 每个关键选择是否给出了足够理由。 【按方案编码】 以下是已评审通过的方案: {方案中相关章节的摘录} 请只实现 {模块/函数},要求:1. 严格遵循方案中的 {机制名称};2. 不编写本模块之外的任何代码;3. 给出 3 个边界条件的最小测试用例。别觉得模板越长越好。真实项目里我经常只写两三行,核心是那三要素:方案上下文加范围收窄,再加一句“这一步不做什么”。范围收窄是给 AI 划清边界,防止它顺手把路由、鉴权、日志、部署配置全给你写一遍,最后你光删代码就花半天。
5.2 四个阶段的高频信息流
把这套流程摊开,其实就是一张四阶段对照表:
| 阶段 | 给 AI 的信息 | 让 AI 输出 |
|---|---|---|
| 方案生成 | 背景、硬性约束、已知边界 | 技术方案,不是代码 |
| 方案评审 | 方案全文 + 负责人视角 | 风险清单、过度设计嫌疑、待验证假设 |
| 按方案编码 | 方案摘录 + 模块边界 | 单个模块代码 + 最小测试用例 |
| 结果验收 | 代码 + 编译/测试结果 | 问题清单、改进项 |
想省时间的话,第一步和第二步可以合并:方案生成时直接要求“请同时用负责人口吻评审自己的方案”。实测下来效果也不差,但如果是重要模块,我仍然建议人工分开审一遍。毕竟 AI 自评往往有一种“自己写的自己看着顺眼”的倾向,挑出来的毛病没有真人挑得狠。
6. 这套流程的真边界:什么代码值得先方案、什么不值得
6.1 不需要写方案的场景
方案先行很好,但也不是所有代码都值得。我自己会快速判断一下:
- 一次性脚本、几十行的数据迁移小工具,直接让 AI 生成,跑完即弃,写方案纯属浪费
- 探索性原型,需求每天都在变,方案写出来第二天就作废
- 已有成熟规范、模式固定的低风险小改动,比如照着已有接口再补一个类似的查询接口,直接生成更快
这些场景里,方案先行的收益会被流程成本吃掉,没必要为了仪式感多浪费时间。说白了一行find . -name "*.log" -mtime +7 -delete这种命令,直接让 AI 给就完事,谁写方案谁矫情。
6.2 真正值得投入方案的地方
反过来,下面这几类是我强烈建议走完整流程的:
- 后端接口和高并发路径,尤其是鉴权、限流、缓存、降级交织在一起的时候
- 你不熟悉的技术栈,让 AI 先做保守选型,风险可控
- 老系统改造,历史约束多,方案阶段能提前暴露兼容性问题
- 需要多人 review 或者要长期维护的模块,方案就是最好的文档
我有一个比较实用的判断标准:如果这段代码后期需要人 review 两次以上,或者上线后出问题要半夜起来排查,那就值得先方案。说白了,方案先行的收益不是生成速度快,而是返工率低。我自己的体感是,多花在方案上的 20 分钟,通常能省下后面 2 小时的排错时间。特别是那种“缓存穿透把数据库打挂了”的夜班故障,提前在方案里把热点 key 和兜底策略写清楚,比事后调一个通宵划算得多。
还有一句掏心窝的话:方案阶段 AI 也会一本正经地胡说。它给的东西必须有人工抽查,技术选型、关键命令、版本号都值得核对。别让 AI 替你拍脑袋,让它先替你把方案想清楚——这套流程用顺了,你会发现“让 AI 写代码”这件事,真正的分水岭恰恰发生在写代码之前。