
AI 把写代码变便宜之后工程的分水岭变成了「读得懂」最近一年AI把写代码这件事的门槛和成本直接打到了地板价。无论是ChatGPT、Claude还是各种国产模型你说个需求它给你生成一版代码从零到能跑往往只要几分钟。很多团队和个人开发者都在享受这种“代码自由”。但讲句实话代码变便宜了麻烦才刚刚开始。写出来是一回事读不读得懂是另一回事。我见过太多项目里堆满了AI生成的“天书”——变量名叫 data、temp、result函数几百行不分职责注释全是“// 遍历”这种废话三个月后连写它的人都不知道这段逻辑在干嘛。软件工程这么多年兜兜转转核心矛盾其实一直没变机器只关心代码能不能运行人得关心代码能不能被理解。AI时代写代码的速度不再是稀缺能力真正拉开工程师差距的是你写出来的东西别人读不读得懂三个月后的自己读不读得懂。这篇文章就用我踩过的一些坑和实操经验聊聊为什么读得懂成了工程领域真正的分水岭以及怎么把可读性这件事落到代码里。1. 当生成代码变得免费软件工程的成本中心彻底转移1.1 成本结构变化从“编码工时”到“理解工时”先看一个很直观的变化。以前接一个需求团队第一反应是“谁来写、写多久”工时估得明明白白。现在很多团队接需求第一反应是“让AI先出一版”生成代码的边际成本几乎为零。我记得前两年帮朋友项目做技术评审一个接口从零到一说要半天现在用AI辅助十分钟能出完整的一版。但有意思的是这一版代码拿到手之后团队小伙伴要花四十分钟去梳理它到底做了什么有没有边界问题数据流和异常处理在哪个位置。写代码的时间被人均摊到了“读懂代码”上了。传统软件工程把成本压在“写”上需求分析、设计、编码、测试编码占大头。现实世界是代码写完之后会活很久被很多人反复阅读和修改。根据我自己的经验开发者在IDE里真正敲字符的时间不到工作时间的两成剩下八成时间都在读代码、查逻辑、找上下文。AI入场之后这个比例更夸张了——敲字符的部分直接被抽走读代码占比更高理解成本变成了团队最大的隐性支出。这个成本以前不是没有而是被“写得慢”遮住了。现在写快了这个变量被AI抽走剩下来的“理解成本”就浮出水面了。代码总行数暴涨AI生成的代码风格五花八门质量参差不齐。读得懂、读得快的代码才是真正能让你快速迭代的资产。读不懂的代码看起来完成了功能实际上是在给团队背上技术债。我去年参与过一个中后台项目业务方要求两个星期内上线一个权限配置模块研发团队用了新的AI辅助工具代码写得飞快一周就调通了。但等第二期迭代要加一个“按角色批量导入权限”的功能时大家发现原代码里权限判断散落在一百多行工具函数里改一处崩三处最后只能推倒重写。这个例子很典型写快了读不懂等于把成本从当下挪到了未来而且未来的利率高得吓人。1.2 谁在承担“读懂”的成本是你未来的自己和同事很多人有个错觉觉得自己写的代码只有自己能看懂。但哪怕只隔三个月你自己回头看也可能变成“陌生人”。我见过太多开发者在重构自己的旧代码时像看别人写的一样。更别提接手别人代码时的那种窒息感变量名叫a、b、data函数叫handle、doSomething注释就一行“// 逻辑”状态全靠猜。这里有一个核心的观点代码有两个读者一个是你的同事一个是三个月后的你。机器只关心代码能不能跑人得关心代码能不能被理解。AI时代写代码越来越便宜读代码的却永远是Human。想让自己和团队不被代码拖死就得把“读得懂”当成一等公民来设计。“读得懂”不光是代码本身还包括整个上下文。为什么要这么写这个分支为什么存在这个判断条件是哪来的如果一个新人能在没有你陪伴的情况下顺着模块的脉络说清楚业务流转这份代码的可读性就及格了。我在Code Review里最常问的一句话是“这个函数为什么要接收六个参数”多数情况下写的人自己也支支吾吾。这不是记忆力的问题而是写的时候根本没想清楚边界和职责。AI生成的代码常常“看起来很有道理”但它的“道理”是统计出来的不是你基于业务逻辑推导出来的所以你读起来会有一种微妙的不适你无法解释它为什么这么做。这在可读性上是个致命弱点。因为一旦你无法解释就无法修改更无法信任。1.3 可读性差的代码在AI时代会被指数级放大如果说以前可读性差是个人风格问题那么AI时代它就是系统性问题。AI模型在预训练阶段对代码做了大量统计学习它天然倾向于产生“典型”的、通用化的代码模式但一旦遇到特殊的团队规范、领域模型或业务流它就会生成看起来很专业但逻辑很拧巴的东西。多AI协作或反复提示之后代码里可能混入多种风格一会儿是函数式一会儿是面向对象一会儿又是命令式可读性就更不用说了。更麻烦的是AI模型生成代码的高效让团队倾向于接受“一次性代码”。反正下一版让AI再生成一个就是了。这种心态蔓延之后项目里会积累大量的“一次性”代码堆没有模块边界、没有层次、没有语义。等到某个功能突然要扩展或者出线上问题时整个仓库就变成了一座巨大的、脆弱的纸牌屋。我见过一个团队三个月里用AI“堆”完了一个项目上线之后所有bug都集中在几段AI生成的大型工具函数里——几千行集中在node_modules边缘逻辑里测试覆盖不上人不敢动AI也修不干净。最后团队不得不再写一个适配层把烂代码包起来。这套路看起来省事其实绕了远路。所以我说AI把写代码变便宜之后分水岭变成了读得懂这不是说说而是血泪教训堆出来的。2. “读得懂”到底是什么拆解可读性的核心构成2.1 命名让你的代码像叙事文而不是谜语读代码读什么第一眼看到的是命名。命名是代码可读性的脸面也是最容易被AI生成代码忽略的地方。AI模型生成的变量名通常是英文直译或者占位符比如data、temp、result、flag、promise这类名字在局部范围勉强能用一旦跨模块就完全丢失语义。我给自己定了一个规矩如果一个变量名需要读注释才能懂那就应该改名字。一个好名字应该自带上下文让看代码的人不用翻上去找定义。举一个生活化的例子你写一个“更新订单状态”的方法如果变量叫result读的人只能猜它是更新结果、返回结果还是查询结果。但如果叫updatedOrderRecords或者orderStatusChangeResult读的人一目了然。命名不是诗不需要优雅但必须准确。再强调一次命名是给下一个读代码的人看的不是给解释器看的。AI生成代码的时候我一般会在提示词里显式要求“使用语义化变量名不要缩写不要用data/temp一类的占位名”。实测下来模型在大部分场景能听进去但不稳定所以人工审查仍然必不可少。别指望一次提示就能贯彻到底最好把可读性要求写进团队的代码规范再用工具强制检查比如eslint的命名规则。2.2 结构小函数、单一职责、UI和逻辑分离代码可读性的第二个核心是结构。结构清晰意味着读者可以先把系统看成一个一个的小积木再根据业务组装起来。AI生成代码经常犯的毛病是把一大堆逻辑揉进一个函数里参数越加越多if-else层层嵌套循环里面套回调回调里再套Promise。这种结构机器能跑人却读起来崩溃。小函数原则是我反复强调的。函数保持在一个屏幕能看完的长度最好控制在20行以内。每个函数只做一件事函数名就是这件事的描述。如果函数干了好几件事那就拆。拆完之后你会发现函数的层级极其清楚出错时也能快速定位——线索就在函数名里。单一职责原则同理。举一个我实际改进的例子一个AI生成的“发送通知”函数里面包含了查用户表、判断通知类型、拼模板、调短信API、记录日志、失败重试六个动作。我拆成七个函数getUserById、shouldNotify、buildMessage、sendSms、logNotification、retryLater外加一个sendNotification做编排。拆完以后新来的同事两分钟就能看懂整条链路。这就是结构的力量。另外UI代码和业务逻辑的分离也是可读性的重灾区。AI生成前端代码特别喜欢把业务判断直接怼进模板里三行状态运算、两行权限判断、一个数组map全塞在return里。我在Code Review时看到这类代码一般直接打回。判断逻辑不放在render之外测试也没法写可读性无从谈起。2.3 注释写“为什么”而不是“是什么”关于注释很多AI生成工具会自动给每行代码加注释看起来非常贴心其实大多是无意义的废话。比如“// 遍历数组”“// 调用接口”读者又不是瞎的看代码就知道在遍历。真正的注释应该解释“为什么这行代码存在”“为什么用这种写法而不是另一种”“为什么这里是1而不是-1”因为这些决策依据和领域信息从代码本身是看不出来的。我总结了一个注释原则好的注释是“决策录音机”。你写注释时应该记下自己在这个地方做的关键权衡和一个个坑。比如“这里用双重循环而不是hash因为数据量小于100且可读性更直观”“这个偏移量是后端老接口的历史包袱新接口不用管”这类注释能让后来的维护者节省大量试错时间。AI生成注释的时候我通常会让模型“只给核心逻辑写注释解释为什么不要逐行注释”。实际操作中模型难以完全区分“为什么”和“是什么”所以最终注释质量还是要靠人把关。宁可没有注释也不要机器味的假注释——假注释比没有更糟因为它让人误以为理解了上下文。2.4 提交记录把项目当成有章节的书很多人聊代码可读性只盯着源代码文件却忘了另一个层面提交记录。git log其实是一个项目最重要、最不会被删掉的“文档”它记录了每一段代码为什么进来的历史。但AI时代提交记录的可读性正在下降。很多开发者的提交信息是一句“fix bug”“update”更有甚者直接写“AI生成”。三个月后你想回溯一个异常提交完全找不到线索。我建议团队推行“描述式提交信息”每次提交标题写清楚“改了哪个模块、做了什么、为什么做”正文里可以粘贴AI生成代码时的prompt摘要方便追溯当时的上下文。AI生成的代码尤其需要这一步因为你很难从代码本身推导出它为什么写了一个奇怪的判断条件但如果prompt里记录了“用户反馈某场景下订单重复创建”后续维护者就能理解那段防御逻辑的来源。写提交记录这件事就像一个项目的大纲它让读者不用通读所有代码也能把握整体脉络。对一个大仓库来说可读性不只是字节层面的“读代码”更是历史层面的“读变更”。把提交记录整理好等于给项目写好了目录。3. 实操让AI生成的代码具备可读性的方法论3.1 通用指令设计把可读性写进AI的约束条件想让AI写出可读性好的代码最有效的方法是在提示词层面就把要求讲清楚而不是生成之后再花大力气重构。我整理了一套通用指令模板历史项目实测下来很稳分享给你们“请用语义化变量名避免缩写和占位名。每个函数控制在30行内保持单一职责。把复杂条件抽取为独立函数并给出函数名。不要逐行注释只为核心业务逻辑添加短注释解释为什么而不是是什么。保持代码风格与现有文件一致。”一个关键细节把“保持一致”这个要求放在提示词里非常有用AI模型会参考当前文件的风格生成。如果项目里已经有编码规范直接把规范文件路径或关键片段粘进prompt里效果更好。实测下来加入这种提示词后生成的代码可读性评分会有明显提升虽然不可能完全达标但至少减少了后续人工整理的工作量。另外我会把“多轮生成”也利用起来第一轮让AI出一个能跑的骨架第二轮要求“重构这段代码抽取函数、重命名变量、添加必要注释”。很多开发者不知道AI的能力边界在于上下文你把它当作一个“开卷面试者”在prompt里把规范和约束写清楚它就能生成更符合预期的结果。3.2 生成后的“五分钟整理”人机协作的关键一环很多AI编程流程的问题在于代码生成完就直接提交跳过人工整理。这是最大的坑。我的建议是每次生成后拿出五到十分钟做一个“整理仪式”。具体动作有三个第一通读一遍生成代码确定函数边界把过长函数拆掉第二重新命名不符合团队规范的变量和函数第三删除或改写AI添加的垃圾注释补上必要的“为什么”注释。这五分钟看起来浪费时间实际是在给未来节省大量时间。因为代码一旦提交进仓库它就会开始腐蚀每一个读它的人。可读性差的代码会在接下来的每一次改动里让你多花时间这五到十分钟的投入是软件工程里回报率最高的操作之一。我在写过的一个AI辅助项目中给团队定了一个约定AI生成的代码必须经过“五分钟整理”才能提交。一开始大家觉得麻烦但两周之后都自动接受了。因为每次改代码时大家发现“原来这段代码是自己整理的所以逻辑非常清晰”这种正反馈比任何规定都有效。3.3 Code Review 与可读性检查清单Code Review是可读性的最后一道防线。AI时代我不建议完全信任任何AI模型。无论它生成的代码看起来多合理都要过一遍人工评审。我给团队整理了一份“可读性检查清单”做评审时逐项打勾好用得很命名是否语义化是否存在无意义变量名函数是否超过30行是否违反单一职责是否存在过深的嵌套超过3层能否提前返回或抽取注释是否解释了“为什么”而不是“是什么”是否包含了死代码、重复逻辑UI和业务逻辑是否分离提交信息是否描述了变更原因这些清单项看起来基础但AI时代重新变得重要起来。因为AI生成的代码不是“人写的”它不会像资深工程师一样天然具备对可读性的本能。评审时需要注意不要因为AI代码“看起来全对”就放松标准只要有一项不过就打回让开发者整理或重新生成。我自己在评审时还会特别留意“AI典型问题”的三个信号过度封装为了追求抽象搞出了层层包装、逻辑分布极端要么全部塞进一个函数要么拆成碎片但毫无层次、带上了混淆的通用模式比如在一个纯函数里做IO、在一个Builder里隐身调用全局状态。这三个信号一旦出现说明这段代码大概率不是人类设计的要打回重审。3.4 多AI协作下的可读性风险现在很多人开始尝试多AI协作比如用一个AI做需求分析、一个AI写业务代码、一个AI做单元测试、一个AI做评审。听起来效率高但可读性风险也更高。不同AI模型的思维模式、代码风格、上下文理解差异都很大它们协作产出的代码往往更难以让人理解因为你无法预测谁的“思路”被采纳了。一个可行的策略是在多AI协作流程里指定一个“代码风格总管”通常用同一模型或相同的规范前缀来统一输出。无论哪个AI伙伴生成了内容在最终合入之前都要经过同一套格式化和规范性检查。另一个策略是把可读性检查也交给AI但要设置黑名单规则比如“禁止返回包含data/temp变量的代码”“禁止超过50行的函数”用明确的负向约束替代模糊的“写好一点”。我在实际项目中试过让AI做评审它能挑出很多低级错误但它的评审逻辑并不稳定容易“看走眼”比如对同一个函数两次评审给出不同意见。所以AI评审只能当辅助必须有人类兜底。多AI协作听起来酷但真正的分水岭还是人能否把整个流程hold住。4. 常见问题与排查技巧实录4.1 AI生成代码的典型可读性问题我把过去一年多AI辅助开发遇到的典型可读性问题整理成了一个速查表方便大家对照排查问题表现处理方案变量名无意义data、temp、result满天飞提示词加命名约束人工重命名函数超长单个函数几百行职责混杂按单一职责拆分抽取子函数注释废话逐行“// 赋值”“// 循环”删除废话注释只留“为什么”注释逻辑散落业务判断散在视图层/调用处提取为独立函数或服务层重复代码相似逻辑出现多份参数略不同抽取公共函数但注意别过度抽象分支过深if-else嵌套超3层用卫语句提前返回或策略模式这些问题的根源在于AI模型对“代码的可读性”没有人类那种同理心它只负责“写得像”不负责“读得懂”。开发者要做的不是在生成后绝望而是有意识地用规范、模板、Code Review去约束它。4.2 可读性冲突性能优化和可读性打架时怎么办很多工程师会纠结为了性能写出的位运算、缓存逻辑、惰性求值可读性很差怎么办我的原则是可读性和性能不是非此即彼大多数情况下它们可以共存。把性能相关的复杂逻辑封装在独立函数里给它写一个清晰的命名和一段“为什么”注释调用方保持可读性就两全了。比如一个用了大量位运算的哈希映射函数你可以把它命名为buildTinyHash并且在注释里写明“采用位运算是因为数据量千万级普通对象会爆内存”。如果实在冲突我建议可读性优先性能后置优化。现代编译器、解释器、运行时都很聪明大部分可读性差的“性能优化”其实是过早优化。只有性能成为真实瓶颈并且profile证明了热点所在才值得用更巧妙的写法去替换。替换时务必写清楚“为什么这么做”这本身就是可读性的体现。还有一个容易踩的坑AI生成代码经常在“看起来高性能”和“实际高性能”之间制造假象。比如它可能为了“性能”用了一个复杂的数据结构但实际上数据量只有几百条完全没必要。评审时一定要带着Profile的精神看待AI的优化动作别被它绕晕。4.3 老代码重构如何逐步把“谜语”变成“故事”如果项目里已经积累了大量AI生成或历史遗留的低可读性代码怎么开展重构我的经验是“不要一次推倒重来”那是最危险的。正确做法是“逐步翻译”。第一步挑出最影响团队效率的三个模块优先处理第二步只做“可读性重构”不混入业务变更避免范围爆炸第三步每个模块重构完成后补充测试作为安全网再交付给团队。具体的重构手法有个小技巧叫“命名的蝴蝶效应”先从一个关键函数改名开始比如把handleUsers改成syncUsersFromRemoteProvider改完你会发现函数体里很多局部变量和子调用也随之变得清晰了。命名是整个重构的“锚点”先立好锚点再顺着清晰度往下走。另一个技巧是用“提交记录当路线图”。重构前先看看git log里那段代码的历史提交把每次commit的原因整理出来你就知道哪些逻辑是历史包袱、哪些是必要防护。把“为什么”找回来可读性自然就恢复了。这个过程挺费时间但它是团队走向良性代码生态的必经之路。最后提一句别把AI当成可读性的救世主也别把它当成洪水猛兽。工具永远放大使用者的习惯如果你本来就注重可读性AI能帮你写得更快更稳如果你本来就堆烂代码AI只会让烂代码来得更快。真正要把分水岭踩在脚下还是那句老话写出的人要像讲故事一样写代码读代码的人要像读小说一样读代码。AI变便宜之后便宜的不只是代码还有每个人的耐心。谁能保住耐心谁就过了分水岭。