AI 编程最危险的瞬间:它还没听懂,就已经开始写了
AI 编程最危险的瞬间:它还没听懂,就已经开始写了
AI 写代码真的很快。
快到你刚说完一句“帮我加个导出功能”,它已经开始改文件了。
快到你还没解释清楚“导出哪些字段、权限怎么判断、失败怎么提示、老数据怎么办”,它已经给你生成了一套看起来很完整的实现。
这就是 AI 编程最危险的瞬间。
不是它写不出代码。
而是它在还没听懂的时候,就已经开始写了。
很多人刚开始用 AI 写代码时,最容易被这种速度打动。过去要半小时起手的功能,现在三分钟就有 diff。过去要查文档、翻旧代码、抄邻居实现,现在一句话就能跑起来。
但用久了你会发现,真正让人心里发毛的,恰恰也是这种速度。
它太愿意开始了。
你给它一个模糊目标,它会补全细节。
你给它一个不完整上下文,它会假装上下文完整。
你给它一个现象级 bug,它会直接修现象。
你让它“看下能不能优化”,它可能顺手把本来稳定的结构改成另一套风格。
AI 编程的问题,从来不只是“代码质量不够好”。更深的问题是:它会把没对齐的意图、没确认的边界、没验证的假设,全部写进代码里。
代码只是最后的结果。
前面那些没问清楚的东西,才是真正的风险来源。
一、它不是不会写,是太擅长猜
人类开发者听到一个模糊需求,通常会停一下。
“导出是 CSV 还是 Excel?”
“有没有权限控制?”
“数据量大时要不要异步?”
“失败后用户能不能重试?”
这些问题听起来慢,但它们不是拖延。它们是在确认边界。
AI 不一样。
AI 的默认姿势是积极响应。你说“加一个导出”,它会根据常见模式推断出一个导出按钮、一个接口、一个工具函数、一个成功 toast,甚至顺手补一个样式。
这看上去很聪明。
但工程里最怕的就是“看上去很聪明”。
因为它猜出来的内容,可能每一项都合理,却没有一项是你真正要的。
你要的是后台管理员导出全量订单,它给你做成了当前页面筛选结果导出。
你要的是服务端分页导出,它给你做成了前端拿当前列表转 CSV。
你要的是保留团队已有错误处理模式,它新引入了另一种 helper。
最后你看 diff,会有一种奇怪的感觉:每一段代码单独看都说得过去,但合起来就是不对。
这不是 AI 不会写。
这是 AI 太擅长把空白补成答案。
可需求里的空白,不应该由模型擅自填。它应该被问出来,被确认,被写成约束。
二、AI 的“已完成”,经常只是“已生成”
另一个常见错觉,是把“生成完代码”当成“完成任务”。
AI 很喜欢说:
“已完成。”
“问题已修复。”
“现在应该可以正常工作了。”
听上去很可靠,但你仔细追问一句:“你跑了什么验证?”很多时候答案就开始虚了。
它可能只是静态看了一遍。
它可能只跑了一个不相关的测试。
它可能没有覆盖真实失败路径。
它也可能因为环境里缺依赖、测试没跑起来,就用一句“理论上应该可以”绕过去。
工程里,完成不是一种语气。
完成必须是一组证据。
你改了导出功能,就要证明导出路径能跑通。
你修了权限判断,就要证明有权限和无权限都被覆盖。
你修了 bug,就要证明 bug 能先复现,再被修掉。
你做了重构,就要证明外部行为没有变。
没有证据的“已完成”,只是“我写完了”。
而“我写完了”和“它能正确工作”,中间隔着测试、验证、边界条件、集成风险和真实用户场景。
AI 最大的问题不是它不会给你一个答案,而是它太容易让你误以为答案已经经过验证。
三、修 bug 时,最怕它只修掉症状
如果说新功能里最危险的是“没听懂就开始写”,那修 bug 时最危险的就是“没定位根因就开始改”。
你贴给 AI 一个报错:
“这个页面偶尔白屏,帮我修一下。”
它可能很快找到一个空值判断,然后加上:
if(!data)returnnull;页面不白了。
看起来修好了。
但真正的问题可能是接口 race condition,可能是状态初始化时机不对,可能是缓存 key 错了,可能是异常被上游吞掉了。
AI 很容易把“错误消失”误判为“问题解决”。
这在 bug 修复里尤其危险。
因为症状是最吵的,根因通常是最安静的。
报错栈会指向最后炸掉的地方,但最后炸掉的地方未必是最先出错的地方。
一个空判断可以让页面不崩,但也可能把错误数据静默吞掉。
一个 try-catch 可以让日志变干净,但也可能让系统失去可观测性。
一个默认值可以让测试通过,但也可能掩盖上游协议已经漂移。
真正的 bug 修复,应该从复现开始。
先让问题稳定出现。
再列出假设。
再沿着数据、状态、调用链往前追。
最后用一个回归测试证明:这个问题以前会失败,现在不会失败。
如果没有这个过程,AI 的“修复”很可能只是把报警器音量调低了。
火还在。
四、你需要的不是更快的 AI,而是更稳的协作协议
很多人优化 AI 编程方式时,第一反应是换更强的模型、写更长的 prompt、塞更多上下文。
这些当然有用。
但它们解决不了一个根本问题:如果流程本身允许 AI 在没搞清楚前就动手,那么模型越强,只会越快地把错误假设写进系统。
真正需要改变的,是协作协议。
不要一上来就说:
“帮我实现这个功能。”
可以先说:
“先别写代码,帮我确认需求、边界、风险和验收标准。”
不要一上来就说:
“这个 bug 帮我修一下。”
可以先说:
“先复现问题,列出可能根因,追到确认原因后再改。”
不要在它写完后只看 diff。
还要问:
“你跑了什么验证?验证覆盖了哪些路径?还有哪些风险没有覆盖?”
不要让 commit 成为 AI 生成代码后的自动动作。
commit 前应该有一轮 review:这次改动是否符合需求?有没有无关改动?有没有临时代码?有没有测试缺口?有没有和团队约定冲突?
这也是我做dev-skills(仓库:Jason-chen-coder/dev-skills)的原因。
它不是想把 AI 编程变成繁琐流程。
相反,它想解决一个很朴素的问题:在不同场景下,让 AI 先做该做的事。
需求模糊时,先拷问需求。
方案复杂时,先定方案。
写功能时,用测试锁住行为。
修 bug 时,先复现和定位根因。
声称完成前,拿出验证证据。
commit 前,先 review diff。
这些步骤单看都不新鲜。成熟开发者本来就会这么做。
只不过到了 AI 编程时代,我们不能假设模型天然懂这些工程习惯。
你得把习惯变成协议。
把协议变成入口。
把入口变成每次都能复用的 skill。
五、快不是问题,盲快才是问题
我并不反对 AI 写代码快。
恰恰相反,速度是 AI 编程最有价值的地方之一。
它能快速生成样板代码,快速探索方案,快速补测试,快速查调用链,快速给出实现草稿。
但工程不是打字比赛。
工程是在约束里交付正确的变化。
一个靠谱的 AI 开发流程,不应该追求“让 AI 更快开始写”,而应该追求“让 AI 在该开始的时候开始写”。
该问清楚的时候,慢一点。
该验证的时候,硬一点。
该 review 的时候,挑剔一点。
该收尾的时候,克制一点。
真正高效的 AI 协作,不是把油门踩到底,而是先装上刹车、仪表盘和路线图。
因为你终究不是在和一个代码生成器合作。
你是在把一个极其积极、极其能写、但默认没有团队上下文和工程责任感的助手,纳入真实的软件交付流程。
这件事的关键,不是让它少写。
而是让它先听懂,再动手。
如果你也经常被 AI 的“已完成”坑过,可以回头看一眼你平时的提问方式。
也许问题不在于它不够聪明。
而在于我们太早给了它开工许可。
