重复代码是 LLM 为换取速度而征收的税
我合作过的每一个编码智能体都有同样的病症。给它一个与它此前完成过的请求相似的请求,它就会兴高采烈地伸手去拿同一种形状的代码——哪怕这种形状已经以另一个名字存在于仓库之中。把这种本能放大到一个由三名工程师和四个智能体组成的团队里,你就会迎来定义当前软件时代的状态:重复率的增长速度超过功能增长速度的仓库。
这并不是一个关于马虎智能体的故事。让 LLM 有用的那种模式匹配,正是让它产生重复的那种模式匹配。一个 transformer 并不知道你的仓库里已经有了一个 UserRepository。它知道的是训练分布中包含一种叫做"repository"的形状,于是它就复现这种形状。三次,分布在三个文件里,用三个略有差异的名字。
为什么现有工具不是答案
代码克隆检测领域拥有三十年的文献和少数几款生产级工具——CPD、Simian、jscpd、Sonar CPD。它们都共享两条已不再成立的假设:
- 重复是偶发的缺陷。 这些工具把重复以列表形式呈现,按发现顺序或文件名排序。当偶尔出现的重复是手工打造时,这种方式还行得通。但当重复成为仓库的默认状态时,它就不灵了。
- 人类是主要读者。 输出格式假定开发者会眯着眼睛盯着一张表格,挑出一个簇去调查,然后在闲暇时清理它。智能体不会眯眼。智能体需要的是字节范围、稳定的 ID 和一份 schema。
Deslop 从这两条假设出发重新构建。输出按每个簇的加权影响排序,因此顶部那一行始终是收益最大的所在。输出以 JSON 为先,文本和 HTML 只是同一份 schema 之上的视图。受众是双重的:安装它的人,以及查询它的智能体。
快速反馈就是整个产品
最重要的特性,不是支持的语言之广,不是同行为检测(Type-4)的精度,也不是信号融合的精巧。它是到首个有用信号的时间。一个在落地三次提交之后才浮现的重复,是你不会再去重构的重复。一个在智能体还开着那个文件时就浮现的重复,是你在下一条消息之前就修掉的重复。
所以整条流水线都为此而调优。缓存的键设计使得未改动的文件零成本,因此一次热运行只会重新解析你刚刚动过的那些文件。排名很廉价——每个簇两次乘法和一次对数运算。LSP 外壳今天就已发布,它在编辑器里以拼写检查器的速度点亮重复代码;MCP 外壳则把同一份实时分析暴露给 Claude、Cursor 和 Copilot,在智能体甚至还没敲出那段重复之前。
速度不是 Deslop 的一个特性。速度就是全部的意义。
拿到一个发现该怎么办
Deslop 报告中的一个簇是一个决策,而非一纸定论。工具负责报告;你来决定。大体上有三条路径:
- 提取。 这些片段足够一致,且共享了足够多的调用图,以至于一个共享函数就是显而易见的答案。JSON 中的
action_hints会标记出这些。 - 复用。 其中一个片段是"真正的"实现,其余的应当调用它。挑出测试最好的那个,删掉其余的。
- 接受。 有些重复是有意为之的——测试夹具、引导初始化,以及两个今天看起来相似但日后会分道扬镳的东西。加上标注,继续前进。Deslop 不作评判;它只是记分。
唯一错误的做法,是忽视报告的顶部。那里才是钱之所在。
这将走向何方
今天的 Deslop 就是那台实时服务器。两个协作的进程——其一是文件监视器加 LSP 外壳,其二是 MCP 外壳,通过一个本地 IPC 套接字通信——再加上一组聚焦的 MCP 工具,以 find-similar 为首,智能体可以在生成过程中调用它们。与 CLI 相同的流水线、相同的 schema、相同的缓存——CLI 如今是用于 CI 门禁的冷缓存兜底方案。VS Code 扩展把这一切(LSP、MCP、CLI)打包进单个 VSIX。JetBrains 是下一个。
这台服务器的主要用户不是你。是与你结对编程的那个智能体。这也理应如此:智能体产生重复;智能体就应该修复它——而且,有了内循环中的 find-similar,智能体更应该预防它。
今天就安装。打开你最乱的那个仓库。读第一行。