← 文章 / 编程开发
Hacker News 1小时前 · 2026-09-12 00:13:15 · 0 阅读

编码解决之后:衡量代码的“粗糙度”

日期:2026年9月10日 星期四

发件人:Sebastian <sebastian@earendil.com>

收件人:你

主题:如果编码被解决了,接下来做什么?:衡量代码的“粗糙度”

LLM 在生成代码方面已经近乎完美,但这并非故事的终点。代码在形式上正确,不代表它没有引入不必要的抽象、产生重复,或做出糟糕的整体决策。这不是什么颠覆性的观察,绝大多数通过 vibe-coding 开发过项目的人都能意识到,每添加一个新功能,代码行数(LOC)有时都会发生爆炸式增长。

这导致了人类主导权的丧失,因为在那些每月新增数百万行代码的项目中,人类很难跟上节奏。1 有些人可能认为这根本不是问题,因为他们信任智能体(agents)能处理这些。但我有个坏消息:智能体其实也处理不了这些“粗糙”(slop)。

由于拥有物理学背景,我解决问题时习惯采用实验/量化的方法。在 Earendil 任职初期,面对如何衡量代码粗糙度的任务,我的本能反应是先深入研读文献,然后查看其他公司在做什么。

坦率地说,除了少数有洞察力的研究论文外,我对行业目前这种“基于感觉(vibes based)”的现状感到失望。在我的调研过程中,以及在 X 平台上,我不断被诸如“端到端编码智能体”、“不只是建议代码——而是直接交付的 AI”或“无需人力成本即可实现人类水平评估”这类信息轰炸。当然,就像所有精彩的故事一样,这些话都有一定的道理。

LLM 能够编写近乎完全正确的代码。这得益于代码的可扩展性和可验证性。让 LLM 生成代码,然后由隐藏测试进行检查,从而产生清晰的奖励信号,这非常容易。与之形成鲜明对比的是,检查代码的“粗糙度”往往需要人类的直觉和品味,且通常是一项极其困难的任务。我认为,通过梳理衡量“粗糙度”的可行方法,最能说明其中的原因。

让 AI 当裁判:这大概是行业内评估代码质量最常用的方式,但据我观察,它几乎从不奏效。最愚蠢的做法是让模型给代码打 1 到 10 分,这基本上等同于随机数生成器。稍显高级的做法是让裁判模型对比两个方案 A 和 B,并判断它更偏好哪一个。这种方法有个明显的副作用:当你给方案改名时,模型会改变偏好。我这儿有点开玩笑的成分,且在大模型上这种现象没那么严重,但核心观点依然成立。让 LLM 评判自己生成的代码,不能替代严谨的评估。尽管存在一些引入评分标准或让 LLM 编写测试用例的有趣尝试,但它们离真正消除“代码垃圾(slop)”还远得很。

人来评判 AI:如果我们忽略软件工程师质量参差不齐这一事实,这可能是确保代码保持人类可读性的最佳方案。缺点在于,这种方法在训练 AI 或构建包含多家模型提供商和多种框架的大型基准测试时,不具备可扩展性。2

最简单的方法:在我的研究和测试中,单纯追踪代码行数(LOC)的变化,竟然是衡量“代码垃圾”程度出乎意料的敏感指标,不过讽刺的是,如果我们开始刻意优化它,它就会失去作为衡量标准的意义

下面两种衡量指标来自论文 SlopCodeBench,它们看起来很有希望,因为能很好地区分传统代码库和 LLM 生成的“垃圾代码”。

冗长度(Verbosity):试图量化重复且不必要的冗长代码行数量。3

$$\mathrm{Verbosity}=\frac{|\text{AST-Grep flagged lines}\cup\text{clone lines}|}{\mathrm{LOC}}$$

侵蚀度(Erosion):试图衡量代码库中有多大比例的质量集中在少数几个庞大且复杂的函数中。

$$\mathrm{mass}(f)=CC(f)\sqrt{\mathrm{SLOC}(f)}$$

其中 $f$ 是函数,SLOC 是源代码行数,$CC(f)$ 是函数的圈复杂度

$$\mathrm{Erosion}=\frac{\sum_{f:\,CC(f)>10}\mathrm{mass}(f)}{\sum_f\mathrm{mass}(f)}$$

所谓侵蚀度,就是圈复杂度大于 10 的函数的质量总和,除以全部函数的质量总和所得的比例。

把 SlopCodeBench 评估中生成代码的平均冗余度和侵蚀度,与一组成熟的代码仓库对比,差距非常明显:仓库的平均冗余度为 0.15 ± 0.06,而 agent 生成的代码为 0.33 ± 0.10;侵蚀度方面,仓库为 0.31 ± 0.17,agent 则高达 0.68 ± 0.20。也就是说,agent 写的代码平均比人类代码冗余约一倍、侵蚀度也约一倍。我又检查了一些自己 vibe coding 出来的项目,发现不少冗余度高达 0.4、侵蚀度高达 0.75,所以这些结果应该不只是评估方法本身的产物。4

回到前面的问题:为什么 agent 自己处理不了这些 slop?这就要看 SlopCodeBench 的评估方式了。其他编程基准通常是先给 agent 一份完整的任务说明,再用一组隐藏测试来检验程序能否通过;SlopCodeBench 反其道而行:它设计了多轮“下达指令—运行测试”的迭代,并且在每个检查点之间清空模型的上下文。这更贴近真实的迭代开发过程,也就是人类实际使用 coding agent 的方式。其结果是,糟糕的编码决策会随时间不断累积。在严格通过率(要求所有检查点的全部测试都通过)下,即使是最先进的模型也达到了 0% 的通过率。5 这对那些每天开心地往代码库里塞进几万甚至几十万行代码的人来说,无疑是一个警示。当然,常见的保留意见仍然适用——测试可能过于苛刻、问题描述可能有歧义——但总体趋势是成立的。

希望通过了解这些指标,你能更清楚地认识到评估代码质量的难度所在,以及为什么人类的直觉和品味依然以显性或隐性的方式深深嵌入在评估过程之中。

还有一些值得探索的方向,比如函数耦合度、代码变更频率和内聚性。如果你也在做评估(evals)相关的工作,欢迎联系我: sebastian@earendil.com


  1. 这让我想起那句话:“用代码行数衡量编程进步,就像用重量衡量飞机制造进度一样。”

  2. 我不想强迫任何人审查数百万行代码,只为了获得模型供应商不断变化的排名。

  3. 这些规则是通过 AST-Grep 实现的一组手工制定的启发式规则,这也再次凸显了其中的人工因素。

  4. 虽然一个以氛围感著称的开源项目在这两项指标上得分都不高,但这很可能源于极高的函数耦合度,或是大量无关函数拉低了平均分。

  5. 尚未在 Fable 5.1 或 Astra 上测试,但已在 GPT 5.6 sol xhigh 等版本上验证。

原始来源: Hacker News

评论 (0)