关于 antfu-simplify
用于精简当前 PR 或工作区差异的代码审查技能,目标是在不改变行为的前提下保留最小且正确的改动。它分批验证删除内容,并报告保留或删减的部分、差异规模及检查结果。
主要功能
- 01审查当前变更差异
- 02移除冗余或推测性内容
- 03保持行为和范围不变
- 04每批改动后运行检查
- 05报告取舍及差异规模
适用场景
- 01精简 PR 中的抽象层
- 02判断新增分支或辅助函数是否必要
- 03审查前缩减工作区改动
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ antfu/ skills --skill antfu-simplify安装后在 Claude Code 中输入/antfu-simplify确认已加载。
详细介绍
精简变更
审查当前变更(PR 分支或工作区),并像熟练的开发者那样,将其精简为最小且正确的差异。采用消融研究的方法:逐项移除,检查是否会破坏重要功能,只保留真正有必要的部分。
目标:代码整洁、精简,抽象程度恰到好处,同时稳健(能处理实际边界情况)且通用(解决一般情况,而不只是触发此次变更的特例)。
硬性规则
- 行为保持不变。 只做精简。不要添加功能、修改公共 API 或修复无关问题。应单独报告无关发现。
- 范围仅限差异。 只修改此次变更新增或修改的代码,以及移除这些代码所必需修改的部分。不要重构周边代码库。
- 每项移除都要验证。 每批修改后运行仓库的测试、类型检查和代码检查。如果某项检查没有覆盖被移除的部分,就明确分析原因,否则保留该部分。
- 遵循周边代码的风格、命名和注释密度。
工作流程
- 获取差异。 确定基准:优先使用 PR 目标分支的合并基点(
git merge-base HEAD origin/<default>);否则,对未提交的改动使用git diff HEAD。阅读完整差异及相关文件。用一句话记录变更目标;之后所有判断都以此为准。 - 盘点各部分。 列出差异新增的每个单元:函数、参数、选项、分支、类型、文件、依赖、抽象层、注释、测试。参见消融研究。
- 逐项消融。 尝试移除、内联或合并每个部分。根据保留还是删减决定取舍。
- 应用删减。 分小步进行。每批修改后运行针对性检查(测试、类型检查、代码检查)。如果删减导致行为异常,就撤销;这说明该部分确有必要。
- 检查结果。 以审查者的视角重新阅读最终差异。剩下的每一行是否都能用那句目标说明?代码是否仍然稳健且通用?
- 报告。 用简短表格列出删减或保留的内容及原因,并提供修改前后的差异规模(
git diff --stat)。除非有人要求,否则不要提交。
消融研究
对差异中的每个部分,都要问:如果删除它,具体会有什么损坏?
| 部分 | 消融操作 | 保留条件 |
|---|---|---|
| 新函数 / 辅助函数 | 在调用处内联 | 被 2 个或更多位置调用,或其名称说明了不明显的步骤 |
| 包装器 / 抽象层 | 直接调用底层内容 | 它隐藏了实际复杂性,或隔离了可能变化的边界 |
| 参数 / 选项 / 配置 | 将唯一使用的值硬编码 | 现有调用方确实需要使用不同的值 |
| 类型 / 接口 / 泛型 | 使用推断类型或现有类型 | 它已导出,或类型推断会导致更差或错误的类型 |
| 分支 / 守卫 / try-catch | 删除并运行测试 | 它防护的是可达情况(真实输入、真实故障),而非不可能发生的情况 |
| 新文件 / 模块 | 合并到唯一的使用方中 | 它有多个使用方,或职责独立 |
| 依赖 | 改用几行代码或现有依赖 | 它能处理否则很容易出错的边界情况 |
| 重复逻辑 | 复用仓库中已有的工具函数 | 仓库中不存在等效实现(先搜索) |
| 注释 | 删除 | 它说明的是为什么(限制、变通方案、令人意外的选择),而不是是什么 |
| 测试 | 删除并检查哪些行为失去了保护 | 它覆盖了其他测试都未覆盖的行为或回归问题 |
| 与目标无关的修改行 | 还原 | 绝不保留顺手改动 |
保留还是删减
在以下情况下删减:
- 推测性的:为没人需要的未来需求而构建(额外选项、钩子、插件扩展点、“以防万一”的泛型)。
- 冗余的:重复了语言、框架、类型或现有工具已经提供的功能。
- 防范不可能发生的情况:对类型或调用方保证的值进行空值检查、永远不会执行的回退逻辑、吞掉错误的
catch块。 - 没有收益的间接层:只用一次的辅助函数、透传包装器、明明函数就能完成的类、只能构建一种东西的工厂。
- 噪音:注释掉的代码、叙述性注释、未使用的导入和导出、仅涉及格式的改动。
在以下情况下保留(或适当增加):
- 健壮性: 处理真实的边界情况(空输入、并发、清理、跨平台路径、附带上下文的错误传播)。
- 通用性: 解决一般问题,而不是只针对报告的问题做特殊处理。如果修复将问题报告中的名称、路径或值写死,就应将其泛化。
- 恰到好处的抽象: 某种内容重复到第三次时再提取;第一次和第二次通常不必。好的抽象能删掉比自身增加的代码更多的代码。
如果抽象太小,就合并;如果函数做了几件互不相关的事,就拆分。目标既不是行数最少,也不是层数最多,而是让读者需要掌握的概念尽可能少。
需要留意的问题
- 在调用处修补症状,而不是解决根因。
- 存在通用规则即可覆盖的特殊情况(
if (name === 'foo'))。 - 两条代码路径做着相同的事,只存在细微差异;应将它们统一。
- 可以从现有数据推导出的状态、标志或缓存。
- 参数列表过长,或选项对象中的大多数值从未改变。
- 可以通过
typeof、ReturnType、Parameters或工具类型推导,却仍手动重复定义的类型。 - 仓库、运行时或现有依赖已经提供,却仍手动实现的工具函数。
- 断言实现细节或逐行复刻代码的测试。
报告格式
| # | Piece | Action | Why |
|---|-------|--------|-----|
| 1 | `parseOptions()` in src/cli.ts | inlined | one caller, 3 lines |
| 2 | `retry` option | removed | no caller passes it; default is enough |
| 3 | `try/catch` in fetchData | kept | network errors reach users; test covers it |
Diff: +142 -8 -> +61 -8. Tests, typecheck, lint pass.
将发现但不在本次范围内的问题(无关的 bug、更大范围的重构)单独列出,并暂不处理。
评论
支持 Markdown