让 AI 重构代码,最常见的翻车方式不是改错,是改多了。你让它清理一下某个函数,它顺手换了命名风格,调了依赖顺序,把你写惯的那段写法替换成它更喜欢的写法。功能看着还在,diff 却有四百行,你盯着屏幕不敢点合并。
问题不在模型能力,在指令缺约束。github/awesome-copilot 仓库里有个叫 refactor 的 Skill,只解决这一件事。skills.sh 注册表给到的累计安装是 21,316 次,Smithery 页面显示 20,589,在 1,349 个代码审查与质量类 Skill 里排到第 17 位。整个 Skill 就一个 SKILL.md,没有脚本,没有 MCP 服务器,纯指令。

从文档结构看,它跟我想的完全相反。我本以为又是一份重构手法大全,结果前五十行几乎全在讲什么时候不许重构、什么情况下你做的事根本不叫重构,十种代码坏味道的 before/after 反而排在后面。这个排列顺序本身就是一种判断。
说真的,这篇文章只想弄明白一件事:它是怎么用一段自然语言,把 Agent 的默认倾向从重写掰回改结构的。哪些规则是真起作用,哪些只是凑数的排版。如果你也在给团队写类似的工程约束,这套写法可以直接抄走。
Prompt 结构分析
先说整体布局。这份 SKILL.md 一共切成十节,从 Overview 一路排到 Common Refactoring Operations,中间没有一节是凑数的。按作用归一下类,脉络很清楚:
-
前两节定边界:Overview、When to Use -
第三节立闸门:Refactoring Principles -
中段给手法:十种 Code Smells、Extract Method、Type Safety、Design Patterns -
末段做收口:Refactoring Steps、Checklist、Operations 表
结构本身不新鲜,密度相当吓人。尤其是第三节,两页纸里塞进了五条硬规则和四个禁止项,其余九节加起来都没它重。
真正起作用的是 Golden Rules 那五条。它不在描述重构是什么,它在给 Agent 设五道闸:
The Golden Rules
1. Behavior is preserved - Refactoring doesn't change what the code does, only how
2. Small steps - Make tiny changes, test after each
3. Version control is your friend - Commit before and after each safe state
4. Tests are essential - Without tests, you're not refactoring, you're editing
5. One thing at a time - Don't mix refactoring with feature changes
第四条那句“没有测试你不是在重构,你是在编辑”,是全篇最狠的一句。多数重构类 Prompt 会把跑测试写成操作步骤里的一环,这里直接把它抬到了定义层面:前提不满足,你做的事就不叫重构。定义式约束比流程式约束强得多,因为 Agent 没法靠跳过某一步绕过去。
更反常识的是它专门拿一节写 When NOT to Refactor。多数 Skill 只讲自己能干什么,这份列了四种该住手的情况:
When NOT to Refactor
- Code that works and won't change again (if it ain't broke...)
- Critical production code without tests (add tests first)
- When you're under a tight deadline
- "Just because" - need a clear purpose
从 Prompt 设计角度看,这一节的功能是给 Agent 留一个合法拒绝的出口。没有它,Agent 接到任何“帮我优化一下”的请求都会硬着头皮动手;有了它,Agent 面对没有测试覆盖的生产代码就有了引用依据,可以直接回一句先补测试。这一点上它比不少人类工程师清醒。
把整份文档按作用切一刀,结构其实非常清楚:顶层定边界,中层给闸门,底层才是具体手法。

这张图里最该盯的不是底层那十种坏味道,是中间那层闸门。底层的手法换个模型照样能生成,闸门才是这份 Skill 真正的护城河,也是它跟一份普通重构教程的分界线。
工作流分析
流程部分走的是五个阶段,从 PREPARE 一路到 CLEAN UP,看上去是个标准线性流程。但把第三步那一节拆开,里面藏了一个更小的循环,这个循环才是整套设计的核心:
1. PREPARE - Ensure tests exist (write them if missing)
- Commit current state
- Create feature branch
2. IDENTIFY - Find the code smell
- Understand what the code does
- Plan the refactoring
3. REFACTOR - Make one small change
- Run tests
- Commit if tests pass
- Repeat
4. VERIFY - All tests pass
- Manual testing if needed
- Performance unchanged or improved
5. CLEAN UP - Update comments and docs
- Final commit
第三步那四行有个容易被忽略的细节:commit 是写在循环里的,不是写在循环外的。也就是说每一小步通过测试就立刻落一个提交点,而不是攒到最后一次性提交。这个设计的意图很明确,它假设你会失败,并且让失败的成本尽可能小。

对照仓库里其他几个名字带重构的 Skill,分工能看得更清楚。同一个 repo 里还躺着四五个同类,切入角度完全不同,拿错了场景基本等于白装:
| Skill | 切入角度 | 典型触发 |
|---|---|---|
| refactor | 单点到块的结构改善,保行为 | 清理这个函数、拆掉上帝类 |
| refactor-plan | 多文件改动前先出计划再确认 | 跨模块重构先排顺序 |
| review-and-refactor | 按仓库既有编码规范对齐 | 对齐 .github/copilot-instructions.md |
| refactor-method-complexity-reduce | 把认知复杂度压到阈值以下 | 指定方法名 + 目标复杂度 |
| repo-rebuilder | 大范围重写或结构重建 | 推翻重来 |
这张表暴露了一个事实:refactor 只是这条链路上最保守的一环。真要动跨模块的手术,应该先用 refactor-plan 出计划;要对齐团队规范,用 review-and-refactor 更准。把 refactor 当万能重构入口用,是当前最容易犯的误用。
实战场景
最能体现它价值的场景,是加新功能之前的清理。代码结构已经碍事了,但你又不希望这次改动混进任何行为变化。加载 refactor 之后,Agent 的产出会被 Golden Rules 第五条卡住:只做结构,不碰功能。diff 里如果出现了逻辑分支的新增,那就是它越界了,可以直接退回。
第二个场景反而更常见,也更尴尬:你的 PR 里同时混着重构和新功能。这是绝大多数人真实的提交习惯,也正好撞在第五条规则上。装了这个 Skill 的 Agent 会把这两件事拆成两轮,先出结构改动并提交,再动功能。人类工程师在这里往往比 Agent 更需要这条约束。
第三个场景是它的硬边界。面对一段没有测试覆盖的临界生产代码,这份 Skill 的正确反应是拒绝执行,并要求先补测试。如果你在一个测试覆盖率接近零的遗留仓库里装它,大概率会觉得这个 Skill 很啰嗦。这不是它的缺陷,是它在诚实地告诉你前提不成立。

时序图里那个回退箭头值得单独说。测试失败就回到上一提交点,这一步在多数重构 Prompt 里是缺的,大家都默认重构会一路向前。真实情况是失败才是常态,把回退路径写进指令,Agent 才不会在错误的方向上硬撑着改下去。顺带说一句,这也解释了为什么第三条规则要把版本控制单独拎出来,没有可用的提交点,回退就只是一句空话。
洞察与反思
我个人判断,这份 Skill 的价值不在教你重构,在于它把 Agent 的默认行为模式硬掰了过来。模型天生倾向于重写,因为重写在生成上更省事,输出也更完整好看。这份文档用五条规则、四个禁止项、一个每步提交的小循环,硬生生把倾向扭成了改结构。这种对抗模型默认倾向的设计,才是 Skill 这类东西真正的技术含量。
批评也得给到位。十种坏味道基本全是 OOP 语境,对函数式或者数据导向的代码几乎没覆盖。随手点四条出来就明白了:
-
Large Class:拆掉知道得太多的上帝类 -
Feature Envy:方法过度依赖别人的数据 -
Primitive Obsession:拿裸字符串表示邮箱和电话 -
Inappropriate Intimacy:跨对象深挖别人的内部结构
这四条放到一个以纯函数和数据管道为主的项目里,命中率会低得可怜。Checklist 那条函数小于 50 行同样是机械阈值,一个 60 行的状态机硬拆成三块反而更难读。这份文档的工程观大致停留在 2010 年前后。
再往大一点说,我观察到 Skill 生态正在从能力包转向约束包。早期大家比的是谁的 Skill 能让 Agent 多干点事,现在开始有人比谁能让它少干点事。refactor 21k 的安装量放在这个背景下就不奇怪了,它卖的不是能力,是克制。这个转向比任何一个具体 Skill 都重要。
还有一个容易被忽略的点:这类约束型 Skill 的效果高度依赖模型的服从度。同一份 SKILL.md 换一个模型跑,表现差距不小,强模型会把 When NOT to Refactor 当真规则执行,弱模型大概率直接跳过。它带来的那部分稳定性,其实是从模型能力里借来的。
边界要讲清楚。它默认你有测试、有版本控制、有时间做小步提交。三条里缺任何一条,效果都会打折,缺测试那一条基本等于白装。判断要不要装它,先看你们仓库的测试覆盖率,别看它的安装量。
资源地址
| 资源 | 地址 |
|---|---|
| Smithery 技能页 | https://smithery.ai/skills/github/refactor |
| GitHub | https://github.com/github/awesome-copilot |
| 源码位置 | skills/refactor/SKILL.md |
| 技能目录站 | https://awesome-copilot.github.com |
总结
值不值得装,取决于你有没有测试。有测试覆盖、又经常让 Agent 动老代码的团队,这个 Skill 能省掉大量 review 里挑行为变更的时间;测试覆盖率低的仓库,装了也只会得到一堆先补测试的回复。
给你自己写重构类 Prompt 的第一条建议:把约束写成定义,不要写成步骤。“没有测试就不叫重构”这类句式,比“第三步请运行测试”有效得多,因为 Agent 没法通过跳过步骤绕开一个定义。
第二条建议是给 Agent 留拒绝的出口。单独写一节“什么时候不要做”,明确列出可以回绝用户的条件。没有这一节,Agent 会把所有请求都当成必须执行的命令,而很多工程事故恰恰始于它不敢说不。

