关于 refactoring
这项技能指导 AI Agent 在不改变外部行为的前提下重构现有代码,适用于维护代码库的开发者。它涵盖代码异味识别、方案规划、逐步修改和测试验证。
主要功能
- 01识别代码异味
- 02选择重构模式
- 03规划小步修改顺序
- 04保持 API 与行为不变
- 05通过测试验证修改
- 06总结重构内容
适用场景
- 01拆分过长或嵌套的函数
- 02消除重复逻辑
- 03改进命名并简化条件
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ seb1n/ awesome-ai-agent-skills --skill refactoring安装后在 Claude Code 中输入/refactoring确认已加载。
详细介绍
代码重构
此技能将指导 AI Agent 按照规范的流程重构现有代码,同时不改变其外部行为。重构可以提升可读性、降低复杂度,并让代码库更易于扩展和维护。Agent 会识别代码异味、提出有针对性的重构模式、安全地应用转换,并通过测试验证正确性。
工作流
-
识别代码异味:扫描目标代码中的常见质量问题——过长的函数、嵌套过深的条件语句、重复逻辑、变量作用域过宽、魔法数字、死代码以及参数列表过长。标出每处异味的位置,并简要说明其对代码库的影响。
-
选择重构模式:针对每处已识别的异味,选择最合适的重构模式。常见模式包括提取方法、重命名符号、简化条件语句、内联变量、将魔法数字替换为命名常量、移除死代码和引入参数对象。说明每项变更的权衡及预期改进。
-
规划变更顺序:确定安全的重构顺序。优先采用小型、彼此独立且可以单独验证的变更。将相关变更组合在一起(例如,先提取辅助函数再重命名),并避免交错进行互不相关的转换,以免难以回滚。
-
应用重构:每次应用一种模式来转换代码。保留原有的公共 API 和行为。使用符合语言习惯的结构——例如,Python 中的列表推导式、JavaScript 中的解构、Rust 中的模式匹配等。
-
运行测试并验证:每次转换后运行现有测试套件。如果没有测试,则生成轻量级单元测试,在变更前后覆盖重构涉及的代码路径。确认所有测试均通过,且没有引入回归问题。
-
记录变更:总结应用的每项重构、解决的异味,以及现在可以进行的后续改进。此总结可用作提交消息或 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 迁移文件)。标记这些文件并跳过。
- 性能关键的热点路径:有些“难看”的代码是经过刻意优化的。在用可能导致性能下降的高层抽象替换手工调优的循环之前,请先向用户确认。
- 格式风格混杂:如果文件中的风格不一致(制表符与空格、引号风格),请在重构后运行项目的格式化工具,而不要在重构过程中手动调整格式。