1. 为什么我不把 AI 当“代码生成器”,而是当“结对搭档”
我平时写代码,AI 已经深度嵌进了日常工作流。但如果你问我“哪个 AI 写代码最厉害”,我一般不会直接回答,因为这个问题本身就问偏了。真正决定效率的,不是模型排行榜上那零点几个百分点的差距,而是你有没有把 AI 放在正确的场景里,用正确的 Prompt 去驱动它。
举个很常见的例子:有人让 AI “帮我写一个用户登录接口”,结果拿到一堆看起来能跑、实际上跟项目现有鉴权体系完全不兼容的代码,然后得出结论“AI 写代码不行”。但换个方式,把项目用的框架、现有的中间件、数据库表结构、错误码规范都交代清楚,再让它写,出来的东西基本能直接用。差别不在模型,在于你有没有把它当成一个需要上下文的搭档,而不是一个许愿池。
这篇内容我整理了自己平时最常用的 5 个场景,每个场景都配上可以直接复制去用的 Prompt。这些场景覆盖了从写新代码、改老代码、排查 Bug、读懂陌生代码库到写测试的完整链路。适合已经有基本编程能力、想把 AI 真正用起来的开发者,也适合刚入门、还在摸索怎么跟 AI 协作的新手。我不会讲太多“提示工程”的理论,重点放在“我实际怎么问、为什么这么问、问完怎么验证”上。
先说一个底层认知:AI 写代码的质量,约等于你给它的上下文质量乘以你验证它的严格程度。上下文给得越具体,验证做得越扎实,产出就越靠谱。下面这 5 个场景,本质上都是在解决“怎么给上下文”和“怎么验证”这两件事。
2. 场景一:从零写一个新模块,怎么让 AI 一次给对
2.1 为什么直接说“帮我写个 XX”基本会翻车
新手最容易犯的错,就是给一句话需求。比如“写一个限流器”。AI 会给你一个令牌桶或者漏桶的实现,但它不知道你用的是什么语言版本、有没有现成的依赖、限流粒度是接口级还是用户级、超限后是返回 429 还是排队等待。这些信息缺失,它只能靠猜,猜错就是返工。
我的做法是:在让 AI 写代码之前,先花两分钟把“约束条件”列清楚。约束条件包括技术栈、运行环境、输入输出、边界情况、以及项目里已有的约定。这一步看起来麻烦,但它能把返工率降下来一大半。
2.2 我常用的“新模块生成”Prompt 模板
下面这个模板我用了很久,基本可以套用到大多数后端模块的开发上:
你是一名资深后端工程师。请帮我实现一个【模块名称】。 技术栈约束: - 语言/版本:【如 Python 3.11 / Go 1.22 / Java 17】 - 框架:【如 FastAPI / Gin / Spring Boot】 - 依赖限制:【如只能用标准库 + 已有的 redis 客户端,不要引入新依赖】 - 代码风格:【如遵循 PEP8 / 项目使用 Google Java Style】 功能需求: 1. 【需求点一,写清楚输入、输出、行为】 2. 【需求点二】 3. 【需求点三】 边界与异常: - 【如:参数为空时返回什么】 - 【如:依赖服务超时如何处理】 - 【如:并发场景下是否需要加锁】 请先输出实现思路(不超过 10 行),确认无误后再输出完整代码。 代码中关键逻辑请加注释,并在最后列出你做的假设。这个模板里有两个关键设计。第一,要求它先输出思路再输出代码。这一步能让你在它写一大堆代码之前就发现方向错误,省时间。第二,要求它列出假设。AI 在信息不全时一定会自己补全,让它把假设显式写出来,你就能快速判断哪些假设跟你的项目不符。
2.3 拿到代码后我必做的三件事
代码生成出来只是开始,我一般会做三件事。第一是通读一遍,重点看它有没有引入我没要求的依赖,以及异常处理是不是符合项目规范。第二是跑一遍边界用例,尤其是空值、超长输入、并发这些它容易忽略的地方。第三是让它自己 review 一遍,Prompt 是“请以代码审查者的角度,指出这段代码可能存在的 3 个问题,并给出修复建议”。实测下来,它自己找出的问题里,大概有一半是我没注意到的。
注意:不要一次性让 AI 写太大的模块。一个模块超过 200 行,它出错的概率会明显上升。我的经验是单次生成控制在 100 到 150 行以内,超出的部分拆成多次,每次基于上一次的产出继续。
3. 场景二:改老代码和加功能,怎么避免它把逻辑改崩
3.1 改代码比写代码更考验上下文
在真实项目里,写新代码的比例其实不高,大部分时间是在改老代码。改代码的难点在于:AI 看不到完整的调用链,它只看到你贴给它的那一段。如果它不知道这个函数被谁调用、返回值被怎么用,就很容易改出问题。
我踩过的一个坑:让 AI 给一个工具函数加个参数,它直接把函数签名改了,但没管所有调用方,结果编译直接报错。后来我学乖了,改代码之前一定先把调用关系交代清楚。
3.2 “安全改代码”的 Prompt 写法
我需要修改下面这段代码,请严格按我的要求来,不要做额外改动。 【粘贴原代码】 修改需求: - 【具体要改什么,越具体越好】 上下文信息: - 这个函数被以下位置调用:【列出调用方】 - 返回值的使用方式:【说明】 - 项目中的相关约定:【如错误码、日志格式】 要求: 1. 只修改必要的部分,保持其他逻辑不变。 2. 如果我的需求会导致调用方出问题,请先指出来,不要直接改。 3. 输出修改后的完整代码,并用注释标出改动位置。这里最关键的一句是“如果我的需求会导致调用方出问题,请先指出来”。这句话能让 AI 从“执行者”切换成“审查者”,很多时候它会提醒你某个改动会破坏兼容性,这种提醒价值很高。
3.3 用 diff 思维验证改动
改完之后,我不会直接接受,而是让它输出一个改动说明,格式是“改了哪几行、为什么改、影响范围是什么”。然后我拿这个说明跟自己的预期对一遍。如果它改了我没要求的地方,我会追问“你为什么改了第 X 行,这不是我要求的”。多数情况下它会解释,少数情况下它会承认是多余的改动,然后改回去。
这个来回的过程看起来费事,但比改崩了再回滚要快得多。尤其是涉及核心业务逻辑的代码,多问一句永远不亏。
4. 场景三:排查 Bug,怎么让 AI 从“瞎猜”变成“有依据地推理”
4.1 排查 Bug 是 AI 最被低估的用法
很多人觉得 AI 排查 Bug 不靠谱,因为它看不到运行环境。但实际上,只要你把错误信息、相关代码、以及你已经做过的排查步骤给全,它的推理能力相当强。关键在于,你要给它“证据”,而不是只给它“现象”。
我见过太多人这样问:“我的程序报错了,怎么办?”这种问法,AI 只能给你一堆通用建议,比如“检查依赖版本”“看看日志”。但如果你把完整的堆栈信息、出错的那段代码、以及你运行的环境版本都贴上去,它往往能直接定位到问题。
4.2 我的“Bug 排查”Prompt 结构
我在排查一个 Bug,请帮我分析根因。 现象描述: - 【什么操作触发了这个问题】 - 【期望结果 vs 实际结果】 错误信息: 【粘贴完整堆栈或报错日志】 相关代码: 【粘贴出错位置及上下游代码】 环境信息: - 语言/框架版本: - 操作系统: - 相关依赖版本: 我已经排查过的方向: - 【如:确认了数据库连接正常】 - 【如:单独跑这个函数是正常的】 请按以下步骤分析: 1. 根据错误信息,列出最可能的 3 个原因,按可能性排序。 2. 针对每个原因,给出验证方法。 3. 不要直接给修复代码,先确认根因。这个 Prompt 的精髓在最后一句“不要直接给修复代码,先确认根因”。因为 AI 有个坏习惯,看到报错就想直接给修复方案,但很多时候它修的是表象,不是根因。强制它先分析原因,能避免你被带偏。
4.3 一个真实的排查案例
我之前遇到过一个接口偶发超时的问题,日志里只有一句“request timeout”,没有任何有用信息。我把这个现象、接口的完整代码、以及数据库查询语句都贴给 AI,它分析后指出:代码里有一个循环里嵌套了数据库查询,在数据量大的时候会触发 N+1 查询问题,导致响应时间随数据量线性增长。
这个判断是对的。我后来把循环内的查询改成了批量查询,问题就解决了。如果我只贴一句“接口超时”,它绝对给不出这个答案。所以排查 Bug 的核心,还是把上下文给足。
4.4 常见排查方向速查表
| 现象 | 优先排查方向 | 让 AI 帮你做什么 |
|---|---|---|
| 偶发超时 | 慢查询、锁竞争、外部依赖 | 分析代码中的循环查询和同步阻塞 |
| 空指针异常 | 参数校验、返回值判空 | 检查所有可能为空的调用链 |
| 内存持续增长 | 缓存未清理、监听器未注销 | 找出未释放的引用 |
| 并发数据错乱 | 共享变量、事务边界 | 检查加锁范围和事务隔离级别 |
| 编译通过但运行报错 | 依赖版本冲突、配置缺失 | 对比依赖树和配置文件 |
提示:排查 Bug 时,把“我已经排查过什么”写清楚特别重要。这能避免 AI 重复给你已经试过的建议,也能让它在你排除的方向之外找原因。
5. 场景四:读懂陌生代码库,怎么快速建立全局认知
5.1 接手老项目时的困境
换项目或者接手别人代码的时候,最痛苦的不是代码难,而是你不知道从哪看起。一个几万行的项目,文件几百个,调用关系错综复杂。传统做法是顺着入口一点点跟,效率很低。我的做法是让 AI 帮我做“代码地图”。
5.2 用 AI 做代码结构梳理的 Prompt
下面是一个项目的目录结构和部分核心文件,请帮我梳理这个项目的架构。 目录结构: 【粘贴 tree 命令的输出,或者手写的目录树】 核心文件内容: 【粘贴入口文件、配置文件、以及你认为最核心的 2-3 个文件】 请输出: 1. 这个项目大致是做什么的,用一句话概括。 2. 主要的模块划分,以及模块之间的依赖关系。 3. 一个请求从入口到返回,大致经过哪些环节。 4. 如果我要新增一个功能,最可能改动的文件是哪几个。这个 Prompt 里,目录结构比代码内容还重要。因为目录结构能反映项目的组织方式,AI 通过目录名就能推断出很多信息。我一般会先用tree -L 3或者类似的命令把三层目录导出来,再挑几个关键文件贴进去。
5.3 从“看懂”到“能改”的过渡
光看懂结构还不够,真正要能改代码,还得知道数据怎么流动。我通常会让 AI 针对某个具体功能,画出调用链路。比如“用户下单这个功能,从接口进来之后,数据经过了哪些处理,最后写到了哪些表”。这种问题它能回答得比较准,因为它只需要顺着代码跟。
这里有个技巧:不要一次问整个项目,而是挑一条最核心的业务链路,让 AI 把这条链路讲透。一条链路搞明白了,其他链路基本是类似的模式,上手就快了。
6. 场景五:写测试和补文档,把 AI 用在“没人愿意干”的活上
6.1 测试和文档是 AI 性价比最高的场景
写测试和补文档这两件事,技术含量不算高,但特别耗时间,而且很多人不愿意干。这恰恰是 AI 最擅长的:它有耐心,不会烦,而且能覆盖到你容易漏掉的边界情况。
我现在的习惯是,每写完一个函数,就让 AI 生成对应的单元测试。它生成的测试用例,覆盖的边界情况往往比我自己想的还全。尤其是那些“参数为 None”“列表为空”“数值为负数”之类的边界,人写的时候容易忘,AI 不会。
6.2 生成测试的 Prompt 模板
请为下面的函数生成单元测试。 【粘贴函数代码】 测试框架:【如 pytest / JUnit / Go testing】 要求: 1. 覆盖正常路径、边界情况、异常情况。 2. 每个测试用例要有清晰的命名,说明测的是什么。 3. 对于依赖外部服务的部分,使用 mock。 4. 如果发现函数本身有难以测试的设计,请指出来。 请输出完整可运行的测试代码。最后那句“如果发现函数本身有难以测试的设计,请指出来”很有用。有时候 AI 会告诉你,这个函数因为耦合太紧所以不好测,这其实是在提醒你重构。测试写不下去,往往说明设计有问题。
6.3 补文档的实用做法
文档这块,我一般不让 AI 从零写,而是让它基于代码生成初稿,我再改。Prompt 是“请为下面的模块生成 API 文档,包括每个函数的用途、参数说明、返回值、以及使用示例”。生成的初稿可能不够准确,但框架和格式是现成的,我只需要填内容、改错误,比从空白页开始快很多。
注意:AI 生成的测试和文档一定要人工过一遍。测试要确认断言是对的,文档要确认参数说明跟实际代码一致。它偶尔会“想当然”地写一些不存在的参数,这种错误必须靠人工兜住。
7. 让 AI 真正好用的几个底层习惯
7.1 上下文要给“够”,不是给“多”
很多人以为上下文给得越多越好,其实不是。给太多无关代码,反而会稀释重点,让 AI 抓不住关键。我的原则是:只给跟当前任务直接相关的代码,加上必要的调用关系说明。一个函数能说清楚的事,不要贴整个文件。
7.2 把 AI 的输出当成“初稿”而不是“终稿”
这是心态问题。AI 给的东西,永远要经过你的判断。它能帮你省掉 70% 的体力活,但剩下 30% 的判断和验证,必须你自己来。把它当实习生,而不是当专家,你的预期就对了,用起来也顺了。
7.3 建立自己的 Prompt 库
我把自己常用的 Prompt 都存成了一个文档,按场景分类。下次遇到类似任务,直接复制改改就能用。这个习惯坚持下来,效率提升很明显。因为好的 Prompt 是打磨出来的,每次踩坑后微调一点,慢慢就形成了一套适合自己的模板。
7.4 几个容易忽略的细节
第一,明确告诉 AI 你的语言版本。不同版本的语法差异很大,不说清楚它可能给你过时的写法。第二,涉及安全相关的代码,比如鉴权、加密、SQL 拼接,生成后一定要重点审查,这部分不能偷懒。第三,如果 AI 连续两次给出的方案都不对,别再追问了,换个思路重新描述问题,往往比在错误方向上纠缠更快。
我在实际使用中最大的体会是:AI 写代码的上限,取决于你对问题的描述能力。你越能把问题拆清楚、把约束讲明白,它给出的东西就越接近可用。反过来,如果你自己都没想清楚要什么,它也只能给你一堆似是而非的代码。所以与其纠结用哪个模型,不如先把“怎么问”这件事练好。这套方法我用了大半年,从写新功能到排查线上问题,基本都覆盖到了,你可以直接拿去试,根据自己的项目情况微调就行。