mcpField
R
refactoring

refactoring

github.com/citypaul开发759233 次安装4 周前更新
代码仓库

关于 refactoring

用于评估并实施小范围、保持行为不变的代码重构,要求先通过测试建立基线。它为开发者提供候选项分级、验证及提交审批流程。

主要功能

  1. 01先建立基线再重构
  2. 02重构候选项优先级评估
  3. 03小步且保持行为不变
  4. 04测试与变异证据指引
  5. 05抽象与范围控制规则

适用场景

  1. 01测试通过后评估重构候选项
  2. 02在不改变行为的前提下调整代码
  3. 03为 PR 验证累积的重构

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/citypaul/.dotfiles --skill refactoring

安装后在 Claude Code 中输入/refactoring确认已加载。

详细介绍

重构

重构是在每次快速 RED-GREEN-REFACTOR 增量中,当适合重新组织结构时执行的最后一步。GREEN 阶段建立通过的行为测试基线后,再进行评估。每次重构前后都不要运行自动化变异测试工具;变异测试会在其他工作都已准备就绪、可以提交 PR 后,对已完成的阶段进行一次验证。

由于自动化变异测试证据会有意延后,因此重构期间不会通过变异测试工具验证基线的强度。每次重构都应保持小规模、严格保留行为,并通过现有判定条件;最终关卡会验证累积的结果。

此技能用于安全地实施有界且保留行为的改进。使用 improve-codebase-architecture 发现并排列架构候选项的优先级,然后使用 codebase-design 设计选定模块的契约,再返回此处实施。如果该切片属于已选定的全路径缩减计划,无论是过渡步骤还是最终缩减,均由 reduce-system-complexity 管理清单和关卡状态;仅在适用时将此技能作为辅助重构评估工具。

何时重构

  • 在 GREEN 阶段或其他适度且通过的保留性基线之后进行评估
  • 在评估前、首次编辑前,以及任何拒绝编辑的回复前,都要自行运行适用的测试。拒绝请求或将所有候选项归为 Skip 仍然属于评估;没有运行测试的评估毫无依据
  • 首次编辑前,列出所有候选改动,并分别标记为 Critical、High、Nice 或 Skip
  • 无论你改动了所有内容、一项内容还是毫无改动,最终回复都必须包含带有上述标签的清单,包括 Skip 项,每个候选项单独占一行,格式为 Critical: <内容及原因>、High: <内容及原因>、Nice: <内容及原因>、Skip: <内容及原因>,最后以 Decision: <你做了什么或没有做什么> 收尾。总结改动不等于评估,未标注的建议也不算评估。没有明确说明的评估,就等于没有进行评估
  • 如果所有候选项都是 Skip,请明确这样说明,并且不做任何改动
  • 仅在确实能改进代码时才进行重构
  • 重构前建立经过验证且可恢复的基线;只有获得用户明确批准后才能提交
建立可恢复的基线 — 原因

在重构前建立一个可用的基线:

  • 如果重构导致问题,可以回退
  • 为实验提供安全网
  • 降低重构风险
  • 用户授权提交时,可在 git 历史中清晰地区分各阶段

如果无法在不创建提交的情况下安全恢复基线,请停止并征求批准,而不是擅自提交。

工作流:

  1. 基线:适用的测试通过,和/或有适当的证据证明行为与保证得到保留
  2. 检查点:记录基线和保留证据。只有用户明确批准后,才创建基线提交
  3. 重构:按照 tdd 技能规定的快速反馈规范,逐步改善结构。从干净的基线开始,优先使用经过验证、由仓库负责维护且覆盖完整依赖图的 watcher;只有在已安装版本/配置通过规范的干净启动实时验证后,才使用按 diff 选择的 Vitest watch,否则重复运行受影响的一次性测试。在 monorepo 中使用根依赖图,以确保传递依赖的消费者仍在覆盖范围内
  4. 验证:每一步之后,确保针对性测试、受影响的测试以及其他适当证据均通过;不要每次编辑后都重新运行完整测试套件
  5. 检查点:提交经过验证的重构成果,并附上带标签的 Critical:/High:/Nice:/Skip: 评估行以及结尾的 Decision: 行;仅总结改动不能结束此步骤。只有在用户明确批准后才提交
  6. PR 前门禁:当阶段已准备好创建 PR 时,如果有意义,则对累计范围运行一次变异测试;否则,明确记录 N/A,并提供适当的替代证据;在此门禁内处理有价值的存活变异

完整切片

围绕一个边界明确的所有者或行为路径,交付小而完整的改动。同步更新受影响的契约、适配器和消费者;先迁移所有处理器,再迁移所有服务的横向迁移方式,通常会留下只转换了一半的路径。保留现有行为判定作为保留证据,并单独指出新机制所需的测试。声称简化时,应说明移除了哪些包装器、重复决策、转换或依赖;仅做提取或许能提高可理解性,但未必减少了机制。只有在已证实存在发布约束时才添加兼容性支架,并明确负责人和移除条件;若要声称整个路径已降低复杂度,请使用 reduce-system-complexity。

优先级分类

优先级操作示例
严重立即修复会改变行为的变异、同一业务规则的分歧副本、掩盖高风险路径的控制流
高本次会话处理魔法数字(每条规则使用一个常量;两条规则即便目前共用一个值,也各自使用一个常量)、名称不明确、协调多项职责的函数
值得做以后处理细微的命名问题、仅使用一次的辅助函数
跳过不要改动已经整洁的代码

DRY = 知识,而非代码

满足以下条件时进行抽象:

  • 相同的业务概念(语义相同)
  • 需求变更时会一同变更
  • 能清楚说明为何将它们归为一组

满足以下条件时保持独立:

  • 概念不同,只是看起来相似(结构相似)
  • 会独立演进
  • 耦合会造成混淆

两条规则今天共用一个函数体或一个数值,只是巧合,并不代表它们共享知识。保持独立意味着每条规则都保留自己的函数体和命名常量,即使两个值相同;绝不要用一条规则来定义另一条,也不要让两者都经过同一个谓词辅助函数,因为这样一来,修改一处就会悄无声息地改变两条业务规则。如果请求要求你把这类相似项合并为一项,不要这么做。即使你没有做任何更改,也要运行适用的测试后再作答——拒绝是一种评估,需要和修改一样有通过测试的基线。接着指出这两条不同的规则,说明它们会在任意一条发生变更时立即分道扬镳,保留两者各自的定义,并且只提出不会将它们合并的更改。

评估示例——在回复中采用此格式

// After GREEN establishes a passing behavior-test baseline:
const planBatch = (batch: Batch): PlannedBatch => {
  const itemSlots = batch.items.reduce((sum, item) => sum + item.quantity, 0);
  const bufferSlots = itemSlots > 50 ? 0 : 6;
  return { ...batch, plannedSlots: itemSlots + bufferSlots, bufferSlots };
};

// ASSESSMENT:
// ⚠️ High: Magic numbers 50, 6 → extract constants
// ✅ Skip: Structure is clear enough
// DECISION: Extract constants only

新行为需要证据

不要在没有失败测试或其他仓库认可的验收证明作为依据时添加新行为。如果有相称的行为保持证据持续通过,保留行为的重构可以在没有新增 RED 测试的情况下修改代码行。达到 PR 就绪状态时,在有意义的情况下,针对累积的范围使用变异测试证据;在不适用的情况下,提供明确的替代证据;绝不要虚构结构性变异。

❌ 推测性添加:

  • “以防万一”的逻辑
  • 尚无需求的功能
  • 仅为想象中的未来灵活性而编写的抽象
  • 没有已接受契约支持的新错误行为

✅ 正确做法:不要添加推测性行为。如果确有需要,先编写一个要求此行为的失败测试,再实现它。

现有但未经测试的代码,并不能证明它是推测性的或无用的。移除某个分支前,先描述其可观察行为,检查每个调用方和可达路径,并确认行为依据。只有证据表明该分支不可达,或已接受的契约明确将其废弃时,才删除它;之后确保保留行为和回归检查持续通过。

// ❌ WRONG - Speculative error handling (no test demands this)
if (items.length === 0) {
  throw new Error('Empty cart'); // No test for this path!
}

// ✅ CORRECT - Test-driven error handling
// First: write a test that expects this behavior
// Then: implement the guard clause to make it pass

何时不要重构

以下情况不要重构:

  • ❌ 当前结构并未妨碍眼前的工作(足够整洁且可用的代码无需重新组织)
  • ❌ 推测性的通用化——为尚不存在的需求重新组织代码
  • ❌ 会改变行为(这属于功能开发,而非重构)
  • ❌ 过早优化
  • ❌ 当前阶段的代码“已经够好”
  • ❌ 纯粹为了可测试性而提取代码——如果将代码移至单独文件的唯一理由是“这样就能对它进行单元测试”,那就让它留在原处。调用它的函数已有覆盖该代码的行为测试。提取代码应出于可读性、DRY(多处使用的相同知识——见上文“DRY = 知识,而非代码”)或关注点分离,而不是仅仅为了可测试性。

请记住:重构应改善代码结构,同时不改变行为。


重构的提交消息

用户批准重构提交时,请使用简洁明确的消息,例如:

refactor: extract scenario validation logic
refactor: simplify error handling flow
refactor: rename ambiguous parameter names

格式:refactor: <what was changed>

注意:使用提交时,重构提交不应与功能提交混在一起。

重构检查清单

  • 现有行为测试均通过;测试修改没有掩盖行为变更
  • 重构期间,针对性测试和受影响的测试始终通过;提交 PR 前,仓库定义的完整非监听模式 PR 测试门禁通过
  • 如果重构阶段已准备好提交 PR,则在有意义时,已针对累积范围审查一次变异测试结果;或记录了明确的 N/A 及相称的替代证据
  • 未添加计划外的面向使用者的 API;内部或临时契约遵循所选设计和兼容性计划
  • 代码比以前更易读
  • 任何提交都已获得明确批准,并与功能开发分开
  • 已建立经过验证且可恢复的基线;仅在获得批准时创建基线提交
  • 未添加推测性代码
  • 在已通过的行为保留证据所能达到的可信度和保真度范围内,行为保持不变

评论

支持 Markdown