Adam 那篇东西过了两年再翻出来,社区里那轮吵架早没热度了。但有一句留下来了,比当时任何一篇长文都更接近问题的核心——他不再问“你用没用 AI”,而是问“你有没有为重要的部分战斗过”。翻译成行业语言,这句话说的不是态度,是一个被所有人跳过去的机制:理解不是写代码之后自然沉淀下来的东西,理解是摩擦的副产品。手写代码之所以能让人懂系统,是因为它在每个决策点上都逼你停一下——变量为什么放这,状态为什么这么流转,失败路径要不要处理,库的边界在哪。AI 把这套停顿拿掉了。这是它的全部卖点,移除摩擦。而摩擦恰好是理解建立的那个机制。两年前我读这个观点,觉得这老头是旧工具被新工具怼了之后的防御姿态,把“我手写所以我更懂”包了层道德外衣。现在回头,他说的不是道德,是机制。机制上,这条因果链被 AI 一口咬断了。
先拆“摩擦”这个词。手写代码的摩擦,本质是时间上的强制停顿。你想写个循环,你必须在脑子里先跑一遍边界条件;你想调个函数,你必须知道它返回什么、抛什么、副作用在哪。这些停顿不是效率损失,是理解正在发生的地方。一个人写了一年代码,对系统的理解未必来自文档,来自那些错——错就是摩擦,摩擦就是停下来想。但评论区有个人说了一句我当时没当回事、现在觉得比 Adam 原文还准的话:AI 不是移除摩擦,是重新定位摩擦。它拿走的那些摩擦——语法错误、不记得 API 签名、不记得怎么起测试套件——是会自我宣告的。你运行一下它就报错,你被迫处理。而 AI 留下的那些摩擦是沉默的:一个变量名你觉得顺理成章,但你其实没想清楚它和上游数据模型的约束关系;一段正则看着能跑,但你不知道它在某个 Unicode 边界上会怎么错。这些摩擦不会主动跳出来。你需要一种主动找错的意识,而大多数人——包括我——在工具说“好了”的时候,不会去主动找错。
所以问题不在“AI 代码质量低”,那个维度挺糙的。问题在 AI 把验证的成本从一个强制环节变成了一个需要自律的环节,而人的自律在有捷径的时候是系统性地靠不住的。
Ida Zhang 在那个讨论里贴过一组数:扫了 270 个 AI 生成的项目,57.8% 至少有一个真实 bug,11% 有安全漏洞,硬编码密钥、XSS 都有,而且代码表面看着干净。这个采样我没法核验,但她点出的反差是对的:表面干净是 AI 最擅长的事,而最危险的错误恰恰是那些不会让表面变脏的错误。手写的人至少知道自己哪里心虚;接受 AI 代码的人连心虚的机会都没有,停顿不存在了。@avp9-nexus 说的那件事比数据更硬:他跑一个在测试网提交价值的代理系统,记了 26 个错误,没有一个靠重读代码发现,全部是通过不一致的输出浮出来的——哈希分歧、计数器不匹配、同一输入给出不同结果。26 个错误里没有一个能靠读代码找到,这句值得停一下。读代码是手写时代最主力的验证手段,它是摩擦的直接延伸:写的时候想过一遍,读的时候再想一遍。而 AI 生成的代码,读的时候你在读一个陌生人的思路,这个思路的漏洞和你自己的漏洞不在一个位置,你读不出来。验证的手段从“读代码”变成了“看输出是否一致”,但绝大多数团队的测试覆盖远没到能让不一致自己浮出来的程度。
这就是这件事真正残酷的地方。摩擦被重新定位之后,旧的那套验证手段失效了。手写时代,理解靠摩擦,验证靠理解,是一条闭环。AI 时代,理解本来就没建立,验证又被指望用一个更低成本的方式完成——看测试过没过。测试过没过,和“你知不知道这段代码会在什么情况下错”,是两回事。@unitbuilds 说“摩擦不等于理解,验证才是”,我懂他在反对把痛苦浪漫化,但只说对了一半。验证确实更接近理解,但验证本身是要花时间的,而 AI 省下来的时间,大多数人不会主动投进验证里。他们会投进下一个功能里。这是人类天性,不是道德问题。
所以 @madsendev 那个建议——AI 辅助的项目应该强制开发者对自己仓库做测验,证明真的懂自己建了什么——听着挺合理,但反人性。测验是自愿的,摩擦也是自愿的,这两件自愿的事在截止日期面前永远被牺牲。一条规则要靠道德感维持,它就不该被当成解决方案。
这件事真正有分析价值的部分,不是谁对谁错,是利益的分布变了。手写时代,理解的成本由开发者个人承担,收益也由个人获得;AI 时代,理解的成本被推迟到了一个未知的时间点——上线之后、故障之后、有人入职之后、有人离职之后。而收益立即兑现,给了写下代码的那一刻。这个错配就是问题的全部。
开发者工具和 AI coding assistant 这个品类,过去两年的商业化逻辑几乎全建在“消除摩擦”四个字上。广告语写的是“让开发更快”“把想法直接变成代码”。更快是真的。但在 SaaS 这个生意里,你永远要问“这笔钱从哪来、流到哪去、卡在谁手里”。AI 编码工具赚的钱,一部分来自开发者的订阅,一部分来自公司为团队采购的席位。它卖给开发者的东西是速度,卖给公司的东西也是速度,但它没有卖给任何人的东西是理解。理解不在这笔交易里。理解变成了一个负外部性——成本被推到未来,推到维护阶段,推到那个半夜被告警叫醒的人身上。
@reidmarlow 在评论里用过一个词,“维护收据”。他说维护收据比面试解释更难伪造——测试、修复、生产事件留下的痕迹,比一个人站在白板前解释一段代码更难造假。这个词好。它把理解从一种感觉变成了有形资产。AI 时代,开发者的真正问题不是学不到东西,是他们不再积累维护收据。所有收据都变成了“AI 生成、AI 通过、AI 部署”的流水线票据,上面没有挣扎过的痕迹。等下一次故障来,账上没有任何储备可以支取。
Adam 那句话我现在是同意的,而且比两年前更同意。“你有没有为重要的部分战斗过”——“战斗”这个词太重,我换成“你的时间到底花在了哪里”。手写路径的逻辑是:摩擦 → 洞察 → 更好的决策。AI 辅助那条路径的逻辑是:选择 → 实施 → 验证。两条路径都能产出好代码,但学习路径完全不同。第一条把理解建在写的过程里,第二条把理解建在验证的过程里。第二条不是绝对做不到,它只是需要一个人主动把省下的时间投回验证。而这件事,据我观察,在真实的交付压力下几乎永远不会发生。
@unitbuilds 说开发者应该把省下的那部分时间用于验证 AI 代码——这句话单独拎出来是全对的。问题是“省下的那部分时间”在真实世界里只是一个理想化变量。AI 省下的时间被拿去开会了、被拿去赶下一个迭代了、被拿去处理积压的更新了。把验证变成一句忠告,等于没有把验证变成机制。机制的意思是有什么东西逼着它发生,而不是靠一个人某天突然决定要变得负责。
那什么能逼着验证发生?目前只有两种。一种是故障——昂贵的、生产环境的、有用户损失的故障。这强制是真的,但它到来的时刻不由你选,代价也不由你控。另一种是合同和标准——如果一个 AI 辅助的项目要过验收,验收的人有权质询,验证就会发生。但后者在工具链里还没成为默认存在。现在的 AI coding assistant 没提供任何东西让验证变成流程的一部分。它们优化的是生成速度,不是验证能力。它们连个诚实的东西都不太给:它生成一段代码,不告诉你“我对这段代码没把握的程度是 70%”,它只会说“这样应该可以”。这是产品设计的问题,不是用户习惯的问题。
写到这,一个更冷的结论自己浮出来了。AI 编码工具这个生意,卖的最核心的东西其实是“让开发者以为自己懂了”。你看着一段干净的代码,它写好了注释,边界处理得比你想象中完整,你就以为这段代码在你脑子里已经有了可恢复的状态,以为下次要改的时候你知道该碰哪里。这个“以为”是错的。你不知道。你只是看过了正确答案,看过了不等于能重新推导。理解的证据从来不是“你看到的时候能认可”,而是“没有提示的时候你能重建”。这也是为什么手写时代即便一个人写得很慢、很烂,他依然比一个接受正确答案的人更懂系统:前者的每一行都是重建,后者只是在做选择。
这个判断不是怀旧。我不会说大家该回去手写代码,那个时代过了。我想说的是,如果摩擦是理解的前提,而 AI 移除了大部分摩擦,那么“用 AI 的人”和“不用 AI 的人”之间出现差异的地方,不在能力,不在智力,不在学习速度,在于谁保留了多少摩擦。一个人用 AI 写但坚持自己审、自己改、自己跑测试、自己复现 bug,另一个人全盘接受,这两个人做的是完全不同的两件事。前者在用一个加速器,后者把自己外包给一个黑箱。两年过去,这个分化没缩小,反而在扩大,因为工具本身没有为后者提供任何抵抗的力量。
我的判断摆在这儿:AI 辅助编程的真正分水岭不是“用和不用”,而是“摩擦被移除之后,你有没有主动把摩擦加回来”。这个判断的证伪条件也具体——哪一天 AI 编码工具能把验证能力做成自动化的默认流程,不是在用户要求时才跑测试,而是能在生成代码的同时标记出它自己不确定性最高的部分,并且把这个不确定性直接纳入 CI 流程,那这套“人需要主动加回摩擦”的分析就要推倒重来。到那时,摩擦未必需要人自己去找,工具可能本身就带某种摩擦力。但在那之前,一个团队用 AI 编程工具省下的时间,到底有多少投回了验证,这是可以算账的。而据我看到的账,这个数字无限接近零。
这就是代价。
