如何度量代码的邋遢程度
大语言模型(LLMs)生成代码的能力已近乎完美,但故事远未结束。代码形式上正确,不代表它没有引入冗余抽象、重复代码,或是整体决策失当。这并非什么突破性发现——大多数靠"感觉"写代码的开发者都清楚,新增功能有时会导致代码行数(LOC)激增。
这种激增会削弱人的主导权:当项目每月新增数百万行代码时,人力很难跟上节奏。¹ 有人或许觉得这根本不是问题,因为他们信任AI代理能处理好。但我要泼盆冷水:AI代理同样搞不定这些"冗余垃圾"。
我出身物理学背景,习惯用实验量化的方法解决问题。加入Earendil后,我的任务是找到衡量代码冗余度的方法,直觉告诉我,第一步应该深入调研文献,再看看其他公司的实践。
坦率地说,除了少数颇具洞见的研究论文,当前行业的做法让我失望——大多还是靠"感觉"。调研过程中,我在X平台上不断看到这类宣传:"端到端编码代理""不止写代码,还能直接部署的AI""无需人力成本的人类级评估"。这些说法和所有动听的故事一样,虽有几分道理,但言过其实。
大语言模型能写出近乎完全正确的代码,这得益于代码的可扩展性与可验证性:让LLMs生成代码,再用隐藏测试验证,就能得到清晰的反馈信号。但与之形成鲜明对比的是,判断代码是否冗余往往需要人类的直觉与审美,这是一项难度极高的工作。要说明其中缘由,最好的方式就是逐一分析现有的冗余度衡量方法。
让AI当裁判:这或许是行业内最常用的代码质量评估方式,但据我观察,效果往往不尽如人意。最朴素的做法是让模型给代码打1-10分,结果基本和随机数生成器没区别。更复杂的方法是给裁判模型两个解决方案A和B,让它选出更优的那个,但缺点是——只要重命名方案,模型就可能改变偏好。我这话略带调侃,大模型的这类问题没那么明显,但核心问题依然存在:让LLMs评判自己写的代码,绝不能替代专业评估。即便有人尝试用评分细则或让LLMs自行编写测试,这些方法距离真正消除冗余仍有很大差距。
让人类评判AI代码:如果暂不考虑软件工程师的能力差异,这是确保代码可读性的最佳方案。但缺点是,这种方式无法规模化——无论是用于AI训练,还是针对多模型提供商、多测试框架搭建大型基准测试,都不现实。²
最简单的方法:在我的调研与测试中,单纯统计代码行数的变化,竟是衡量冗余度的意外有效指标。但颇具讽刺意味的是,如果我们刻意针对这个指标优化,它就会失去意义。
接下来两种衡量方法来自我看到的论文SlopCodeBench,它们能很好地区分遗留代码库和LLM生成的冗余代码,看起来很有前景。
冗长度:衡量代码中重复、冗余的行数占比。³
腐化度:衡量代码库的体量集中于少数大型复杂函数的程度。
其中f代表函数,SLOC是源代码行数,CC(f)是函数的圈复杂度。
腐化度的计算方式很简单:圈复杂度大于10的函数总"质量",除以所有函数的总"质量"。
对比SlopCodeBench评估中AI生成代码与成熟代码库的平均冗长度和腐化度,差异十分显著:成熟代码库的平均冗长度为0.15±0.06,AI代理生成代码为0.33±0.10;腐化度方面,成熟代码库为0.31±0.17,AI代理生成代码为0.68±0.20。也就是说,AI生成代码的冗长度和腐化度平均是人类代码的两倍。我随后调研了一些自己靠"感觉"开发的项目,发现不少项目的冗长度高达0.4,腐化度甚至达到0.75,这说明上述结果并非评估本身导致的偏差。⁴
回到"为什么AI代理无法真正处理冗余代码"这个问题,我们需要看看SlopCodeBench的评估机制。与其他编码基准测试不同——那些测试一开始就给AI代理完整指令,再用一组隐藏测试验证程序是否达标——SlopCodeBench反其道而行之:它设置了多轮指令与测试迭代,每轮检查点之间会清空模型的上下文,更贴近人类实际使用编码代理的迭代流程。结果就是,糟糕的编码决策会随时间不断累积;在要求所有检查点都通过所有测试的严格通过率指标下,即便是最先进的模型,通过率也为0%。⁵ 这应该给那些每天轻松新增数万乃至数十万行代码的人敲响警钟。当然,测试标准过严、部分问题描述略有歧义等常见问题也可能影响结果,但整体趋势不容忽视。
通过对这些指标的探讨,希望你能更清楚地理解:为何评估代码冗余度如此困难,以及为何人类的直觉与审美仍在评估中扮演着或明或暗的关键角色。
我还想探索一些更有前景的方向,比如函数耦合度、代码变更频率、内聚性等。如果你正在做评估相关工作,欢迎和我交流:sebastian@earendil.com
这让我想起一句话:"用代码行数衡量编程进度,就像用重量衡量飞机制造进度。" ↩
我可不想逼着人去审核数百万行代码,只为得到一个不断变化的模型提供商排名。 ↩
冗长度的计算规则是一套手工编写的启发式算法,通过AST-Grep实现,这再次体现了评估工作中的人为因素。↩
不过有个以"靠感觉开发"著称的开源项目,这两项指标得分都不高,可能是因为函数耦合度极高,或是大量无关拉低了平均值。 ↩
尚未在Fable 5.1或Astra上测试,但已在GPT 5.6 sol xhigh等模型上完成测试。 ↩