如果编程问题已经解决,接下来做什么?:衡量代码的草率程度
If coding is solved, what now?: Measuring the sloppiness of code

原始链接: https://earendil.com/posts/measuring-code-sloppiness/

尽管大语言模型(LLM)擅长编写形式上正确的代码,但它们经常引入“垃圾代码”——即不必要的抽象、冗余以及糟糕的结构决策。这导致代码行数(LOC)激增,使人类难以管理。依赖人工智能进行自我质量评估往往收效甚微,因为它缺乏维护整洁代码所需的直觉和品味。 为量化这一问题,研究表明人工智能生成的代码比人类编写的代码更为“冗长”且“退化”。例如,`SlopCodeBench` 的数据显示,人工智能代理生成的代码在冗长程度和复杂度上是标准人类代码库的两倍。此外,在指令和测试不断演进的迭代环境中,当前最先进的模型难以保持代码质量,往往无法维持项目的正常运行。 归根结底,检测代码的低质冗余仍然是一项难以通过简单自动化指标完成的任务。虽然形式上的正确性可以通过测试轻松验证,但长期的可维护性依赖于人类式的判断。随着我们不断推动编码自动化,必须将重心从简单的输出生成,转向对结构健康度、内聚性和复杂性的严谨评估,以避免被难以驾驭的低质量代码库所淹没。

关于“粗制滥造”AI 生成代码的 Hacker News 讨论揭示了一个深刻的分歧:编程是否真的已经被“攻克”了。 许多参与者认为,AI 目前擅长独立生成功能模块,但缺乏构建复杂、多功能系统所需的架构远见。虽然 AI 能快速生成代码,但这往往会导致“面条式”设计、过多的代码行数(LOC)以及人类最终必须去处理的技术债务。怀疑论者指出,“正确性”只是一个基准要求,并非软件工程的全部,软件工程还要求具备可维护性、可观测性和安全性。 相反,一些人认为人类编写的代码历史上质量就很差,AI 只是加速了在企业环境中早已泛滥的“垃圾代码”的产出。AI 的支持者认为,目前的局限性只是暂时的障碍;随着我们对“代码质量”定义出更好的衡量标准,AI 将会自然而然地进化以满足这些要求。 归根结底,共识在于区分了“编程”(语法生成)和“软件工程”(设计与意图)。虽然 AI 改变了前者,但后者在很大程度上仍然是一个由人类驱动的过程,需要语境理解以及准确定义问题的能力。
相关文章

原文

LLMs have become almost perfect at generating code, but that isn’t the end of the story. Just because the code is formally correct doesn’t mean that it is not introducing unnecessary abstractions, creating duplicates, or just making bad decisions overall. This is not a groundbreaking observation, most people who have vibe-coded a project, have realized that each additional feature can sometimes lead to an explosion of lines of code (LOC).

This results in a loss of human agency, because in projects that are adding millions of LOC per month, it is hard for humans to keep up. Some people might say that that is not an issue at all, because they trust their agents to deal with it. I have bad news for you, agents can't really deal with the slop either.

Coming from a physics background, I always had an experimental/quantitative approach to solving problems. When I started at Earendil, with the task of figuring out how to measure code sloppiness, my natural instinct was to first take a deep dive into the literature and then check what other companies were doing.

To be frank, with the exception of a few insightful research papers, I was disappointed at how “vibes based” the industry seems at the moment. In my research and on X, I was constantly bombarded with messages such as “End-to-end coding agents”, “AI that doesn't just suggest code—it ships it” or “Human-level evaluation without human-level cost”. Which like all good tales, have a grain of truth in them.

LLMs are able to write almost perfectly correct code. This is because of the scalability and the verifiability of code. It is pretty straightforward to let LLMs generate code and then let that code be checked by hidden tests, which results in a clear reward signal. In stark contrast to that, checking the ‘sloppiness’ of this code often requires human intuition and taste, and is an extremely difficult task in general. I think the best way to illustrate why that is, is by going through possible ways of measuring slop.

AI as a judge: This is probably the most common way of evaluating code quality in the industry and from my observations it rarely works. The most naive way of doing it, namely asking the models how good the code is on a scale from 1-10, is basically equivalent to a random number generator. The more sophisticated approach, namely trying to give the judge model two solutions A and B, and then letting it decide which solution it prefers, has the downside of the model changing its preference, when you rename the solutions. I am being a bit facetious here and the effect isn’t as pronounced with larger models, but the main point still stands. Asking LLMs to judge the code they write is not a substitute for a proper evaluation. Even though there are some interesting approaches with rubrics or the LLMs writing tests, they are still a far shot from actually getting rid of the slop.

Human judges the AI: If we ignore the fact that there is huge diversity in the quality of software-engineers, this would be the best solution to assure that the code stays human readable. With the downside being that this is not scalable for training AI or having large benchmarks with multiple model providers and harnesses.

The simplest method: In my research and tests simply taking the change in the number of LOCs has been a surprisingly effective metric for sloppiness, with the ironic caveat that if we started optimizing for it, it would cease to be a meaningful measure.

The next two measures were introduced to me by the paper SlopCodeBench, and seemed promising because they were able to separate legacy code bases from LLM-slop quite well.

Verbosity: Tries to measure the amount of duplicated and unnecessary verbose lines.

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

Erosion: Tries to measure how much of a codebase's mass is concentrated in a few large and complex functions.

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

Here f is the function, SLOC is the source lines of code and CC(f) is the cyclomatic complexity of the function.

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

The erosion is then simply the fraction between the mass of the functions with a cyclomatic complexity larger than 10, by the mass of all functions.

If we look at the average verbosity and erosion of the code generated during the SlopCodeBench evaluation and compare that to a set of established repos there is a stark difference between them. On average the verbosity in the repos is 0.15 ± 0.06 and in the agents code is 0.33 ± 0.10. For erosion the repos achieve 0.31 ± 0.17 and the agents 0.68 ± 0.20. The agent's code is on average roughly twice as verbose and eroded as human code. I then investigated some vibe coded projects of my own and a lot of them had a verbosity of up to 0.4 and erosion as high as 0.75, so these results probably weren't just an artifact of the evaluation.

To come back to the point of why agents can’t (really) deal with the slop themselves, we need to look at the evaluation of SlopCodeBench. In contrast to other coding benchmarks, which give the agent a complete list of instructions at the start and then have a set of hidden tests the program needs to pass, they do the opposite. They create multiple rounds of instruction and test iterations, where in between checkpoints the context of the models is erased. Thereby mimicking much more closely an iterative process, like how coding agents are actually used by humans. The result of that is that bad coding decisions accumulate over time and for the strict solve rate, where all tests have to be passed at all checkpoints, even state of the art models achieve 0% pass rate. Which should be a warning sign to everyone who happily adds tens of thousands or even hundreds of thousands of LOC a day. Obviously there are the usual caveats about too strict of tests or one or the other slightly ambiguous problem statement, but the general trend holds.

In exploring these metrics I hope you now have a clearer picture of why it is challenging to evaluate code sloppiness and why human intuition and taste are still either implicitly or explicitly baked into the evaluation.

There are some promising other directions I want to explore, such as coupledness of functions, code churn, cohesion and so on. If you are working on evals and would like to talk, I would be happy to do that: [email protected]

联系我们 contact @ memedata.com