mcpField
R
refactoring

refactoring

github.com/seb1n开发243146 次安装13 周前更新
代码仓库

关于 refactoring

这项技能指导 AI Agent 在不改变外部行为的前提下重构现有代码,适用于维护代码库的开发者。它涵盖代码异味识别、方案规划、逐步修改和测试验证。

主要功能

  1. 01识别代码异味
  2. 02选择重构模式
  3. 03规划小步修改顺序
  4. 04保持 API 与行为不变
  5. 05通过测试验证修改
  6. 06总结重构内容

适用场景

  1. 01拆分过长或嵌套的函数
  2. 02消除重复逻辑
  3. 03改进命名并简化条件

安装

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

$npx skills add https://github.com/seb1n/awesome-ai-agent-skills --skill refactoring

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

详细介绍

代码重构

此技能将指导 AI Agent 按照规范的流程重构现有代码,同时不改变其外部行为。重构可以提升可读性、降低复杂度,并让代码库更易于扩展和维护。Agent 会识别代码异味、提出有针对性的重构模式、安全地应用转换,并通过测试验证正确性。

工作流

  1. 识别代码异味:扫描目标代码中的常见质量问题——过长的函数、嵌套过深的条件语句、重复逻辑、变量作用域过宽、魔法数字、死代码以及参数列表过长。标出每处异味的位置,并简要说明其对代码库的影响。

  2. 选择重构模式:针对每处已识别的异味,选择最合适的重构模式。常见模式包括提取方法、重命名符号、简化条件语句、内联变量、将魔法数字替换为命名常量、移除死代码和引入参数对象。说明每项变更的权衡及预期改进。

  3. 规划变更顺序:确定安全的重构顺序。优先采用小型、彼此独立且可以单独验证的变更。将相关变更组合在一起(例如,先提取辅助函数再重命名),并避免交错进行互不相关的转换,以免难以回滚。

  4. 应用重构:每次应用一种模式来转换代码。保留原有的公共 API 和行为。使用符合语言习惯的结构——例如,Python 中的列表推导式、JavaScript 中的解构、Rust 中的模式匹配等。

  5. 运行测试并验证:每次转换后运行现有测试套件。如果没有测试,则生成轻量级单元测试,在变更前后覆盖重构涉及的代码路径。确认所有测试均通过,且没有引入回归问题。

  6. 记录变更:总结应用的每项重构、解决的异味,以及现在可以进行的后续改进。此总结可用作提交消息或 PR 描述。

支持的语言

  • Python
  • JavaScript / TypeScript
  • Java
  • Go
  • Rust
  • C / C++
  • Ruby

用法

提供要重构的代码,并可选地说明目标,例如“降低复杂度”“改进命名”或“拆分为更小的函数”。Agent 会分析代码、提出重构计划,并在获得批准后应用变更。你也可以指定整个文件或模块,让 Agent 对其进行全面的质量检查。

示例

示例 1 — 提取方法并简化条件语句(Python)

用户请求:“这个函数太长了,嵌套的 if 很难理解。请重构它。”

之前:

def register_user(payload):
    if payload.get("email"):
        if "@" in payload["email"]:
            if payload.get("password") and len(payload["password"]) >= 8:
                user = {"email": payload["email"], "active": True}
                db.save(user)
                send_welcome_email(user["email"])
                log.info(f"User {user['email']} registered")
                return user
            else:
                raise ValueError("Password must be at least 8 characters")
        else:
            raise ValueError("Invalid email format")
    else:
        raise ValueError("Email is required")

之后:

def register_user(payload):
    _validate_payload(payload)
    user = _create_user(payload["email"])
    _notify_and_log(user)
    return user

def _validate_payload(payload):
    if not payload.get("email"):
        raise ValueError("Email is required")
    if "@" not in payload["email"]:
        raise ValueError("Invalid email format")
    if not payload.get("password") or len(payload["password"]) < 8:
        raise ValueError("Password must be at least 8 characters")

def _create_user(email):
    user = {"email": email, "active": True}
    db.save(user)
    return user

def _notify_and_log(user):
    send_welcome_email(user["email"])
    log.info(f"User {user['email']} registered")

应用的模式:提取方法、展平嵌套条件语句(守卫子句)。

示例 2 — 消除重复并引入常量(TypeScript)

用户请求:“整理一下这个 Express 路由处理程序,里面有很多重复代码。”

之前:

app.post("/orders", async (req, res) => {
  if (!req.body.items || req.body.items.length === 0) {
    return res.status(400).json({ error: "Items are required" });
  }
  if (req.body.items.length > 50) {
    return res.status(400).json({ error: "Too many items" });
  }
  let total = 0;
  for (const item of req.body.items) {
    total += item.price * item.quantity;
  }
  if (total > 10000) {
    return res.status(400).json({ error: "Order exceeds maximum total" });
  }
  const order = { items: req.body.items, total: total, status: "pending" };
  await db.orders.insert(order);
  return res.status(201).json(order);
});

之后:

const MAX_ITEMS = 50;
const MAX_ORDER_TOTAL = 10_000;

app.post("/orders", async (req, res) => {
  const { items } = req.body;
  const validationError = validateOrder(items);
  if (validationError) {
    return res.status(400).json({ error: validationError });
  }

  const total = calculateTotal(items);
  if (total > MAX_ORDER_TOTAL) {
    return res.status(400).json({ error: "Order exceeds maximum total" });
  }

  const order = await createOrder(items, total);
  return res.status(201).json(order);
});

function validateOrder(items?: OrderItem[]): string | null {
  if (!items || items.length === 0) return "Items are required";
  if (items.length > MAX_ITEMS) return "Too many items";
  return null;
}

function calculateTotal(items: OrderItem[]): number {
  return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}

async function createOrder(items: OrderItem[], total: number) {
  const order = { items, total, status: "pending" as const };
  await db.orders.insert(order);
  return order;
}

应用的模式:提取方法、将魔法数字替换为命名常量、解构。

最佳实践

  • 保持重构小而原子化。 每项更改都应能独立验证,并且在出现问题时易于回退。
  • 绝不要同时进行重构和添加功能。 将行为更改与结构更改混在一起,会让 Bug 几乎无法追踪。
  • 保留公共 API。 除非用户明确要求重新设计 API,否则内部重构不应迫使调用方做出更改。
  • 充分利用测试套件。 如果测试覆盖率较低,请在重构前编写特征测试,以记录当前行为。
  • 使用保护子句简化深层嵌套的条件判断。 提前返回比给嵌套分支添加注释更能提升可读性。
  • 大胆重命名。 清晰的名称可以免去注释。名为 validate_email 的函数比名为 check、还需要注释说明用途的函数更好。

边界情况

  • 没有现有测试:在进行任何转换之前,生成能记录当前输入/输出行为的最小化测试。提醒用户,对正确性的信心取决于测试覆盖率。
  • 模块紧密耦合:如果重构某个模块会破坏另一个模块中的导入或契约,请先梳理依赖关系图,并在提取逻辑前提出接口边界方案。
  • 生成的代码或引入的代码:不要重构自动生成的文件(例如 protobuf 存根、ORM 迁移文件)。标记这些文件并跳过。
  • 性能关键的热点路径:有些“难看”的代码是经过刻意优化的。在用可能导致性能下降的高层抽象替换手工调优的循环之前,请先向用户确认。
  • 格式风格混杂:如果文件中的风格不一致(制表符与空格、引号风格),请在重构后运行项目的格式化工具,而不要在重构过程中手动调整格式。

评论

支持 Markdown