最近半年,我把项目里大量“先写再说”的代码活儿,都交给了编辑器里的AI编程搭档。这种玩法大家起了个名字,叫 vibe coding。我理解下来,它不是说彻底躺平、AI写什么就信什么,而是把你从逐行敲字的体力活里解放出来,把注意力放到审查、验证和决策上。标题里写的是 Copilot + VS Code,其实这套玩法换个编辑器、换个助手也成立,关键在于你有没有把工具配置到适合“连续心流”的状态。
这篇文章就是我折腾了半年之后重新整理过的实操笔记。适合谁看?主要是我这种不想把时间花在样板代码和重复逻辑上的开发者;如果你刚接触AI编程助手,看完也能知道第一步该干什么、什么东西最不该碰。
1. 先看清楚 vibe coding 的边界:不是说什么都能外包给AI
1.1 我理解的 vibe coding:保持心流,而不是甩手掌柜
vibe coding 这个词的字面意思是“凭感觉编程”,但很多人理解偏了。它不是让你漫无目的地让AI写写看,而是通过“让AI先给初稿、你保持review节奏”的方式,把大脑的认知负荷从“生成代码”转移到“评估代码”。
举个我每天都在发生的例子:以前写一个批量接口,要从头想参数结构、循环逻辑、错误处理,写到后面手指累、脑子也累。现在我把目标描述清楚,AI十分钟生成一版初稿,我只需要干三件事:看数据流是否合理、看边界条件有没有漏、看命名是否有歧义。整个过程中我始终坐在同一个上下文里,不用等大脑“重新加载”,这就是所谓的心流状态。
很多人会担心这样是不是在偷懒。我的体验恰好相反:AI把代码写出来之后,我要付出的审查精力比凭空写更多。因为你不仅要看这段代码对不对,还要看出AI自己察觉不到的设计缺陷。这个“review别人写的烂代码”的过程,恰恰是让技术判断力成长最快的部分。
1.2 我的一条判断法则:十分钟定位法则
我后来给自己定了一条很简单的判断标准:如果一个功能出了问题,你能不能在十分钟内通过日志、断点或读代码定位到它?如果能,那它就适合 vibe;如果不能,就别让AI碰核心逻辑。
这条法则帮我避过很多次雷。最典型的一次,我让AI帮忙写了一段并发限流逻辑,当时只在本地跑了一轮发现没问题,就直接合进分支了。结果一上测试环境,所有请求在边界情况下被限流器全部拦死,我在日志里翻了整整半天才定位到一个时间窗口的竞态问题。原因很清晰:并发场景的失败模式太隐蔽,AI在生成代码时不会主动考虑“多线程同时到达”这种场景,因为它的训练目标只是“看起来正确”。
从那以后我就把并发控制、跨服务事务、支付回调、加密协议实现这类东西划进了黑名单。不是说这些代码AI不能写,而是出了问题之后,我要付出的排查成本远超它替我节省的成本。定位成本一旦大于生成成本,这笔交易就不划算。
1.3 适合与不适合的清单
我用一张表格总结自己这半年划出来的边界,你可以直接抄作业:
| 类别 | 适合交给AI | 不适合交给AI |
|---|---|---|
| 脚手架 | 目录结构、接口骨架、模板文件 | 模块边界设计、权限模型规划 |
| 数据层 | 单表CRUD、简单查询、批量导入导出 | 跨表事务、复杂级联删除、数据迁移的幂等保证 |
| 业务逻辑 | 状态机初稿、规则引擎的简单分支 | 金融计算、审批流、多租户隔离 |
| 工程类 | 依赖升级后的接口适配、重构重命名 | 编译期元编程、复杂代码生成器维护 |
| 测试 | 单测用例初稿、Mock数据构造 | 测试覆盖率策略、性能压测基准 |
表格右侧的项目,不是AI不能生成,而是它们都带一个共同特点:错误发生在“系统层面”而不是“函数层面”。函数写错了,顶多一张堆栈;系统写错了,整个服务雪崩、数据对不上,那个代价谁也赌不起。
2. 把编辑器和AI助手调到同频:配置清单与取舍
2.1 不是越贵越好:模型选型看任务复杂度
AI编程助手背后可选的模型能力差异确实存在,但大多数时候我们写的是“普通业务代码”,中档模型完全够用;越大的模型,单次生成质量更高,但延迟和成本也更高。我现在的习惯是:小改动、样板代码用轻量模型,延迟在200毫秒左右,基本无感;遇到跨文件重构、迁移旧代码这类复杂任务,再切成更强的模型。
这里有个容易被忽略的参数叫“上下文窗口”。代码仓库越大,AI越不可能一次看完所有文件。所以真实的瓶颈不是模型聪明不聪明,而是你能不能把最相关的信息塞进那几万token的窗口里。我一般会在对话里用“文件引用”功能把接口定义、数据结构、报错日志这三样东西精确投喂进去,而不是让它去整个仓库里乱翻。投喂信息准确,AI的行为稳定度立刻上一个台阶。
2.2 几个我建议改掉的默认设置
默认配置往往只保证了“能用”,不等于“好用”。我踩了一圈之后,建议你按下面的思路调整自己的编辑器设置。
第一,把“自动补全弹窗”的触发延迟调高到300毫秒左右。默认值太灵敏时,光标每停一下都弹代码建议,非常打断思路。调高延迟之后,只有当我确实停顿下来、准备接受建议的时候,它才出现,那个节奏感完全不一样。
第二,强制开启“预览Diff”。AI修改代码之后,一定要在Diff视图里逐段确认,确认保存之前绝对不让它直接写进文件。这条规则是我用血的教训换来的——现在所有AI助手改完的代码,都会先在Diff视图里过一道我的眼睛。
第三,把快捷键绑定成肌肉记忆:接受建议用 Tab,拒绝建议用 Esc,呼出对话用 Ctrl+I,提交对话用 Ctrl+Enter。这几个键位改完之后会有一周左右的适应期,但适应期一过,手基本不用离开键盘,心流断点少一大半。
第四,如果助手提供“温度”或“创造力”参数,把它调低一点。写代码需要的是确定性和可预测性,温度越高,AI越爱生成花里胡哨但不一定正确的写法。我自己的经验是,创造力的高低不应该靠调高温度去赌,而是靠多轮对话去引导。
2.3 上下文控制:决定AI在盖楼还是在盖危房
一个被说烂但值得反复强调的问题:AI不知道你在想什么,它只知道你贴给它的东西。把当前文件、相关接口、运行错误日志、目标行为的描述全贴齐,比它自己猜强十倍。
我一般会在编辑器里把“上下文引用”的范围设置成“当前打开的文件 + 最近编辑过的文件”,而不是“整个工作区”。这么做有两个好处:一是省token、省钱、省延迟;二是减少噪音。AI如果同时看到二十个不相关的文件,它很容易被无关代码带偏,生成一堆看似合理但跟当前需求毫无关系的逻辑。
如果你用的是支持“项目规则”的助手,建议建一份规则文件,把命名规范、错误处理偏好、接口风格统一写在里面。每次开会话它会自动加载这些约束,等于给AI戴上了一副适合本项目世界的眼镜,生成结果会稳定到你惊讶。
2.4 隐私边界和合规红线
代码如果来自未公开的内部项目,不要直接塞给公网上的AI助手。这句提醒看起来有点老生常谈,但实际操作中太容易被忽视了——很多人为了图方便,直接把内部包名、数据库结构、鉴权逻辑原封不动贴进对话里。
最稳妥的做法是:企业内部如果有代理网关或本地部署的助手,优先走那套链路;如果只有外部服务,就把类名、字段名、业务关键词做脱敏处理。脱敏不是改个变量名就行,而是要把真正敏感的逻辑抽象成“类型A”“接口B”这种无意义代号。记住,安全意识没有任何工具能替你兜底。AI理解你需求的能力越强,它在对话里接收到的敏感信息就越多,这个风险我们必须自己控制住。
3. 一套稳定复现的 vibe 工作流:从“一个想法”到“一段提交”
3.1 用“人话注释”代替原型图
每次动手前,我会约定先用自然语言写一段注释,再让AI把注释翻译成代码。比如这样一段:
// 读取config目录下所有json文件 // 逐个校验是否包含requiredKeys里的字段 // 缺失的字段写入missing.log,最后返回汇总表这段注释同时是给AI的需求描述,也是给未来看代码的人类留下的路标。我观察到一个规律:注释越像“验收标准”,AI生成的代码就越贴边。如果你只写“读取配置并校验”,AI会默认你不需要日志、不需要汇总,只出一个最简单的循环。而一旦你把行为写得具体,它就会主动补齐错误处理、日志、返回值结构这些细节。
这个习惯起始于一次让我哭笑不得的体验——我让AI“读取所有用户并导出成Excel”,它真的只做了一件事:把用户列表循环了一遍,然后空手返回。后来我才意识到,它理解的是字面意思,不是我的业务意图。从那以后我给自己立了一条规矩:不把“验收标准”写清楚,就不允许AI动手。
3.2 让AI先提问题,而不是让它猜
很多人跟AI对话的模式是“命令式”:写一个登录模块、写一个限流中间件、写一个导出功能。这种对话方式效率极低,因为AI拿到的需求太模糊,只能生成一堆“看起来能用”的样板。
我试过更有效的对话方式:让AI先提问。比如我会说:
我准备做一个JWT鉴权登录,目前有两个方案:A是服务端Session,B是JWT。结合我现在的路由结构,你会选哪种?在动手之前,你还需要知道哪些信息?
AI被迫把自己的不确定项列出来,我再逐条回答。这轮问答看着像多花了两分钟,实际上省掉了后续可能产生的所有返工。因为AI一旦在回答里暴露了它对业务理解的偏差,你可以在它写第一行代码之前就把方向掰正。
还有一个额外的好处:这种“先讨论后编码”的方式,能让我在跟AI对话时保持清楚的头脑,不会因为生成结果看起来很完整就稀里糊涂接受。
3.3 人审关键分叉点,AI填重复逻辑
AI生成骨架之后,我不会逐行review,而是重点看几个“分叉点”:数据是否真的做了校验、错误分支是否处理、外部依赖版本是否兼容、状态转移是否有遗漏。这四个点一旦确认没问题,剩下的遍历、格式化、字段映射这类重复逻辑,我会放心让它放手去写,只在最终Diff视图里抽查一遍。
为什么要这样分而治之?因为人的注意力是稀缺资源。你如果逼自己每个if、每个循环都读一遍,看十分钟就会走神,结果真正有隐患的地方反而漏了。倒不如把有限的注意力集中分配给少数几个高风险分叉点,重复部分交给自动化和终端抽查。这就好比开车,老司机不会每秒钟都盯着仪表盘,但一定会在转弯、并线、刹车这些关键动作上保持警觉。
3.4 一个“验收检查清单”,治好了我的AI依赖症
我每次vibe coding会话结束前,都强迫自己在提交前跑完四条命令:
- 类型检查或编译能不能通过;
- Lint有没有新增错误;
- 已有的测试能不能全过;
- 关键路径手动走一遍,点几下界面、查一下结果。
四条里只要有一条是红的,都不准提交。这是我对“AI生成代码”的最低信任门槛。AI写出来的代码可能很漂亮,但合不上验证的代码,再漂亮也只是装饰品。这套检查清单还有一个隐藏好处:它逼着我每完成一小段任务就做一次状态确认,而不是一口气让AI写两小时然后面对一坨无法收拾的烂摊子。小步快跑永远是编程世界里最可靠的节奏。
4. 最容易翻车的四类AI编程现场,以及我的急救方案
4.1 AI编造不存在的API
现象很典型:AI生成了一段调用第三方库的代码,看着像模像样,结果一运行就报undefined is not a function。去查文档才发现,这个库的某个旧版本里根本没有这个方法,AI把记忆里某个模糊印象缝合成了“最可能的API”。
根因是:模型对开源库的记忆是概率性的,不是在检索数据库。它不知道某个方法在当前版本里存不存在,只能凭训练数据推断“这里大概应该有个方法叫这个名字”。
急救方案分两步。第一步,让AI自己求证:“请去查一下这个库的官方文档,把某个方法在当前版本下的函数签名复制回来。”大多数助手下一次回复会老实很多。但如果它还在嘴硬,就做第二步——直接在编辑器里按定义跳转,把真实的函数签名拿出来,贴进对话里让它照着写。我的体会是:越是大牌开源库,AI的API幻觉越少;越是冷门小库,越要谨慎。凡是遇到冷门依赖,一律先把文档贴给AI再让它动手。
4.2 对话越来越长,代码越来越“打转”
用过AI编程助手的人基本都遇到过这种场景:对话进行到一半,你发现它开始重复写已经写过的代码块,或者把之前明确否定过的方案又提了一遍,甚至出现前后逻辑自相矛盾。
根因是上下文窗口已经被大量历史对话和旧代码塞满了,AI分不清哪些信息是“当前的现状”,哪些是“已经废弃的讨论”。它就像一个人被拉进了一场持续五小时的会议,听到后面已经记不起第一小时定了什么结论。
我的急救方案是“重置会话”:新开一个对话窗口,把“已确认的结果”压缩成一段摘要贴进去。摘要只包含三部分:当前目标、已经确定的方案、待办事项。绝对不要把五小时的历史记录全贴过去,否则新会话很快就会中毒复发。这种“定期清理、保留摘要”的做法,比试图在同一个会话里无限追加需求的效率高得多。
4.3 安全底线被“顺手写成漏洞”
AI生成代码时最吓人的不是报错,而是看起来很顺畅地写出一段有严重安全问题的代码。比如:直接用字符串拼接SQL、把密钥硬编码在代码里、拿eval处理用户输入、把越权校验写在某个根本不会被调用的中间件里。
根因很简单:AI是在拟合“你看起来想要的东西”,它不是一个安全审计器。如果你说“写一个查询接口”,它会默认用最直观的方式拼接查询语句,而不会主动想到SQL注入这回事。
我的急救方案是“三层防线”。第一层,在需求描述里写清安全约束:“禁止SQL拼接,禁止硬编码密钥,所有输入必须经过参数化查询和边界校验。”把这个要求写进项目规则文件,每次自动加载。第二层,每次vibe完成后,专门挑出三个点逐行审查:用户输入在哪里进入系统、密钥在哪里被访问、权限校验是否真的拦到了越权请求。第三层,让别人负责安全审查——我自己写的代码尚且会有盲点,AI生成的代码更不可能一次就看穿。
4.4 测试看起来全绿,实际是假绿
再来说一个很容易被忽略的坑:让AI补测试,它补完跑一遍全绿,你开心地提交了,结果上了环境被边界输入直接打崩。为什么测试是绿的?因为它只写了“正常路径”——传一个正常对象、调一次正常方法,断言两个正常结果。
根因是:AI对“测试”的理解停留在示例层面,它不会自己推演边界条件。你要求“写测试”,它默认你会给它具体用例;你要求“写一个能拦截非法输入的测试”,它才会开始想边界。
所以我的做法是,在提示词里明确追加边界样例:“请你为这个函数补上这几类用例:空数组、超长字符串、重复key、非法参数、并发调用。”每次补完后还会故意改掉一段正常实现的逻辑,跑一次测试,看它们能不能把异常揪出来。如果测试没失败,说明这组测试根本测不住行为变化,那就是假绿,必须重写。
5. 让 vibe coding 真正持续的三个习惯
5.1 测试先行的心流改版
很多人以为vibe coding和写测试是冲突的——都让AI写了,还写什么测试?我的体验正相反,测试先行才是vibe coding最稳的锚点。
我现在最常用的一套姿势是:先让AI根据需求列一份测试清单,我用5分钟给这份清单补几个边界用例,再让AI照着测试去写实现。测试清单一旦定了,后续整个vibe过程中我根本不用每行代码都盯着看,只要保证最终所有测试变绿就行。这相当于给AI戴了一根绳索,它可以在悬崖边跳舞,但不会真的掉下去。
我统计过自己的项目样本,采用“测试先行”之后,提交后返工率大概低了三分之一。原因很简单:验证成本从“人肉看代码”变成了“跑一条命令”,而跑命令是零摩擦的,遇到问题马上能发现,不会把坏味道带到下游。
5.2 提示词模板要沉淀成文档
跟AI配合久了就会发现,高频需求其实就那几类:新增一个查询接口、改一个字段校验、把某段逻辑重构到服务层、给某个模块补测试。我手里自然会积累出几套反复使用的提示词模板,比如:
新增一个根据传入ID查询详情的接口,风格与现有service层保持一致, 参数需要做基础非空校验,返回结构统一为 { code, data, message }。 不改变现有路由前缀,不需要写多余注释,先给出代码再说明改动点。我后来把这些模板统一收进项目里的一份ai_prompts.md,并在编辑器里配置成“项目规则文件”。每次开会话,AI自动加载这些约束,我不用重复输入三十遍“风格与现有保持一致”。这件事最大的价值不是省程序员敲几行字,而是让AI的每一次产出都保持同样的口头禅和结构,代码库看起来像同一个人写的,而不是一百个AI写的。
以我自己的项目为例,这份提示词备忘目前大概有100来行,里面全是踩过坑之后沉淀出来的“约束条款”。比如“不允许用某个旧API”“错误信息必须包含操作类型”“所有外部接口调用必须有超时时间”。这些条款在一次vibe会话里可能只用到一两条,但长期加载会让AI行为越来越“像我们在职场上带了三年的新人”。
5.3 给明天的自己留一个“记忆续传”入口
AI对话不像人脑,会话一刷新就失忆,这是最让人抓狂的一点。今天写的代码、讨论的结果、踩过的坑,换个分支、换个电脑、换个模型,全都归零。所以我养成了一个很简单的习惯:每天结束前,在当前目录记一个dev_notes.md,只写三行。
- 今天改了什么:完成了配置文件的批量迁移逻辑,拆掉了两个废弃接口 - 明天准备做什么:把回调通知里的重试策略改成指数退避 - 昨天踩的坑:某个旧版SDK的timeout默认是0,表示永不超时,必须显式设置第二天开工时,我先把这份文件丢给AI,让它读一遍摘要,然后基于这个状态继续对话。这个习惯让我的AI开发状态真正做到了跨会话连续。哪怕隔了两周再回来做同一个项目,我也不用从头跟AI解释前因后果,把摘要贴过去它就能接上。
我甚至发现,这个习惯对团队协作也有好处——即使某天换了一个完全没有参与过项目的人来接手,他只要读读dev_notes.md和ai_prompts.md,就能大致还原这个项目的演进脉络和坑位分布。AI不会记住我们的项目,但我们可以通过文档帮它记住。
最后说点感性的体验。用AI编程搭档时间越长,我越觉得vibe coding不是“不管了”,而是把过去花在打字上的精力,重新分配到评审、拆解需求、补测试这三件事上。它不会让你变成一个可以不懂代码的人,反而逼着你把需求想得更清楚——因为AI会把你含糊的需求翻译成具体代码,而你必须去review它的翻译,并且最终为结果负责。抱着这种心态,vibe coding就不仅仅是一种工具玩法,更像是一种新的开发方法论。