rf
Scans for structural design errors first and local code smells second, and only proposes — never edits. Use after a large change or several iterations on the same area, when the user says /rf, or when
Files1
View on GitHubSKILL.mdskills/rf/SKILL.md
GitHub已经做了一次大更新、或在同一处迭代了好几轮。做一次重构扫描 —— 只提案,不动任何文件,我来决定执行哪些。
我给了范围(一个路径 / 模块 / 关注点)就限定在那里;没给就扫整个项目。
先读相关代码、AGENTS.md、README.md、最近的 commits、架构文档,建立 context。不要走马观花。特别看 git 历史里被反复改的地方、review / bug 循环反复出血的点 —— 那是结构错误的信号,不是局部坏味道。
分两遍,顺序不能反:结构在前,表面在后。在一个结构错误的模块上做局部清理,只会把错误焊得更牢。
第一遍:结构性(先做,优先级最高)
不是找杂物,是问"这个设计本身对不对"。对每个重点模块,自上而下。
核心动作 —— 把实现复杂度对照问题的本质难度。 先用一句话写出这个模块真正不可约的难点是什么(本质张力,不引现有代码);再看实现里有多少东西并不在解这个张力。差额就是症状。
对差额定位病因,至少查这三种结构性错误:
- 职责错层 —— 模块兼任了不属于它问题域的职责(如 ingress 里手写了一个 job runner)。信号:同一处在第二遍里同时命中多类坏味道(过度设计 + 冗余 + 不一致 + 静默失败 挤在一起)。
- 为未证实的需求提前优化 —— 手写整套机制去解一个没有使用 / 负载证据的问题;它往往既是最大复杂度源、又是最大 bug 源。问:有真实证据要它吗?更底层是不是已经提供了安全保证(于是这套只是叠在上面的可选优化)?
- 缺一层抽象 —— 某职责没被抽成独立一层,被迫寄生在相邻层(信号:被迫用某平台原语把它塞进"请求的余生" / 某个不相关的生命周期里)。
结构性发现的输出(和局部发现不同,不要给"删这行改那行"):
- 从第一性原理一句话重述该模块真正要达成的行为(不引现有代码);
- 判断缺陷在哪一层,只选一个:
- fix —— 这层有 bug,周围都对
- redesign —— 这个模块的设计本身就不对
- refactor —— 早期埋下的错误架构假设,已在多个模块之间渗透
- rewrite —— 需求当初就理解错了,现在的代码在挡路
- 给匹配该诊断粒度的方案 —— 不反射性选最小补丁,也不反射性选全部重写。pre-release、无 back-compat 包袱时,"删了重来"是合法答案。
(与 /ct 同源:/ct 在打补丁打到第二次时被动触发,这一遍在大迭代后主动扫。)
第二遍:局部坏味道(只对第一遍判定"结构没问题"的代码做)
被第一遍判为 redesign / refactor / rewrite 的模块,先不在这里列它的局部坏味道 —— 那些会随结构方案一起消失,单独列只是噪音。对结构站得住的代码,按这些分类找:
- 死代码 —— 不可达分支、未使用的 export、孤立文件、注释掉的代码、对应代码已不存在的测试。
- Legacy / 被取代的路径 —— "以防万一"的旧实现、给已不存在的调用方留的兼容 shim、半途而废的实验、早该决断却一直挂着的 feature flag。
- 冗余 —— 重复逻辑、同一件事两种做法、包了一行的 helper、跨模块的并行实现。
- 不一致 —— 命名、错误处理、分层、文件结构、约定 自相矛盾处。挑出该赢的那个,其余标出。
- 局部过度设计 —— 只用在一处的抽象、推测性接口、没人调的 config 开关。(成套的提前优化属于第一遍。)
- 静默失败 —— 吞掉的异常、藏起来的 fallback、
catch { /* ignore */ }、用?? default掩盖 bug。 - 过程文档残留 ——
SESSION_*.md、HANDOFF.md、*_PLAN.md、*_PROGRESS.md、临时策略笔记、docs/草稿。只保留产品 / 项目文档。
每个局部发现按这个格式:
- 位置 —— 文件路径(必要时加行号)
- 问题 —— 一句话描述
- 为什么该删 / 该改 —— 一句话,违反了什么原则、或能带来什么
- 风险 —— 删 / 改之后什么会坏,没有就写"无"
执行计划(两遍合并后)
- 结构性方案排在最前:它一动,下游一批局部发现会自动消失 —— 标出哪些局部项被它覆盖,避免重复劳动。
- 其余按风险分批(低风险先做),每批起什么分支名、commit 怎么切。
- 有顺序依赖的标出来(比如先删调用方再删被调方)。
目标:代码不只是干净,而且结构正确 —— 没有错层的职责、没有为幻想需求手写的机制、没有缺失的抽象层;然后才是没有死路径、没有伪装成产品的脚手架、没有两种方式做同一件事。