我告诉了AI入口,为什么它还是改错了?——AI编程工具的真实使用心得
我告诉了AI入口,为什么它还是改错了?——AI编程工具的真实使用心得
一个真实的故事
前几天,我在改一个绑卡功能的异常处理问题。
用户反馈说:绑卡失败时永远只提示“绑卡签约申请失败”,没有任何具体原因。我很快定位到问题在调用链的第四层——一个底层Client的catch块把原始异常信息吞掉了,抛出了一个硬编码字符串。
我想,这不正好用AI来改吗?于是打开了Cursor,输入:
“绑卡失败时抛出具体失败原因,入口是 /api/userBank/bindApply”
结果让我很失望。AI直接把全局异常处理器改了,加了一段统一返回“绑卡失败”的逻辑。我想要的底层修改,它一点没动。
我不信邪,又试了Kiro、Copilot Chat,结果惊人地一致——所有AI都选择了改全局异常处理器。
为什么?我已经告诉它入口了啊,它顺着调用链往下找,不就发现问题在第4层了吗?
问题出在哪?
我花了一整天反复试验,终于想明白了。
误区1:“入口”这个词的含义不一样
对我来说,“入口”意味着:从这个API开始,深度优先遍历整个调用链,直到第三方接口。
但对AI来说,“入口”只是:找到了Controller里的那个方法,然后——停下来了。
AI面临一个它无法解决的困境:追多深才算够?
- 追到Service层?够不够?
- Service调了另一个Service,要不要继续?
- 追到Client层?这是不是底了?
- Client里发HTTP请求,要不要追到网络层?
AI不知道答案。它的设计哲学是:追一层,停下来等用户反馈。用户不说“继续”,它就不动。
误区2:我以为AI会“主动探索”
我以为AI会像人一样,遇到问题就顺着调用链往下挖,直到找到可疑的地方。
但AI不是这样的。AI是懒惰的——不是态度上的懒,而是设计上的保守。在没有明确指令的情况下,它会选择改动最小、风险最低的方案。
改全局异常处理器,只改一个文件,影响面可控,逻辑简单。这是AI眼中最“安全”的答案。
改底层Client的catch块,需要:
- 找到那个文件
- 理解异常处理逻辑
- 修改后确认不影响上层
- 可能还要改多层调用
风险大、改动多,AI天然排斥这种方案。
误区3:我高估了AI的“调用链追踪”能力
这是最核心的问题。AI根本不会主动追踪调用链。
它的工作方式是:你给它5个文件,它就分析这5个文件。你给它1个入口,它只看那个入口所在文件的直接调用,不会递归地去看每个被调用方法的实现。
为什么?因为成本。
假设每个文件有500行代码,追一层需要读1个文件,追两层需要读3-5个文件,追三层需要读10+个文件。AI的上下文窗口有限,它不可能无限制地往下追。
更重要的是,大部分用户的真实需求并不需要追到底。AI选择了性价比最高的策略:先看第一层,用户不满意再说。
那我以后怎么用AI修bug?
经过这次折腾,我总结出了一套可行的协作模式。
核心原则:分析和修改分离
绝对不要让AI一次性完成“分析+修改”。一定要分成两步:
第一步:让AI分析,不改代码
不要改代码,只分析:
从入口 /api/userBank/bindApply 开始,帮我追踪完整调用链。
每一层列出:
1. 调用了什么方法
2. 异常是怎么处理的
3. 找出哪一层把具体异常信息丢掉了
AI会输出类似这样的分析:
第1层: UserBankController.bindApply() - 无异常处理
第2层: BankCardServiceImpl.deductPreBoundCard() - 捕获后重新抛出
第3层: BankPayService.sendSignRequest() - 捕获后抛IllegalStateException
第4层: BankPayClient.bindBankCardSms() - 捕获后抛"绑卡签约申请失败" ← 问题在这里
第二步:确认后,指导AI修改
确认问题在第4层。修改 BankPayClient.bindBankCardSms() 第95行:
把 throw new BusinessException("绑卡签约申请失败");
改成 throw new BusinessException("绑卡失败:" + e.getMessage(), e);
实战模板
我总结了三个实用模板,覆盖不同场景:
模板1:分析调用链
不要改代码,只分析。
入口:[API路径]
请列出完整调用链(至少5层),标注每层的异常处理方式。
找出具体异常信息在哪一层丢失的。
分析完停下来,等我确认。
模板2:搜索定位
搜索“[具体错误信息字符串]”,
找到抛出这个异常的位置,
告诉我文件名和行号。
不要改代码。
模板3:精准修改
修改 [文件名] 第[行号]行,
把 [原代码]
改成 [新代码]
不要改其他文件。
善用“追问”
AI分析不到位时,不要重新提问,直接追问:
你:追到第3层停了,继续往下追
AI:第4层是BankPayClient.bindBankCardSms()
你:再追,看这个方法里调用了什么
AI:调用了sendRequest(),里面catch了异常
你:好,就改这个catch块
你不需要自己读代码,但需要会追问。 AI帮你读,你来判断方向。
不同AI工具的对比
我测试了三个主流工具,感受如下:
| 工具 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|
| Cursor | 代码理解能力强,支持多文件编辑 | Agent模式容易过度修改 | 复杂重构(需严格review) |
| GitHub Copilot | 保守、可控,不会擅自改代码 | 多文件能力弱 | 日常编码、小范围修改 |
| Kiro | 界面友好,免费 | 调用链追踪能力一般 | 学习和探索 |
我的最终选择是双持:
- 日常用 Copilot(补全、问答、小修改)
- 复杂重构用 Cursor,但关掉自动执行,每次都人工review diff
写在最后
这次经历让我明白了一个道理:
AI编程工具不是“自动驾驶”,而是“导航仪”。
- 导航仪会告诉你路怎么走,但方向盘还在你手里
- 导航仪可能选错路,你需要判断要不要听它的
- 导航仪不知道你的目的地是哪个门,你需要明确告诉它
不要指望AI一次性搞定所有问题。把它当成一个24小时在线的、会写代码的、但需要你不断引导的搭档。
用对了方法,它能让你的效率提升10倍。用错了方法,你会花更多时间在“纠正AI的错误”上。
最后送你一句话:
不要让AI当侦探,让它当工匠。你告诉它钉子在哪,它帮你敲。你让它自己找钉子,它就会敲错地方。
希望这篇博客能帮你少踩一些坑。如果你也有类似的经历或更好的方法,欢迎交流。
更多推荐


所有评论(0)