手动重新敲一遍 LLM 生成的代码,以避免认知负债

查看原文 HN 讨论

文章摘要

作者 Ankur Sethi 在这篇「实验室笔记」里坦白:尽管四月他写过反对的话,他现在仍在个人项目里使用编程助手。让 AI 一次性生成整个功能会让他感到不满足和迷失方向,但用它来快进项目里那些无聊的部分,他还是很享受的。问题在于,放任编程助手在项目里自由发挥,会留下他称之为「认知负债」(cognitive debt)的巨额欠账——他可能讨厌为了给网站加标签功能而去翻 Django 文档,但他从根本上仍然想理解这东西是怎么工作的。一个问题无聊,不代表他愿意把对解法的理解完全外包给机器。

理论上他可以逐行审查 LLM 产出的每一行代码——这正是 2026 年这个「被诅咒的年份」里多数开发者被期望做的事:机器人提 PR,人类审查。但他不喜欢审查 AI 生成的 PR:盯着几百行过度防御、注释糟糕、还有微妙错误的代码,一点也不好玩。他说自己可能会为雇主勉强做这件事(同时会尽快让那位雇主变成前雇主),但绝不会为个人项目这么做——个人项目必须首先是好玩的,它的乐趣来自过程而非结果。

他给出的解法自称「效率极低、甚至有点滑稽」:让编程助手把代码生成在聊天窗口里,然后自己手动把所有改动敲进去。他在所有个人项目的 agent 配置文件里都写了同一套指令:我要理解进入这个项目的每一行代码;除非我明确要求,否则永远不要创建、编辑、移动、重命名或删除项目文件,而是把每一处提议的改动展示在聊天里让我手动输入;同样,不要运行任何修改项目文件、安装依赖或改变仓库状态的命令,把命令展示出来我自己运行;我是有经验的开发者,除非我问,不要解释语法、API、编程概念或实现细节。

他估算这种用法仍然比完全不用 LLM 快,但比那些让机器代替自己思考的人慢——不是 10 倍快,大概只有 2 倍快,但换来的是对代码更深的理解。手动敲入的过程中,他会建立起代码如何运作、如何嵌入现有代码库的心智模型;遇到不懂的 API 或算法可以停下来查,或者让 LLM 解释。慢下来意味着更可能发现 LLM 的幻觉或糟糕的设计选择,也可以边敲边清理、重组、重构、加注释,把代码调整成自己的口味。最重要的是,这套流程让他建立起代码库的「空间地图」——他知道每一处功能住在哪里,要改动时知道该去哪改,这既让他在项目里更快,也让他今后能更好地给 LLM 下指令。

他把这个做法类比成青少年时期学编程的经历:老一辈程序员总叮嘱他永远不要往项目里复制粘贴代码——从书里学就把例子全部敲进电脑并确保能跑起来,从博客或论坛答案里学就手打出来并改造进自己的代码库直到完全理解。手动敲 LLM 生成的代码在他看来是完全相同的学习过程:也许不是最高效的用法,但他把理解看得比生产力更重。文末他给出一个更宏大的忧虑:软件行业正在积累巨量的认知负债,很快就得偿还,终将有一天我们不再理解自己数字基础设施的大部分是怎么拼起来的;他改变不了整个行业的走向,但至少能保证自己放到世界上的软件是自己完全理解的——「否则就是职业上的渎职」。

HN 评论精华

这篇拿到 540 分、432 条评论,评论区分歧极大,粗略可分为「照抄不产生理解」的反对派、「手抄确实有用」的经验派、以及一整片关于「这个方向本身是否已经过时」的争吵。

反对派:打字不是学习,发现过程才是:f311a 的顶楼评论引出了 16 条回复:「重新敲一遍对学习是低效的,就像重抄微积分解答一样——你没学到东西。哪怕附带解释,那也不是你自己想出来的,你不知道别的解法。这是记忆练习,不是在建立直觉。更好的做法是自己先写,再问 LLM 有没有更好的方案。」WJW 把这个批评说得最锋利:「文章里其实藏着一篇更好的文章,标题该叫『通过深刻理解 LLM 吐出的代码来避免认知负债』,但那听起来像苦活、大概不受欢迎。给出一个人人都能做的简单方法(哪怕它其实不管用)对读者参与度更好。」他认为这有点货物崇拜(cargo cult)的味道——观察到手打和好结果常常同时出现,就以为是打字本身而非伴随的思考过程带来了好结果。m4xp 同样断言「已经证明是发现过程让我们变强,盲目打字只会让你打字变快」。podgietaru 觉得整件事很荒谬:「无脑打一遍并不比复制粘贴好多少,到那一步不如自己写。」a2128 给了一个刺痛的类比:「作为一个曾经抄同学作业、从网上抄读书报告、照答案册做题的人,我可以告诉你这个策略是众所周知地积累而非避免认知负债。」dools 更直白:「读每一行代码在我看来就已经很荒唐了,重新敲一遍简直难以置信,这肯定是讽刺吧?」也有人从职业角度反对:jatins 说「爱好项目随你,但如果你靠写代码吃饭,祝你向管理层解释成功——『Claude 已经给了我解法,我打算用这周剩下的时间把它敲出来』」。anymouse123456 则贡献了全场最好笑的一段——他脑补了一位美国海军陆战队教官走进开放式办公室的场景:「你他妈在干什么?」「报告长官,我在手打 LLM 的输出!」「你耍我呢?我要的是一个应用,不是打字教程!趴下做二十个俯卧撑!」

经验派:手抄确实有效,只是机制不同:反对声之外,大量老程序员现身说法。wahern 说这个习惯他从 90 年代保持至今:「如果我感觉被催、随手复制粘贴了什么,总会留下一种不安。它会造出一个记忆和理解上的洞,哪怕是看起来很简单的片段也扎眼。你没有仔细走一遍就无法确定它真的简单,而『简单』常常有欺骗性,因为意外通常来自它与周围代码的交互和假设。手打给你时间和空间去考虑更大的图景。」r0ze-at-hn 描述了一个极端做法:接手一个代码库时,他会把代码开在一个窗口里、往另一个窗口重新敲一遍,「不仅抓出并修复了大量 bug,还一夜之间变成了准专家。敲的过程会让我质疑一切:为什么要 import 这个?为什么用 x 不用 y?」bandrami 说 Stack Exchange 时代他总是手打找到的答案;tdeck 补充自己还会顺手改变量名、改格式、增删注释,「可惜现代工具不太方便这么做,Claude Code 默认就想直接改你的源文件,而 Claude 聊天写代码要差得多」——TremendousJudge 给了实用方案:用 Zed(或 VS Code)的侧边栏聊天,收回写权限,提示它「用聊天回答代码」,就得到了一个针对你代码库的个性化 Stack Overflow。sarreph 讲了自己非科班出身学 iOS 时买的一本书,书里强制要求逐行手打例子,十四年后作为软件工程师他仍认为早期的进步很大程度可以追溯到这个要求。sltr 补充了理论依据——「生成效应」(generation effect),并链接了自己五月的类似建议:拿着 LLM 给的设计和实现计划,自己做那些机械的编辑。Kim_Bruning 说自己至今在写真正关键的代码时会手打,「哪怕旁边开着 LLM,它的建议也是手动敲进去的」。1718627440 和多位用户把讨论引向课堂笔记之争:他坚持记笔记调动了更多脑区(听、理解、用自己的话复述、动手写、再看到版面布局),quietbritishjim 则反驳说抄板书可以完全在自动驾驶状态下完成、反而妨碍听讲,「真正有用的是课后的练习题,或者用自己的话总结」。

折中派与替代工作流:不少人提出了自己的变体。holtkam2 的原则很精炼:「我只让 AI 替我写代码,不让它替我思考。写作即思考,编程即写作因而也是思考。任何时候我还没确定某个功能或修复该怎么实现,我就必须自己写,因为那是唯一能逼自己想清楚的方式;只有到了『我完全知道该干什么,剩下的只是敲出来』的时刻,才轮到 AI 上场,本质上当作补全。」(他补充这只适用于要为结果负责的项目,黑客松和个人项目他照样 vibe。)pcwelder 的做法是让 AI 在单独的 worktree 里规划功能,同时自己不受影响地开始写,中途读它的计划来完善自己的想法,最后让 AI 审查自己的实现找 bug。Greenpants 说自己收到生成的代码后会大量追问「为什么」,还会开一个新对话、换一个模型问开放式问题来交叉验证。davide 认为有更简单的路:「建立对改动的完整心智模型,然后提问来确认理解,快得多。」gste 主张用费曼技巧:让 AI 写出可用系统,再让它教你、给你出题、给你打分,「要写就用自己的话写,绝不逐字照抄」。simondotau 分享了三层分级体系,高价值代码全部自己写、每行仔细读,AI 只用于机械改动(清理变量名、函数签名变更后的批量修改)。yanis_t 的做法是让 AI 写但只写小块:不是「实现这个功能」,而是「打开这个文件做这些改动」,每次改动都容易审查。

「方向本身是否过时」的争吵:这是评论区第二条主线。baalimago 用一个类比嘲讽:「『通过手抄编译器生成的汇编来避免次优代码』——我不觉得这是能持续多久的做法」,pritambaral 回敬「LLM 离编译器还差得远」。bonoboTP 把这层意思说得更完整:这就像 80 年代的汇编程序员保持汇编手感——有用、概念值得懂,但多数职业已经转向不需要它了,而且当年的目标也不是靠重抄 GCC 输出来保鲜技能,而是上升到更高层的控制、去思考结构化代码的组织和维护;「有了 AI,我们的角色同样在转移:主要变成判断该在什么上花力气、设定优先级、把需求和缺失的社会语境与潜规则说清楚、预判 agent 还需要哪些文档」。petcat 更刻薄:「这只是一份『照数字填色』的悲惨职业,因为人们懒得对自己的工作或编程爱好产生一点创造性的想法。」WhyComboNadir 用玩笑表达了另一端立场:「LLM 极大扩展了我的认知能力,我现在是一支军队的将军,而不是一个士兵……好了我得走了,我要推着我的车去杂货店(免得忘了怎么走路),我和我的巨大小腿肌几小时后回来。」dataviz1000 类比说数学家和物理学家不会为了不生疏而放下计算机手算一个 10000×10000 矩阵的逆,「正如我们不再写机器码,我们正在向更高的抽象层移动」。estebarb 则援引了一篇 arXiv 论文(2509.21972v1)里的论点:当学生把这些输出当成自己推理和批判性投入的替代品时,学习过程从根本上被破坏了;真正的学习需要主动构建意义、整合知识和反思性投入,这些过程无法通过被动消费「语法正确但语义空洞」的回应来发生。

关于「LLM 是不是已经比你写得好」的支线争论:ozgrakkurt 抛出「如果你写不出比 LLM 更好的代码,你就完蛋了,去读点书或文档吧」,引出一长串对线。jdw64 认为大多数人确实写不过 LLM,并展开了关于「博士级代码」的长篇论述,被 nolist_policy 吐槽「你看过研究论文的代码吗」,jdw64 澄清自己说的是算法层面的建模难度而非代码卫生,并援引《人月神话》的本质复杂度/偶然复杂度之分。maccard 给出了一个很扎实的提醒:「记住,LLM 在你不懂的领域里写出的代码质量,跟它在你懂的领域里一样;你只能评判你懂的那部分。」baq 做出激进预测(前沿 LLM 在 CRUD 任务上已经好过 95% 的开发者,到年底会覆盖 95% 的小众领域),gwynforthewyn 反驳说这种鼓点已经响了好几年但他没见到兑现:「前沿模型能把简单的东西大致做对,但没法维护一个小代码库让它在多次变更后仍然行为正确——上下文一多,测试被改写成什么都不检查,操作相似数据的功能被写出发散的实现。自己玩玩没问题,但把这个误当成维护良好的代码库去卖产品的 vibe coder 会被狠狠教训。」

关于「个人项目的乐趣」的共鸣:jspdown 的自白引起不少人共鸣:他现在空闲时间前所未有地少,深入做一个副项目(哪怕最后没结果)本是他的爱好,时间稀缺让这件事变得令人沮丧,于是他掉进陷阱——用 LLM 在极少时间里做更多事,「你得到多巴胺、得到成就感,但认知负债大到活动本身几乎失去意义。这么干了几个月,我甚至不确定这是不是对时间的好用法,长期来看满足感很少」。K0nserv 走了另一条路:他专门开了一个刻意不使用 agentic coding 的项目,只用 LLM 做研究和学习,代码全部手写,目的是维持自己几十年积累的「品味」;Claude 让他知道了「练习曲」(Étude)这个概念,于是他把这个项目就叫作练习曲项目。