本文是专栏《AI 编程实战》第 3 篇。回到目录与导读。上一篇:AI 怎么"看懂"你的整个代码库。
用 AI 写代码,最常见的翻车不是"模型太笨",而是——你以为你说清楚了,其实没有。
《大模型专栏》第 4 篇讲过提示词的通用心法。这一篇专门讲写代码这个场景,因为它有个特殊性:
代码是要能跑的、有对错的。所以给 AI 写的提示词,本质不是"聊天",而是一份小型的"规格说明书"。
一个对比,胜过千言
同一个需求,两种问法,结果天差地别。
❌ 含糊:"写个函数校验邮箱。"
→ 它给你一个正则,但:要不要支持中文域名?空字符串
怎么办?返回布尔还是抛异常?大小写敏感吗?
——全靠它猜,猜的多半不是你要的。
✅ 规格:"写个校验邮箱的函数。要求:
- 语言 TypeScript,纯函数无副作用;
- 入参 string,返回 boolean;
- 空字符串/null 返回 false,不抛异常;
- 允许 + 号和子域名,不必支持中文域名;
- 附 3 个单元测试:正常、空值、非法格式。"
→ 它给你的,基本就是能直接用的。"
模型没变,变的是你把"验收标准"提前说清楚了。写提示词写得好的人,脑子里想的其实是:"如果我把这活派给一个没接触过项目的外包,我得交代哪些才能让他不返工?"
一份好"代码需求"该包含什么
不用死记,但下面这几样,交代得越全,返工越少:
| 要素 | 大白话 | 例子 |
|---|---|---|
| 目标 | 到底要它干成什么 | "加一个导出 CSV 的按钮" |
| 技术约束 | 用什么、不用什么 | "用现有的 axios,别引新库" |
| 输入输出 | 吃什么、吐什么 | "入参订单数组,返回 Blob" |
| 边界情况 | 异常、空值、极端量 | "订单为空时导出只有表头的文件" |
| 参照物 | 照哪儿的现有写法 | "风格参考 exportPDF 那个函数" |
| 验收方式 | 怎么算做对了 | "附单测,覆盖空值和正常两种" |
其中**"参照物"和"验收方式"最容易被忽略,却最提效**:给个现有例子,它立刻懂你项目的风格;让它附上测试,它会用更严谨的方式对待这段代码(也顺手帮你验了第 5 篇要讲的质量)。
大任务:先要"计划",别要"代码"
需求一大(比如"做一个完整的评论功能"),别一上来就让它闷头写。更稳的做法是分两步:
- 先让它出方案:"先别写代码。告诉我你打算改哪些文件、加哪些接口、数据结构怎么设计,等我确认。"
- 你审一遍方案,纠偏,再让它动手写。
你:做评论功能,先给我实现方案,别写代码。
它:(列出:新建 comment 表、加 3 个接口、
前端加评论组件、涉及 5 个文件……)
你:数据表加个"父评论ID"支持盖楼;接口合并成 2 个。开工。
它:(按敲定的方案实现)
好处很实在:在它写歪之前就纠正,比写完一大堆再返工,成本低得多。 这也是业界所谓 "规格驱动开发(spec-driven development)" 的朴素版——先对齐"要做成什么样",再让 AI 填实现。计划这一步,本质是《AI Agent 专栏》里"先规划、后执行"思想在写代码上的应用。
几个立竿见影的习惯
- 给例子胜过讲道理:想要某种风格/格式,贴一段现有代码说"照这个来",比描述半天管用。
- 一次一个明确任务:别把"加功能 + 重构 + 修 bug + 写文档"塞进一句话。拆开,逐个来,它更专注、你更好审。
- 明确说"不要什么":"别改动
utils.ts""别引入新依赖""别写注释"——约束和目标一样重要。 - 不满意就迭代,别重开:像跟同事对稿一样,"这里空值没处理""命名跟项目不一致,改成驼峰"——把具体问题反馈回去,比推倒重来快。
一个反直觉的收益
你可能会想:把需求写这么清楚,不是很费劲吗?还不如自己写。
但这里有个隐藏的好处:
为了把需求给 AI 讲清楚,你被迫先把它自己想清楚。 而"想清楚要做什么",本来就是写代码里最难、最值钱的部分——AI 只是把这件事从"隐性"逼成了"显性"。
很多人用 AI 编程后发现,自己反而更少写出"想到哪写到哪"的糊涂代码了。这不是 AI 的功劳,是**"必须先说清楚"这个动作**的功劳。
小结
- 给 AI 写代码提示词,本质是写一份小型规格——因为代码有对错,含糊的需求必然换来跑偏的实现。
- 一份好需求尽量包含:目标、技术约束、输入输出、边界情况、参照物、验收方式;其中"给例子"和"要测试"最提效。
- 大任务先要"计划"再要"代码",在写歪前纠偏(规格驱动开发的朴素版)。
- 习惯:给例子、一次一任务、明说"不要什么"、有问题就迭代。
- 隐藏收益:逼自己先想清楚——这本就是编程里最值钱的部分。
需求讲清楚了,就可以放手让最强的第三代工具自己去写、自己去跑、自己去修了。下一篇拆解这个"智能体式编程"的循环到底怎么转。