智能体时代重新定义好代码:从人读优先到人机协同
大概两年前我在一次代码评审里被一位非常较真的同事追着问你这块逻辑能不能再抽象一层那个问题本身没毛病但我改了三个版本都没让他满意。后来我索性把那段代码全部展开、平铺、写成“一个函数只干一件事”的样子他看完点了点头说这样好懂。有意思的是同样是这段逻辑我后来丢给了AI编程助手去重构它给出的方案居然和“被批评的那个优雅抽象版本”出奇地一致。这件事我琢磨了很久。当时只是觉得人和AI的审美不同直到最近看到某位资深工程师在分享里提出“智能体写代码时代需要更新对好代码的定义”我才意识到这不是审美差异而是评价好代码的整个坐标系正在发生变化。如果你还在用五年前的标准去要求今天的代码或者你正在为AI工具产生的庞大代码库焦头烂额这篇内容可能会给你一些不一样的思路。1. 为什么“好代码”的标准必须跟着变1.1 旧标准是给“人读”优化的新标准要兼顾“AI读”以前我们谈好代码核心出发点始终是“给人看”。代码写出来要被同事评审、要被后来的维护者阅读、要在半夜被人翻出来改bug。所以在长期工程实践里我们形成了几个默认的黄金标准可读性强、职责单一、命名表意、注释精准、模块化边界清晰。这套标准本身没有问题但它隐含了一个前提——代码的主要消费者是“人脑”。人脑工作记忆容量有限所以我们才需要把上下文控制在小范围内用函数名、变量名、文件结构来降低认知负担。可如今代码的生成方式变了。越来越多的代码由智能体AI编程助手、自动生成脚本产出也越来越多代码不是给人读的而是直接交给另一个智能体去分析、重构、修复。也就是说代码的消费者从“人”扩展到了“AI”。AI阅读代码的方式和人完全不同它不靠逐行盯屏幕而是靠把整个代码库切片、embedding化、按语义检索。它喜欢自包含的、边界明确的、依赖声明清晰的代码而不是一句看起来方便但隐含跨模块状态的语法糖。在这种情况下旧标准就显得力不从心了。一个在人类眼里“干净利落”的抽象在AI眼里可能就是一个需要翻越很多文件才能找齐信息的黑盒。而一个在人看来“啰嗦冗余”的写法反而可能让AI快速定位逻辑、降低推理错误率。1.2 从“人效优先”到“人机协同效率优先”旧标准的底层逻辑是最大化“人的理解效率”而新标准的底层逻辑应该是最大化“人智能体”的整体协作效率。这个转变不是口号而是由开发流程的真实变化推动的。现在很多团队的开发流程已经变成人下达意图 → AI生成初稿 → 人审查修改 → AI补充测试 → 人确认合并。在这个流程里代码不再只承担“表达设计”的功能它还是人机对话的产物和中间载体。因此评价一段代码好不好不能只看“人是否容易读懂”还要看它是否容易让AI在下一步操作中不出错地修改、扩展、测试。这一点在自动化测试的生成上体现得最明显。一段代码如果函数颗粒度适中、入参出参明确、副作用被隔离AI自动生成单测的成功率会明显更高。反之一段高度依赖外部状态、到处用全局变量、喜欢隐式传递上下文的代码人类读起来也许觉得流畅AI却很难生成靠谱的测试用例。我们团队后来做了一个内部实验把一段经典的老项目代码交给AI加测试结果一大批case因为变量作用域跨模块、函数隐式依赖外部数据而无法自动生成。后来我们简单重构了一下把隐式依赖改成显式参数传递AI生成的测试质量和覆盖率立刻上了一个台阶。那段重构后的代码在人类阅读体验上略微“啰嗦”了一点但人机协同效率显著提升。1.3 旧质量指标在大模型时代的局限还有一个被忽视的问题是传统的代码质量指标比如圈复杂度、重复率、注释密度在大模型时代已经不够用了。指标是静态的而大模型在理解和生成代码时是动态的、语义化的。一个静态指标上完美的代码可能在大模型语义检索时却很难被定位一段带点“坏味道”的代码反而因为关键词丰富而被AI顺利理解和修改。这不是说旧指标没用而是说在智能体时代我们需要给代码质量增加一些新的维度比如“AI可检索性”“AI可理解性”“AI可修改性”。后面我会展开讲这些维度具体意味着什么。2. 重新定义“可读性”语义密度比注释数量更有用2.1 注释的新角色从解释逻辑到指导AI以前写注释主要为了给人解释“这里为什么这么写”。很多规范还强调“注释不要复述代码”“好代码不需要注释”。但在智能体时代注释的角色正在变化。AI读取代码时注释是重要的语义锚点。一段没有任何注释的代码AI只能从代码结构反推意图不仅速度慢还容易跑偏。而一段包含明确意图说明的注释可以大幅提高AI理解的准确率。我测试过同一个函数一个版本只有代码没有注释让AI做代码摘要它写出来的内容经常遗漏关键边界条件另一个版本在函数开头加了三行注释指明输入输出和核心边界条件AI的摘要质量明显提升。所以现在的建议是注释不要写“做了什么”那是代码自己表达的而要写“为什么这么做”和“什么情况下不这么做”。这恰好是AI最难从代码本身推断出来的信息也是人最需要留下的知识沉淀。2.2 命名不可读但语义强相关是AI时代的加分项传统规范说变量名要“清晰可读”比如 count、is_ready、user_profile这没问题。但在AI生成代码的语境下经常会出现像result_data_array、temp_obj_3这种名字。过去你肯定会在评审里打回去但我的实测体会是这类命名只要和周边代码形成足够强的语义关联AI阅读时并不吃力甚至可以更快地完成上下文匹配。比如某个回调函数里一个叫data2的变量如果前后代码、注释、函数名都指向某一项配置数据AI结合上下文理解它比一个叫configData但实际来源不明的变量还要准确。命名的作用是“降低认知摩擦”而不是“保证字面优雅”。在AI参与代码阅读的场景下稳定的、上下文强关联的命名比孤立漂亮的命名更有价值。不过这不代表我们回到无所谓命名的时代。恰恰相反命名的重要性更高了只是标准变了命名要与周边代码、注释、数据结构名称形成一致语义网而不是仅仅自身表意准确。2.3 代码结构与AI理解力的实测对照我先后做过几轮对比实验想看看什么样的代码结构最容易被AI正确理解和修改。总结下来有三个明显偏好短函数、长文件、顺序结构AI在读取长文件时能一次性拿到更多上下文避免跨文件拼接信息。这和人类喜欢“短文件、多文件分模块”的习惯正好相反。显式传参优于隐式状态AI推断显式传入的实参类型、范围和含义比推断函数外部全局变量的当前值容易太多。一个函数如果完全不引用全局变量AI理解它的正确率会高很多。分支逻辑扁平化优于嵌套收敛AI对“并列if”的理解优于“多层嵌套if”。因为并列结构在语义检索时更容易被切片嵌套结构则容易让AI丢失内部层级。这不是说我们要把项目全改成单文件长函数而是说在权衡结构时要考虑“AI读取是否顺畅”这个新因素。3. 新“好代码”的四维评价模型3.1 维度一AI可检索性——代码库越大越关键AI要从一个大代码库里找到它需要修改的目标第一步是检索。检索依赖语义相似度匹配而语义相似度来自变量名、函数名、注释、字符串常量的组合。提升AI可检索性的方法很简单用词要和领域术语一致别造黑话。比如金融项目里用户叫“借款人”状态叫“逾期”代码里就应该有 borrower、overdue 这样的词。如果用p1、st这种缩写人类看多了能记住AI检索时却会失效因为它在海量语料里学到的“借款人”对应的是 borrower不是 p1。另外常量字符串也很重要。比如错误状态码多写const OVERDUE_STATUS 200并在注释里说明“200 已逾期”AI读起来会非常顺只写一个魔法数字200扔在那里AI不仅看不懂还会在生成代码时把这个数字的含义猜错。3.2 维度二AI可修改性——改动波及范围越小越好代码是拿来改的而AI改代码时的风险比人更大因为它不像人一样对全局了然于心。大家应该都体会过AI改一个函数时为了防止漏掉调用方它倾向于把小函数整个重写或者在函数里加一大段兼容逻辑导致代码膨胀。这是因为它无法确定改动影响范围。解决的办法就是尽量缩小单个函数的职责边界让一个函数的改动不需要跨文件同步调整。不变量要写进类型或断言而不是靠调用方约定。请求和响应模型尽量独立不要复用那个“万能DTO”之类的坑爹设计。用一个最简单的例子某个函数原来是返回布尔值后来要改成返回错误码。如果函数签名是saveUser(user): booleanAI在修改时很容易把调用方一并改坏因为它要追踪所有if(saveUser(...))的位置。但如果签名是saveUser(user): SaveResultSaveResult里有isOk和code两个字段AI修改时只需要改函数内部构造调用方几乎不受影响改动波及范围自然小。3.3 维度三AI可测试性——让自动生成测试不再“猜”AI生成单元测试是未来增量的重要产能。但很多代码AI根本没法下手写测试因为依赖外部服务、内部私有状态、时间函数、随机数等不可控因素太多。过去的经验是把这些不可控因素“藏起来”比如在函数内部偷偷 new 一个时间或者直接调全局的服务单例。这在人读代码时觉得“封装度高”但AI生成测试时完全抓瞎。新标准要求我们在设计时就把可测性当一等公民时间要注入、HTTP请求要抽象、随机数要传入生成器、外部服务依赖要显式构造注入。这些改动在人看来增加了参数数量有点啰嗦但换来的是AI可以自动生成高质量的mock然后一键补出单测。实测下来处理过的代码AI自动测试生成成功率从大概30%提升到了80%以上这个提升非常可观。3.4 维度四AI可替换性——面向未来重构的优雅还有一点是面向未来的代码不仅是给当前AI用的将来还会有更强的智能体接手。如果一段代码和自己的描述文档在语义上脱节未来的AI在理解它时就得从头推理。所以我们在代码里留下的语义痕迹越多、越准确未来AI越容易接管。这个维度很像“给AI铺路”变量名用领域词、注释保留决策原因、错误码有统一字典、关键设计有简短文档。这些都不是给现在的人看的而是给未来的AI看的。你可以把它理解为“代码的长期投资”回报周期很长但一旦技术栈大幅迭代这部分资产价值会被放大。4. 实操环节用一套可复制的流程把老代码改造成“AI友好”4.1 改造前的基础评估拿到一个老项目怎么判断要不要改造成AI友好先看几个快速指标有没有大量使用魔法数字、魔法字符串函数是不是普遍超过50行并且伴随三层以上嵌套是否存在隐式全局状态、单例依赖、隐藏的时序耦合单元测试覆盖率是不是长期低于30%团队是否已经在日常使用AI编程工具来生成新代码如果五个指标命中三个我建议优先做一轮“面向AI的友好化改造”。这和工作量大小没关系关键在于奖励长期维护效率。4.2 实际改造步骤一个订单状态模块的演示用之前处理过的一个订单状态模块当例子。原代码的问题非常典型状态码散落、合法状态迁移靠人脑记住、两个相邻模块通过全局单例共享订单对象。改造分四步走。第一步把状态码收敛到一个文件里定义成枚举或常量对象并配上含义注释。这样AI检索时能找到统一的位置不需要从十几个文件里猜状态码的含义。const OrderStatus { PENDING_PAY: 10, PAYED: 20, SHIPPED: 30, FINISHED: 40, CANCELED: 50 }注释补充一句每个状态的使用场景AI读起来就能直接形成概念映射。第二步把原来散布在各模块里的状态迁移判断收敛到一张状态迁移表里。用数据表驱动逻辑人看着直观AI理解起来也轻松因为它只需要根据起点状态和目标状态查表决定是否合法不需要理解散落各处的条件判断。第三步把隐式共享的单例改成显式依赖。原模块里订单对象是全局共享的改造后改成构造函数注入函数的副作用也随之被隔离。这样代码看起来参数变多了但每个函数的输入输出都不再依赖外部可变状态。第四步补上针对状态迁移表的单元测试。数据表驱动状态下AI生成测试用例很容易遍历所有迁移组合覆盖率一下子就能上去。4.3 改造过程中踩到的坑这个改造过程里我踩过几个坑在这里记一下。第一个坑是“过度收敛”。一开始我把所有状态相关逻辑全塞进一张表里结果发现任何业务判断都要绕道表查询代码反而变复杂了。后来才想明白表驱动应该用在校验合法迁移的场合不能滥用其他业务判断该写if还是写if。第二个坑是“注释写太多”。有些文件改造后注释比代码还长AI读取时反而被干扰因为注释里的非关键信息加大了噪声。正确的做法是只留两类注释一类是“意图解释”另一类是“边界提醒”。描述性的、感慨性的、记录性的注释一律删掉。第三个坑是“改造破坏了原本的运行时行为”。因为显式依赖替代共享单例时如果初始化顺序没有控制好会导致部分逻辑提前拿到空数据。改造前一定要把现有测试覆盖率补一下至少保住核心路径不然你很难判断行为变化是优化还是破坏。5. 代码评审规则正在重塑5.1 评审清单从“人味”检查转向“人机协同”检查以前的代码评审清单会包含命名是否清晰、函数是否足够短、注释是否必要、是否有重复代码等。现在我认为应该在这个基础上增加一组面向AI时代的检查项。下面这份清单是我在小范围交流之后沉淀出来的分享给大家参考状态和常量是否有唯一出处AI是否能通过检索找到定义函数的输入输出是否显式副作用是否被隔离是否存在无法被AI自动测试覆盖的外部依赖代码是否自带语义锚点领域词、意图注释、边界注释如果让AI来修改这个函数它的影响范围是否可控评审时不用所有项都通过但要清楚地知道每一项的取舍。旧标准适合人工逐行阅读的场合新标准适合人机协作的场合。两边不可能完全统一取舍时先把场景讲清楚。5.2 人与AI的评审分工人工主逻辑AI主一致性在评审这件事上人和AI是可以分层的。我的做法是AI负责检查一致性——比如命名是否符合项目规范、状态码是否都定义了、是否存在重复逻辑、是否缺少测试人负责审查逻辑意图——比如这个业务规则对不对、这个抽象是否真正反映了领域模型、这次改动的影响范围是否被理解。这种分工成立的逻辑是AI擅长在长代码库里做全面扫描和比对不太会疲劳也不容易漏掉重复的模式。人擅长判断意图和业务语义能看出AI审查不出来的隐含设计意图。两者组合比单靠人或者单靠AI都更高效。5.3 “一次说清”和“点到为止”的边界AI时代的评审还涉及一个重要转向评论密度。以前好的评审是“说得越多越负责”现在评审反而要点到为止避免给AI引入过多噪音。为什么因为AI编程工具会读取历史评论来分析偏好。评审里如果塞满了风格偏好性的评论AI会照单全收甚至过度吸收导致它把所有代码都改得“很评审味”——千人一面失去项目本身的个性。而那些真正指出语义错误的评论AI又会拼命学习。所以评审和AI互动的过程本身就是一种模型调教把每一句话当成训练数据来写才能引导AI往真正的质量方向走。6. 常见问题与排查技巧实录6.1 AI频繁绕开抽象层直接修改底层逻辑这个问题非常常见。AI应该通过函数接口修改逻辑但它经常直接重写底层实现一场重构下来到处是AI的印记。排查思路给关键接口加上显式的类型约束让AI很难绕过在代码里强调“对外方法优先于内部实现”有条件的项目可以在CI里跑静态检查识别那些带any或弱类型的大改及时拦截。6.2 代码里出现大量风格不同、上下文断裂的片段多个AI会话分别生成的代码拼在一起会出现一种“缝合怪”现象这段像A模型写的那段像B模型写的注释风格都不一样。解决办法是建立“代码风格说明书”把命名规则、注释风格、错误处理偏好写清楚然后在每个AI会话开始前固定注入风格说明。经验之谈是说明越短越具体AI遵守得越好。长篇大论它反而会摘取一部分执行。6.3 测试用例表面通过但逻辑空洞AI生成的测试经常是“美丽的花架子”断言数量和覆盖率曲线很漂亮但关键分支没有真正验证。原因在于它没有理解前置条件只会照着代码表面路径生成。破法是强调分支覆盖的同时让AI结合注释里的边界条件生成测试对核心业务方法的测试要求引入真实结构的mock数据不要全部用null和空对象。说白了让AI写测试的设计意图要更有约束它才能测出真正的效果。6.4 AI修改导致行为回归静默吞掉错误这个是最危险的AI改完代码后异常路径被吞掉错误不再向外暴露测试居然还是全绿。应对方案约定所有网络请求、IO操作、状态迁移的失败路径都明确返回错误禁止空catch代码审查时专门看AI新增的代码里有没有被掩盖的错误处理逻辑单测里补充“断言确实抛错”的用例。6.5 团队约定写了很多AI依然我行我素约定如果不能被执行等于没有。如果你发现写了规范文档但AI不遵守大概率是因为规范文档太泛、太理论化了。要写“可被AI执行的规则”而不是“人类理解的建议”。比如不要写“命名要语义化”而要写“所有状态相关变量必须以 Status 结尾”不要写“错误处理要规范”而要写“每个可能抛异常的调用必须至少有一个显式catch并返回错误结果”。规则越可验证AI越容易遵守。7. 后面还能往哪些方向延展代码标准的更新落到底层其实是工程的范式和协作模型在改变。未来值得关注的方向我粗浅列几个第一个方向是“AI可解释性的代码表达”。现在的很多设计模式其实是在向“人类读者”解释意图未来会出现专门向“AI读者”解释意图的代码表达方式可能是对现有模式的组合变化也可能是新的元描述体系。第二个方向是“基于AI反馈的代码质量门禁”。路线大致是让AI对每次改动的可检索性、可修改性、可测试性做自评和人工评审合并成统一的质量卡口落地价值应该会很大。第三个方向是“代码语义资产化”。代码里沉淀出的领域词、限制条件、设计决策未来可能直接被提取成结构化文档喂给AI做更准确的语义理解。这相当于把代码库变成可读的语义知识库。最后提醒一句别急着把现有代码全部推倒重写。AI友好化改造更适合从新需求、新模块、老代码的核心路径这三种地方切入渐进式推进。一次改动范围内没做到AI友好其实影响也不大它是一点点积累的。这段讨论给我最大的启发是好代码没有消失只是它的标准从一个坐标系平移到了另一个坐标系。以前我们问“这段代码人看着是否舒服”以后我们得问“这段代码人和AI协作起来是否顺畅”。两套标准不矛盾但确实需要并有意识地并行。愿你我都别被旧坐标系困住。