文章揭示了 demo 与实际生产中 AI 辅助编程的差异——认知协助 vs 认知卸载,前者 AI 做打字,后者 AI 做思考,最终体现在生产故障时的可解释性缺失。
AI辅助编程在演示中呈现的样子,和它在实际赶工期被使用的方式之间存在一道鸿沟。演示中,模型写一个函数,开发者读懂它、理解它、然后合并它。赶工期里,模型写一个函数,开发者草草扫过,看起来合理,就合并了。同一个工具,两种截然不同的结果,而这种差异在 diff 里根本看不出来。
第一种情况我称之为认知辅助:AI 替代的是打字,而不是思考。第二种我称之为认知卸载:AI 替代了思考,开发者只做剩下的敲代码工作,大部分时候只是点一下"accept"。两者在 Pull Request 里看起来毫无二致。只有到后来出了问题,有人需要解释系统为什么会这样做时,它们才会分道扬镳。
以下是这个鸿沟真正在生产环境中暴露的地方。(以下是常见模式的说明性组合,而非具体事件。)
一位开发者让 AI 助手生成一个迁移脚本,新增一张带有两个外键的表。看起来没问题,本地运行正常,测试通过,上线了。团队里没有人——包括写这个迁移的人——真正推敲过这张表在生产环境中会面对怎样的访问模式。三个月后,一个仪表盘查询这张表时在真实流量下开始超时,因为实际用来过滤的那一列上没有建索引,这个细节如果有人亲手设计过这个 schema 而不是直接批准一个方案,本来是显而易见的。
有人遇到了 NullPointerException,把堆栈跟踪粘贴到 AI 对话里,得到了一个建议的 null check,加上它,上线了。异常消失了。两个 sprint 后,下游某处出现了另一个 bug,因为这个 null check 只处理了症状——调用栈更上游的一个竞态条件——而不是真正的原因。没有人把这两件事联系起来,因为接触过第一个修复的人从来没有理解过到底在竞速什么。
在 retro 上,技术负责人问为什么一个服务要对下游服务发起三次同步调用而不是发布到队列。没有人能回答,因为这个模式是在一个紧急周里生成的,草草扫过就合并了。这不是说这个模式一定错了,而是团队里现在没有人能告诉你它是不是错了,这意味着也没有人能安全地改动它。
认知卸载其实不是 AI 的问题。它是一个披着 AI 外衣的代码审查纪律问题。在 AI 工具出现之前审查习惯就薄弱的团队,现在以更高的数量和速度得到着薄弱的审查,这把一个缓慢的泄漏变成了洪水。
如果你想要一个快速的自检:在你合并 AI 生成的代码之前,你能不打开聊天记录就向队友解释它吗?如果给你更多时间,你能自己想出这个方案吗?你知道为什么是这个模式而不是一个显而易见的替代方案吗?如果任何问题的诚实答案是"不能",这不是一个阻碍,它只是有用的信息,告诉你目前站在分界线的哪一边。
在你的团队中,你如何划定辅助和卸载之间的界限?这是明确的规则、审查流程的一部分,还是只是某种直觉,要等到出了问题才会触发?