anti-slop:在代码审查前用 Oxlint 拦住低质量代码

发布时间:2026/8/30 3:12:07
anti-slop:在代码审查前用 Oxlint 拦住低质量代码 第一次看到 anti-slop 这个项目名时我以为又是一套普通 lint 配置等看到副标题里的 Opinionated Oxlint rules才意识到它想解决的不是语法错误而是 code review 里最耗时的那一类争议。你大概率也遇到过这种 PR语法全对、测试全过但你就是不想 approve。变量全是 data 和 tmp函数里三层 if 嵌套遇到类型推导不出来就随手as any再补两句“把 data 赋给 tmp”的注释。这些问题不会让 CI 变红也不会影响运行结果但它们会让下一个改代码的人多花三倍时间。anti-slop 想做的就是把这类“代码糊墙感”变成一套有态度的规则在代码进入 review 之前就拦住它。它不是再写一篇“代码整洁之道”的文档而是直接告诉你这类写法不允许。我不打算逐条罗列它的规则清单因为具体规则会随版本变化更值得做的是把这类规则集的思路、落地方式和边界拆开讲清楚。1. 为什么“代码能跑”和“代码能维护”之间隔着一堆 slop1.1 语法检查解决不了的问题通常不是语法问题传统 lint 主要解决两类问题一类是错误比如变量未定义、switch 缺少 break另一类是风格比如引号、分号、缩进。这两类都很必要但它们都不关心“这段代码是否丑、是否难改、是否在给未来埋雷”。举个例子下面这段代码function processData(payload: any) { const tmp payload.data; if (tmp.status 1) { return tmp.result.map((item: any) { return { name: item.name, value: item.value }; }); } return []; }语法上没有问题测试也可能通过。但它至少有三个信号payload和item都是any类型系统在这里完全失明tmp这个名字只说明“这是临时数据”没说明它是什么魔法数字1背后是一个业务状态但代码里完全看不出含义。这三类问题靠“有没有报错”来发现是永远发现不了的。真正的排查成本在几周后突然出现你会为了改一个字段名把这 20 行代码重新人肉读一遍还要猜当初的意图。这就是 slop。它不是一个精确的工程定义更像是一种“低质量代码的集合”表面能工作但背后缺乏判断力。anti-slop 这类规则集本质上就是把这些“水面下”的坏味道重新拉回明处。它不追求抓到语法错误而追求让代码在“能运行”之外还表现出可读、可改、可搬移。1.2 Opinionated 的真正含义把审美表达成规则“Opinionated”这个词中文往往翻译成“有主见”。放在规则集里它意味着这个项目并不假装中立。它不满足于“尽量不打扰你”而是明确说“我认为这样写更好”。很多开发团队对严格 lint 的第一反应是约束太多影响效率。但真正拖累效率的不是规则本身而是每个人对“好代码”的定义不一致。写代码的人觉得“能用不就行了”review 的人觉得“这太丑了得改”。双方各执一词谁也说服不了谁。最后经常是 reviewer 列出五条修改意见前三条都是“命名能不能换一下”“这个函数是不是可以拆一下”这种主观建议作者不服回复一句“哪里丑了”然后两个人开始花时间争论审美。Opinionated 规则集的价值就是把这些争论提前消灭。它不给选择权任何地方出现any直接红函数超过设定行数直接红没有解释的ts-ignore直接红。团队成员不需要再就“可不可以更简洁”进行辩论因为标准已经写在规则里了。这里要补一句规则不是绝对合理。把“函数不超过 80 行”写成红线对某些线性流程可能过严。但团队真正需要的不一定是最好的规则而是一个明确规则。先统一再优化比永远不统一要好。2. Oxlint 为什么适合承载 anti-slop2.1 Oxlint 让严格规则变得“摸不到代价”Oxlint 是 Oxc 生态里的 JavaScript/TypeScript lint 工具用 Rust 写的。它和 ESLint 的最大差别不是语法也不是规则数量而是执行效率。在大型前端项目里ESLint 全量扫描经常要跑几十秒Oxlint 的启动和扫描速度从体感上看几乎是“刚按下回车结果已经出来了”。这个差异直接决定了严格规则集能不能真正进入开发流程。如果每次 lint 要等 5 秒很多人会只在提交前跑一次如果只要几百毫秒那完全可以接到编辑器保存动作上。规则集越严格触发的频率越高性能损失就越关键。anti-slop 选择 Oxlint最大的合理性就在这里它包含了很多“宁可错杀不可放过”的规则这些规则如果跑在慢速工具上团队会迅速得到负反馈——不是规则不好而是等太久。Oxlint 把执行成本降下去之后规则本身的强度才可能被接受。2.2 规则集和现有 ESLint 生态不是对立的有人担心从 ESLint 迁移到 Oxlint是不是要放弃现有插件从实际迁移经验看Oxlint 在兼容性上做得比较聪明。它支持读取 ESLint 风格配置也内置了大量核心规则很多规则名可以直接复用甚至能通过规则前缀映射来迁移。当然不同版本的兼容度不一样落地前要自己做一次验证不要假设 100% 覆盖。对 anti-slop 这类规则集来说它更可能以“规则集插件”的方式存在在配置里声明一个plugins然后开启对应规则。常见的配置示例结构大致是这样{ plugins: [anti-slop], rules: { anti-slop/no-explicit-any: error, anti-slop/no-magic-numbers: warn, anti-slop/max-lines-per-function: [error, 80] } }注意以上配置文件是示意结构不是 anti-slop 的官方接入方式。落地之前一定要先看它自己的文档再用最小项目验证。2.3 更低的延迟意味着规则可以成为“习惯”工具不是越严格越好而是越容易被日常执行越好。一个再强的主张如果只在月底做一次全量 lint价值会大打折扣。anti-slop 和 Oxlint 的组合真正的产品化一点在于它把一个“常开的高强度规则”放在了低成本的通道里。这会让开发者下意识地遵守规则而不是到 CI 阶段才发现违规。这其实就是把质量左移与其在 review 时发现“为什么这里又有 any”不如让开发者写的时候就看到红线和快速修复提示。Oxlint 的速度是这套左移流程能够成立的基础。3. anti-slop 在反对什么把坏味道拆成五种可检查的形态“Slop”不是一个标准语法术语它更像一个经验集合。为了理解这类规则集我习惯把 slop 拆成五种常见形态。这些形态不一定覆盖 anti-slop 的全部规则但大概率是任何“反 slop”规则集都会触碰的核心区域。3.1 类型逃避型 slop类型逃避指一切绕开类型系统的写法any、as any、非空断言!、ts-ignore、未经校验的as。它们不是语法错误但它们切断类型推导把问题从开发时推给了运行时。一个典型场景后端返回的数据结构里嵌套了一层data前端开发者不想做类型守卫直接const tmp res.data as any。当时很爽但后续所有访问嵌套字段的行为都会变成“盲人摸象”。规则集通常会对这类写法设置“错误”级别因为一旦允许任何类型保护都形同虚设。另外ts-ignore需要尤其严格。它和any的问题不太一样ts-ignore会吞掉下一行的所有类型错误包括未来的。很多团队宁可允许局部any也不允许随意ts-ignore因为它更容易让类型检查“沉默”。3.2 结构失控型 slop结构失控指函数过长、嵌套过深、分支过多、循环和条件混乱。典型信号是“一个函数做三件事”“这里看起来可以合并但我不敢动”。比如一个函数从参数解析开始到查数据库到构造响应最后兼任错误处理中间还有两张 if 表。语法上没问题但当你只想改其中的错误处理逻辑就必须理解整个函数的前因后果。规则方向包括函数最大行数、圈复杂度上限、嵌套深度、禁止空参数对象。这些规则看起来机械但正是“机械”才适合让机器来卡。有人会说拆函数也可能拆出不合理的函数反而增加阅读跳跃。这个说法成立但它的前提是“团队有足够好的设计能力”。在没有这个前提下让代码爆炸式地堆在一个函数里对大多数团队来说更危险。规则集只不过选了更保守的一方。3.3 命名与注释敷衍型 slop命名敷衍是最容易被发现、也最容易被放行的 slop。data、tmp、res、item是高频名字如果它们出现在十行以上的作用域里读者基本要靠上下文猜语义。规则集能从命名长度、最少字符、可读性方面做检测有些团队会把“禁止无意义命名”开成错误。注释敷衍有两种没有注释和全是废话。最典型的是// 把数据赋值给临时变量这种“照抄代码再说一遍”的注释。它不会增加信息量还占住屏幕。更糟的是注释和代码内容不一致——代码改了注释没改后来的人要花时间判断谁是对的。比较接近合理的规则方向是注释只能解释“为什么”不需要解释“是什么”因为“是什么”应该靠代码本身说清楚。3.4 AI 生成的“合理性” slop随着 AI 编程助手成为日常一种新的 slop 正在变多AI 生成的代码在语法、结构上都非常“正确”甚至能通过单测但仔细看会发现它格外冗余、重复或者做了一个毫无必要的抽象层。它生成的注释也往往和代码重复像是怕你看不懂一样逐行解释。它的变量命名通常不会明显错误但会非常“通用”比如result、parsedData、handleClick放在任何场景都对但对自己项目里的业务含义毫无关联。当codebuddy rules这类给 AI 编程助手立规矩的讨论越来越常见时anti-slop 其实是在做更硬核的事把 prompt 里的软规则变成 lint 里的硬规则。给 AI 写提示词它不一定每次都遵守但 lint 规则不通过就是不能提交。这个差异很关键。anti-slop 这类规则集对 AI 代码的意义不是去检测“这段代码是不是 AI 写的”而是把同一套质量标准套在所有人所有工具身上。AI 写出来的东西可以更快但不应该拥有豁免权。规则