AI & Machine Learning

AI工具正在悄然改变开发者的思维方式

我是在持续使用 Copilot 大约半年后注意到这个变化的。当时我在调试一个 Python 脚本,还没读完错误信息就已经下意识地打开了 AI 助手。回溯信息就摆在眼前——KeyError: 'user_id'——但我的第一反应已经变成了"粘贴到聊天窗口",而不是"先看看再想想"。那一刻让我感到不安,远比任何关于 AI 取代开发者的争论更让我在意。

AI 编程工具改变的不仅仅是我们的生产力,还有我们的认知习惯——我们如何思考问题、多深入地理解自己的代码、以及如何学习。其中一些变化确实是积极的,但另一些则令人担忧,而且这种担忧不会体现在生产力指标上。

用卡尼曼框架理解编程思维

丹尼尔·卡尼曼关于系统1(快速、自动、直觉式)和系统2(缓慢、刻意、分析式)思维的区分,出奇地适合用来理解开发者的工作方式。阅读熟悉的代码模式、编写样板代码、使用已知的 API——这是系统1。调试竞态条件、设计分布式系统、推理安全隐患——这是系统2。

AI 编程工具擅长的恰恰是系统1的任务。它们能瞬间生成样板代码,补全熟悉的模式,处理那些经验丰富的开发者本来就能自动完成的机械性工作。这确实很有价值——把认知资源释放出来去处理真正困难的问题,总体上是件好事。

风险在于,AI 工具也让你很容易完全跳过系统2的思考。当 AI 建议一个完整的函数时,直接接受比真正理解它需要的认知努力要少得多。当它提出一个 bug 的修复方案时,诱惑是直接应用然后继续干活,而不是去理解为什么它有效。长此以往,这会让区分高级工程师和普通码农的分析能力逐渐退化。

真正变好的方面

如果把这件事完全说成坏事,那就不客观了。AI 工具确实在某些方面让开发工作变得更好了。

探索不熟悉的领域

当我需要使用一种不常用的语言或框架时,AI 助手的帮助是变革性的。不是因为它们能写出完美的代码——它们做不到——而是因为它们给了我一个大方向基本正确的起点。不用花一个小时翻文档去搞清楚 Go 里 PostgreSQL 连接池的基本写法,我能在 30 秒内拿到一个合理的脚手架,然后把那一个小时花在真正需要判断力的地方。

这降低了尝试新工具的门槛。我已经探索了一些之前可能会跳过的技术,就因为以前入门成本太高。这是实实在在的好处——能够自如地在更多技术栈之间切换的开发者,战斗力更强。

减少上下文切换的摩擦

现代开发需要在不同语言、框架和范式之间不断切换。这个项目的测试运行器是 Jest 还是 Vitest?这个 API 返回的是 Promise 还是用回调?这个代码库用的是 snake_case 还是 camelCase?AI 工具能消化这些细节,生成符合当前上下文的代码,减少了在项目间切换的摩擦。

加快代码审查速度

让 AI 总结一个大的 diff、标记潜在问题、或者解释不熟悉的代码模式,这让代码审查对我来说不再那么枯燥。我仍然自己读代码——AI 的总结只是起点,不是替代——但它帮我把注意力集中在重要的部分,而不是在样板改动和复杂逻辑改动上花同样多的时间。

正在变差的方面

理解力的鸿沟

我在代码审查中开始注意到一个规律:重度使用 AI 工具的开发者写出的代码能运行,但他们无法完全解释清楚。你问"为什么这里用 WeakMap 而不是普通的 Map?"得到的回答是"AI 建议的",而不是关于垃圾回收机制的解释。代码本身没问题,但理解不到位。

这很重要,因为理解力才是让你能在压力下调试、在意想不到的方向扩展代码、以及做出架构决策的根基。你当然可以发布自己不理解的代码——人们一直在这样做——但你没法维护它,你也没法把自己都不懂的东西教给别人。

调试能力的退化

调试是开发者最重要的技能之一,而且是一项需要练习的技能。仔细阅读错误信息、形成假设、缩小问题范围、用调试器验证假设——这些都是通过练习而增强、因忽略而退化的习得行为。

当你的第一反应是把错误粘贴到 AI 聊天窗口然后直接应用它建议的修复方案时,你并不是在练习调试。你在练习的是另一种技能:评估 AI 的建议是否看起来合理。这个技能有用,但它不是同一回事。那些能系统化调试的开发者,每次遇到 AI 解决不了的问题时都会胜出——而在生产事故中,AI 解决不了的情况占大多数。

平庸的引力

AI 编程工具生成的是中规中矩的代码。这几乎是必然的——它们在现有代码的分布上训练,所以输出的是那个分布的统计中心。对于简单直接的任务,中规中矩就够了。但当你需要优雅的方案、创造性的思路或者对问题领域的深刻理解时,中规中矩是不够的。

我亲眼看过开发者接受了技术上能用但错过了关键洞察的 AI 生成方案——那些洞察本可以让代码更简洁、更快或更易维护。AI 不会建议说"这其实是一个拓扑排序问题"这样的巧妙观察。它只会生成一个暴力破解的可行方案,没人会质疑,因为测试都过了。

学习能力的问题

对于初级开发者来说,影响更为显著。学习编程的本质是构建心智模型——理解变量如何工作、调用函数时发生了什么、为什么某些数据结构比其他的更快。这种学习是通过挣扎实现的:写出烂代码、遇到错误、搞清楚原因、然后逐渐建立直觉。

AI 工具跳过了这个挣扎的过程。一个对每个错误都能立刻得到答案的初级开发者,不会建立起和那些花了 30 分钟阅读堆栈跟踪、逐步调试的人同样的直觉。我总会想到的一个类比是 GPS 导航:总是使用 GPS 的人,空间推理能力比有时看地图导航的人要弱。到达的目的地相同,但建立的心智模型不同。

我并不是说初级开发者不应该使用 AI 工具。这已经是不可逆的趋势了,而且这些工具确实提高了生产力。但有一种做法值得提倡:刻意地在没有 AI 辅助的情况下练习——花时间直面原始的错误信息、阅读文档、使用调试器——专门用来构建那些 AI 工具倾向于跳过的基础理解。

找到平衡点

在反思了自己习惯的变化之后,我总结出了几条对我有效的原则。它们不是普适法则——不同的开发者会找到不同的平衡点。

  • 先读错误信息,再求助 AI。给自己 60 秒时间面对错误信息或异常行为。很多时候,你会立刻发现问题所在。如果没有,再问 AI——但让它解释错误,而不是直接修复。
  • 理解后再接受。当 AI 建议了代码,像审查同事的 PR 一样去读它。你能解释每一行在做什么吗?如果不能,要么搞清楚,要么不要合并。对于你负责的代码,"能跑"是不够的。
  • 用 AI 处理无聊的部分,而非困难的部分。让它生成测试脚手架、API 样板代码、配置文件和文档格式化。架构设计、算法选择和调试自己来。困难的部分才是你学习和发挥判断力最大价值的地方。
  • 定期脱离 AI 工作。和任何工具依赖一样,偶尔在没有 AI 辅助的情况下工作是有益的。不是因为工具不好,而是因为你需要保持它所替代的那些能力。我尽量每周做一次不借助 AI 的完整调试。
  • 教别人,讲出来。检验理解程度的最好方式是向别人解释。如果你解释不了 AI 生成的代码为什么有效,说明你的理解还不够。

更宏观的视角

我们正处于软件编写方式发生根本性变革的早期阶段。AI 工具会持续进步——更准确、更懂上下文、能处理更大更复杂的任务。真正能脱颖而出的开发者,不是抵制工具的人,也不是把一切都交给工具的人,而是善用 AI 获得杠杆效应、同时保持深度理解力的人——当 AI 力不从心时,这种理解力才是真正的竞争力。

我觉得最贴切的类比不是自动化取代工人,而是电动工具辅助手艺人。台锯不会让木匠失业,它让切割的机械部分更快,好让木匠有更多时间花在设计、榫卯和精细打磨上。但一个从来没学过不靠台锯就把木头切直的木匠,在需要手工工具的活儿面前会暴露出致命的短板。

问题不在于要不要用 AI 编程工具,而在于你是把它们当作放大技能的电动工具,还是当作阻碍技能发展的拐杖。答案取决于具体的任务、上下文,以及你所处的职业阶段。但这个问题值得经常自问——因为默认的趋势会滑向依赖,而只有有意识的反思才能抵抗这种惯性。