摘要
1) 一句话总结 本文通过实际调试案例,阐述了 AI 编程助手作为“升级版小黄鸭”如何改变程序员的编程习惯,并强调了清晰表达与独立思考在驾驭 AI 工具时的重要性。
2) 关键要点
- 实际调试案例:作者利用 o1 preview 调试 TipTap Markdown Extension,通过多轮交互并补充
serializer方法代码,AI 成功定位根本原因并解决了独立节点转换 Markdown 的 Bug。 - 升级版“小黄鸭”:传统的“小黄鸭调试法”仅用于倾听,而 AI 助手不仅能听,还能主动思考、提问(如提示死锁风险)并提供架构建议(如推荐观察者模式)。
- 沟通思维转变:与 AI 高效互动需要主动改变思维,必须像与远程同事沟通一样,清晰、准确地交代问题的来龙去脉。
- 编程习惯演进:Cursor、GitHub Copilot 等工具正将编程模式从“构思并埋头编写细节”转变为“清晰描述问题并由 AI 实现细节”,类似于全天候的结对编程。
- 效率提升:AI 能将开发者从繁琐的编码细节中解放出来,并经常能提供不同的思路和更优的解决方案。
- 核心竞争力:在 AI 时代,优秀的程序员不在于代码写得最快,而在于像侦探一样善于提出正确的问题、理清思路并验证假设。
3) 风险/不足
- 建议可靠性风险:AI 目前无法完全替代人类,很多时候会给出不靠谱的建议。
- 依赖人工甄别与拆解:必须由人工来甄别 AI 输出结果的好坏,并需要开发者去拆分任务、给出更具体的指令。
- 基础能力不可替代:使用 AI 仍然离不开扎实的编程基础知识,以及开发者自身独立和系统的思考能力。
正文
今天在调试一个麻烦的 Bug,主要是代码不是我写的,要搞清楚原始代码的思路并找出问题来有点吃力,于是将相关代码都扔给 o1 preview,并尝试描述我的问题。前面几轮 o1 没能很好的理解我的意思,经过几轮修改后很快它能抓住重点,指出了潜在问题,基于它指出的可能问题,我后续更新了一些信息,马上它给出了一个修改方案,测试后居然解决了!
其实在和它互动过程中,通过向它描述问题,以及它给我指出的可能问题,我已经快接近解决方案了,即使它没能给出方案,也已经帮我理清楚了代码的结构。这让我想起著名的“小黄鸭调试法”(Rubber Duck Debugging)。

很多程序员的桌上可能都曾经摆着一只小黄鸭,看起来不过就是那种普普通通的橡皮玩具。在代码的迷宫中走得太深时,你向它解释每一行代码的来龙去脉。神奇的是,往往在表达的过程中,问题的答案就浮出水面了。这就是著名的”小黄鸭调试法”。
现在到了 AI 时代,AI 就是程序员们升级版的“小黄鸭”,不仅能耐心的听你解释代码,它还会思考,会提问,会给出建议。就像金庸小说里面的扫地老僧,当你正在苦恼一个棘手的并发问题时,它会适时地问:“你考虑过死锁的情况吗?“当你在纠结代码结构时,它会建议:“这里如果用观察者模式,是不是会更优雅一些?”
但这种转变不是自动获得的,需要主动开启,也就是你得改变既有的思维方式。以前对着小黄鸭,可以天马行空地自言自语。但要和 AI 助手高效对话,需要学会更清晰地表达。就像和一位远程工作的同事沟通,你得把问题的来龙去脉交代清楚,否则对方可能无法给出有效的建议。
像 Cursor、GitHub Copilot 这样 AI 编程助手/工具的逐步普及,也在一点点的改变了我们编程的习惯。比如以前要实现一段程序,我会脑子构思好,然后动手编码,埋头于代码细节中,而现在是想该如何描述清楚这个问题,让 AI 帮我们实现编码细节,帮助改 Bug,有点像时时刻刻和一个工程师在结对编程。
这样做的好处是可以从繁琐的编码细节中解放出来,甚至有时候能给出不同的思路和更好的方案。但还不能完全做到替代,很多时候 AI 并不能给出靠谱的建议,还是要人去甄别结果的好坏,去拆分、给出更具体指令,仍然离不开编程的基础知识,离不开自己的独立和系统的思考。
在 AI 时代,优秀的程序员不一定是代码写得最快的,而是善于提出正确问题的人。就像一个优秀的侦探,知道该问什么问题,该往哪个方向深入调查。AI 助手则是我们的华生、会说话的小黄鸭,帮助我们理清思路,验证假设,但最终的决策仍然在于我们自己。
如果你的桌上还摆着那只橡皮小黄鸭,不妨试试这个会说话的新伙伴,毕竟未来属于那些既懂技术、又善于驾驭 AI 的程序员。而要驾驭 AI,最好的办法就是保持好奇心和开放的心态,每天去实践和应用 AI。
附录
补充一些我 debug 的具体细节。我在用一个 TipTap 的 Markdown Extension,但是这个 extension 只能对整个文档转换为 Markdown,而我希望对某个独立节点转换成 Markdown,于是我描述问题,并提供了相关代码-starter-kit/tree/master/src/extensions/markdown

然后第一轮它给出了一些思路,提示可能问题出在Node的serializer方法实现有问题,这部分代码其实我没提供。

于是我将测试的 paragraph Node 和 text Node 的 serializer 补充发给它,让它进一步修复:

它在“思考”后找到了 root cause,并给出了解决方案。

