第二节:代码重构实战
安全重构与性能优化

作者:小学子 📚 | 日期:2026年4月2日 | 第十阶段 · 模块十


# 第十阶段 · 模块十 · 第二节:代码重构实战

核心问题

如何使用 Claude Code 进行代码重构?/simplify 命令的完整流程是什么?如何确保重构的安全性?


◇ 本节位置


        Claude Code 全局架构
        
        ┌─────────────────────────────────────────────────────────────────────┐
        │  实战案例                                                            │
        │                                                                      │
        │  代码重构实战 ← 本节                                             │
        │  ├── /simplify 命令                                                │
        │  ├── 三阶段审查                                                     │
        │  └── 重构安全策略                                                   │
        └─────────────────────────────────────────────────────────────────────┘
        


一、重构概述

1.1 什么是重构


        ┌─────────────────────────────────────────────────────────────────────┐
        │  重构(Refactoring)                                                │
        │                                                                      │
        │  定义:改善代码结构而不改变其行为                                    │
        │                                                                      │
        │  与修复 Bug 的区别:                                                 │
        │  - 重构:不改变功能,改进结构                                       │
        │  - 修复 Bug:改变行为,修复错误                                      │
        └─────────────────────────────────────────────────────────────────────┘
        

1.2 Claude Code 的重构能力

源码位置:`src/skills/bundled/simplify.ts`


        // /simplify 命令 = 代码审查 + 重构
        
        // 功能:
        // 1. 代码复用审查
        // 2. 代码质量审查
        // 3. 效率审查
        
        // 特点:
        // - 自动修复发现的问题
        // - 三阶段并行审查
        

1.3 五问分析

问 1:什么时候应该重构?


        // 应该重构:
        // - 代码重复
        // - 函数过长
        // - 难以理解
        // - 难以测试
        
        // 不应该重构:
        // - 代码已经稳定
        // - 重构风险过高
        // - 短期要废弃的代码
        


二、/simplify 命令详解

2.1 命令执行


        # 简化当前更改
        claude /simplify
        
        # 指定焦点
        claude /simplify 专注于性能优化
        

2.2 三阶段审查

源码位置:`src/skills/bundled/simplify.ts`


        ┌─────────────────────────────────────────────────────────────────────┐
        │  Phase 1: 识别更改                                                   │
        │  运行 git diff 查看变更                                              │
        └─────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
        ┌─────────────────────────────────────────────────────────────────────┐
        │  Phase 2: 三阶段并行审查                                             │
        │                                                                      │
        │  ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐       │
        │  │ Agent 1         │ │ Agent 2         │ │ Agent 3         │       │
        │  │ 代码复用审查     │ │ 代码质量审查     │ │ 效率审查         │       │
        │  └─────────────────┘ └─────────────────┘ └─────────────────┘       │
        └─────────────────────────────────────────────────────────────────────┘
                                      │
                                      ▼
        ┌─────────────────────────────────────────────────────────────────────┐
        │  Phase 3: 修复问题                                                   │
        │  汇总发现并直接修复                                                  │
        └─────────────────────────────────────────────────────────────────────┘
        

2.3 五问分析

问 1:为什么使用三个 Agent 并行审查?


        // 并行审查的优势:
        
        // 1. 速度
        // - 三个审查并行执行
        // - 比串行快 3 倍
        
        // 2. 专注
        // - 每个 Agent 专注一个领域
        // - 避免交叉干扰
        
        // 3. 全面
        // - 同时覆盖多个维度
        // - 不会遗漏问题
        


三、Agent 1:代码复用审查

3.1 审查内容

源码位置:`src/skills/bundled/simplify.ts`


        // Agent 1: Code Reuse Review
        
        // 审查点:
        
        // 1. 搜索现有工具
        // - utility 目录
        // - 共享模块
        // - 相邻文件
        
        // 2. 标记重复功能
        // - 新函数是否已有实现
        // - 建议使用现有函数
        
        // 3. 标记内联逻辑
        // - 字符串处理
        // - 路径处理
        // - 环境检查
        

3.2 常见问题


        // 问题示例:
        
        // ❌ 不好:手写字符串处理
        const parts = str.split(',').map(s => s.trim())
        
        // ✅ 好:使用现有工具
        import { splitAndTrim } from '@utils/string'
        const parts = splitAndTrim(str)
        

3.3 五问分析

问 1:如何找到可以复用的代码?


        // 方法:
        
        // 1. 搜索关键词
        // - "util"
        // - "helper"
        // - "common"
        
        // 2. 查看相邻文件
        // - 同目录下的工具文件
        // - 同包内的共享模块
        
        // 3. 询问 Claude
        // "这个逻辑有没有现有的实现?"
        


四、Agent 2:代码质量审查

4.1 审查内容

源码位置:`src/skills/bundled/simplify.ts`


        // Agent 2: Code Quality Review
        
        // 审查点:
        
        // 1. 冗余状态
        // - 重复的 state
        // - 可以推导的缓存值
        
        // 2. 参数蔓延
        // - 函数参数过多
        // - 应该泛化或重构
        
        // 3. 复制粘贴变体
        // - 相似的代码块
        // - 应该统一抽象
        
        // 4. 泄露抽象
        // - 暴露内部细节
        // - 破坏抽象边界
        
        // 5. 字符串类型
        // - 使用原始字符串
        // - 应该使用常量或枚举
        
        // 6. 不必要的 JSX 嵌套
        // 7. 不必要的注释
        

4.2 常见问题


        // 问题示例:
        
        // ❌ 冗余状态
        const [items, setItems] = useState([])
        const [filteredItems, setFilteredItems] = useState([]) // 可以推导
        
        // ✅ 好:派生状态
        const filteredItems = useMemo(() =>
          items.filter(...), [items])
        
        // ❌ 字符串类型
        if (type === 'user') // magic string
        
        // ✅ 好:使用常量
        if (type === UserType.User)
        

4.3 五问分析

问 1:什么时候应该统一抽象?


        // 应该统一抽象:
        // - 三个或更多相似实现
        // - 行为相同,细节不同
        // - 未来可能继续变化
        
        // 不应该统一抽象:
        // - 只有两个相似实现
        // - 未来可能分化
        // - 抽象会带来复杂性
        


五、Agent 3:效率审查

5.1 审查内容

源码位置:`src/skills/bundled/simplify.ts`


        // Agent 3: Efficiency Review
        
        // 审查点:
        
        // 1. 不必要的工作
        // - 冗余计算
        // - 重复文件读取
        // - N+1 模式
        
        // 2. 错过的并发
        // - 独立操作顺序执行
        // - 可以并行化
        
        // 3. 热路径膨胀
        // - 启动时的阻塞
        // - 每次请求的处理
        
        // 4. 不必要的存在检查
        // - TOCTOU 反模式
        // - 直接操作,处理错误
        
        // 5. 内存问题
        // - 无界数据结构
        // - 事件监听器泄漏
        
        // 6. 过度宽泛的操作
        // - 读取整个文件
        // - 加载所有项目
        

5.2 常见问题


        // 问题示例:
        
        // ❌ N+1 查询
        for (const user of users) {
          const posts = await getPosts(user.id)
        }
        
        // ✅ 好:批量查询
        const userIds = users.map(u => u.id)
        const posts = await getPostsByUserIds(userIds)
        
        // ❌ 每次渲染都读取文件
        const config = readFileSync('config.json') // 阻塞
        
        // ✅ 好:缓存
        const config = useMemo(() =>
          readFileSync('config.json'), [])
        

5.3 五问分析

问 1:如何避免 N+1 查询?


        // N+1 查询 = 循环中每次查询
        
        // 解决方法:
        
        // 1. 批量查询
        // - 收集所有 ID
        // - 一次查询
        
        // 2. JOIN 查询
        // - 在数据库层合并
        
        // 3. 缓存
        // - 使用 DataLoader 模式
        


六、重构安全策略

6.1 重构前


        // 重构前检查:
        
        // 1. 确保有测试
        // - 单元测试
        // - 集成测试
        
        // 2. 备份
        // - git commit
        // - 或创建备份分支
        
        // 3. 理解代码
        // - 阅读相关测试
        // - 理解依赖关系
        

6.2 重构中


        // 重构中原则:
        
        // 1. 小步前进
        // - 每次只改一件事
        // - 提交频繁
        
        // 2. 保持测试通过
        // - 每次修改后运行测试
        // - 不要积累大量更改
        
        // 3. 保持可逆
        // - 如果出错,容易回滚
        

6.3 五问分析

问 1:如何确保重构不破坏功能?


        // 方法:
        
        // 1. 测试驱动重构
        // - 先写测试
        // - 然后重构
        
        // 2. 渐进式重构
        // - 每次改一点
        // - 频繁运行测试
        
        // 3. 对比测试
        // - 重构前后行为对比
        // - 确保输出一致
        


七、实战示例

7.1 场景:重构字符串处理


        // 原始代码
        function processUserInput(input: string): string[] {
          const trimmed = input.trim()
          const parts = trimmed.split(',')
          const result: string[] = []
          for (const part of parts) {
            result.push(part.trim())
          }
          return result
        }
        

7.2 Claude 的审查


        Agent 1 (代码复用):
        - 发现手写的 split + trim
        - 建议使用 @utils/string 包的 splitAndTrim
        
        Agent 2 (代码质量):
        - 可以简化为一行
        - 参数名可以更清晰
        
        Agent 3 (效率):
        - 性能良好,无需优化
        

7.3 重构后


        // ✅ 重构后
        import { splitAndTrim } from '@utils/string'
        
        function processUserInput(input: string): string[] {
          return splitAndTrim(input, ',')
        }
        

7.4 五问分析

问 1:重构前后代码行为一致吗?


        // 测试验证:
        // input: "  a, b , c  "
        // 重构前: ["a", "b", "c"]
        // 重构后: ["a", "b", "c"]
        // ✅ 一致
        


八、思考题

思考题 1:重构和重写的区别?

答案


        // 重构(Refactoring):
        // - 改善结构,不改变行为
        // - 渐进式,小步前进
        // - 保持测试通过
        
        // 重写(Rewrite):
        // - 重新实现,从头开始
        // - 大爆炸,一次完成
        // - 风险更高
        


思考题 2:什么时候应该重写而不是重构?

答案


        // 考虑重写的场景:
        
        // 1. 代码库太小
        // - 重写比重构更快
        
        // 2. 架构彻底错误
        // - 重构无法解决
        
        // 3. 技术过时
        // - 无法找到维护者
        
        // 4. 需求根本改变
        // - 现有代码不适用
        


思考题 3:如何说服团队进行重构?

答案


        // 说服策略:
        
        // 1. 量化问题
        // - "这个函数有 500 行"
        // - "每次修改需要 2 小时理解"
        
        // 2. 展示收益
        // - "重构后修改只需 10 分钟"
        // - "测试覆盖率从 30% 提升到 80%"
        
        // 3. 降低风险
        // - "小步前进"
        // - "有测试保护"
        // - "可以随时停止"
        


九、延伸阅读

资源说明
/simplify 命令代码审查 + 重构
/review 命令代码审查
Martin Fowler《重构》经典参考书


十、下节预告

下一节我们将深入 Bug 修复实战

- Bug 分析方法

- 调试技巧

- 修复验证


*- 第一轮:□ 事实准确性*

*- 第二轮:□ 深度与洞见*

*- 第三轮:□ 可读性与价值*