Files
EmailBill/.opencode/skills/code-refactoring/SKILL.md
SunCheng 3e18283e52 1
2026-02-09 19:25:51 +08:00

467 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
name: code-refactoring
description: 代码重构技能 - 强调保持功能不变的前提下优化代码结构,充分理解需求和交互式确认
metadata:
tags:
- refactoring
- code-quality
- clean-code
- interactive
version: 1.0.0
---
# 代码重构技能
## 技能概述
专门用于在**不改变现有功能逻辑**的前提下优化代码结构,包括:
- 抽取公共方法、组件和工具类
- 消除重复代码DRY原则
- 移除无用代码(死代码、注释代码、未使用的依赖)
- 改善代码可读性和可维护性
- 优化代码结构和命名规范
## ⚠️ 核心原则MUST FOLLOW
### 1. 功能不变保证
**禁止在重构过程中改变功能行为!**
- ✅ 重构前后的输入输出必须完全一致
- ✅ 重构前后的副作用必须一致数据库操作、文件IO、日志等
- ✅ 重构不应改变性能特征(除非明确以性能优化为目标)
- ❌ 严禁"顺便"添加新功能或修复bug
### 2. 充分理解需求
**禁止根据模糊的需求开始重构!**
- ✅ 彻底理解重构的目标和范围
- ✅ 识别需求中的模糊点和二义性
- ✅ 使用 `question` 工具获取明确的用户意图
- ❌ 不要基于假设进行重构
### 3. 先确认再动手
**禁止未经用户确认就直接修改代码!**
- ✅ 先列出所有修改点和影响范围
- ✅ 使用 `question` 工具让用户确认重构方案
- ✅ 获得明确的同意后再执行修改
- ❌ 不要边分析边修改
## ⚠️ 强制交互规则MUST FOLLOW
**遇到需要用户确认的情况时,必须立即调用 `question` 工具:**
**禁止**"我需要向用户确认..."、"建议向用户询问..."、"在执行前应该确认..."
**必须**:直接调用 `question` 工具,不要描述或延迟
**调用格式**
```javascript
question({
header: "重构确认",
questions: [{
question: "是否要将重复的验证逻辑抽取到公共方法中?",
options: ["是,抽取到工具类", "是,抽取到基类", "否,保持现状", "其他"]
}]
})
```
**规则**
- 每次最多 **3个问题**
- 每个问题 **3-6个选项**(穷举常见情况 + "其他"兜底)
- 用户通过**上下键导航**选择
- 适用于**所有阶段**(需求理解、方案确认、风险评估)
## 重构流程
### 阶段1: 需求理解(必须交互确认)
#### 1.1 理解重构目标
**获取用户意图**
- 用户想重构什么?(文件、模块、类、方法)
- 重构的原因是什么?(代码重复、难以维护、命名不清晰、结构混乱)
- 期望达到什么效果?(提高复用性、提升可读性、简化逻辑、统一规范)
**触发 `question` 工具的场景**
- 用户只说"重构这个文件"但未说明具体问题
- 用户提到"优化"但没有明确优化方向
- 用户的需求包含多个可能的重构方向
- 重构范围不明确(单个文件 vs 整个模块)
**示例问题**
```javascript
question({
header: "明确重构目标",
questions: [
{
question: "您主要关注哪方面的重构?",
options: [
"抽取重复代码",
"改善命名和结构",
"移除无用代码",
"提取公共组件/方法",
"全面优化"
]
},
{
question: "重构范围是?",
options: [
"仅当前文件",
"当前模块(相关的几个文件)",
"整个项目",
"让我分析后建议"
]
}
]
})
```
#### 1.2 识别约束条件
**必须明确的约束**
- 是否有不能改动的接口或API对外暴露的
- 是否有特殊的性能要求
- 是否需要保持特定的代码风格
- 是否有测试覆盖(如有,重构后测试必须通过)
**触发 `question` 工具的场景**
- 发现公开API可能需要调整
- 代码涉及性能敏感的操作
- 存在多种重构方式,各有权衡
- 不确定某些代码是否仍在使用
**示例问题**
```javascript
question({
header: "重构约束确认",
questions: [
{
question: "发现 `ProcessData` 方法被多个外部模块调用,重构时:",
options: [
"保持方法签名不变,仅优化内部实现",
"可以修改方法签名,我会同步更新调用方",
"先告诉我影响范围,我再决定",
"其他"
]
}
]
})
```
#### 1.3 理解代码上下文
**分析现有代码**
- 使用 `semantic_search` 查找相关代码
- 使用 `grep_search` 查找重复模式
- 使用 `list_code_usages` 分析调用关系
- 阅读相关文件理解业务逻辑
**注意事项**
- 不要在分析阶段进行任何修改
- 记录发现的问题点和重构机会
- 识别可能的风险和边界情况
### 阶段2: 方案设计(必须交互确认)
#### 2.1 列出重构点
**详细列出每个修改点**
- 修改的文件和位置
- 修改的具体内容(前后对比)
- 修改的原因和收益
- 可能的影响范围
**示例格式**
```
## 重构点清单
### 1. 抽取重复的数据验证逻辑
**位置**: TransactionController.cs (L45-L60, L120-L135)
**操作**: 将重复的金额验证逻辑抽取到 ValidationHelper.ValidateAmount()
**原因**: 两处代码完全相同违反DRY原则
**影响**: 无,纯内部优化
### 2. 移除未使用的导入和变量
**位置**: BudgetService.cs (L5, L23)
**操作**: 删除 `using System.Text.RegularExpressions;` 和未使用的 `_tempValue` 字段
**原因**: 死代码,增加维护负担
**影响**: 无
### 3. 重命名方法提高可读性
**位置**: DataProcessor.cs (L89)
**操作**: `DoWork()` → `ProcessTransactionData()`
**原因**: 原名称不够清晰,无法表达具体功能
**影响**: 4个调用点需要同步更新
```
#### 2.2 评估风险和影响
**必须分析的风险**
- 是否影响公开API
- 是否影响性能
- 是否影响测试
- 是否涉及数据迁移
- 是否存在隐藏的依赖关系
**触发 `question` 工具的场景**
- 发现重构会影响多个模块
- 存在潜在的兼容性问题
- 有多种实现方式可选
- 需要在代码质量和改动风险间权衡
**示例问题**
```javascript
question({
header: "重构方案确认",
questions: [
{
question: "发现3处重复的日期格式化代码建议",
options: [
"抽取到工具类Common项目",
"抽取到当前服务的私有方法",
"保留重复(代码简单,抽取收益小)",
"让我看看代码再决定"
]
},
{
question: "重构会影响4个controller和2个service是否继续",
options: [
"是,一次性全部重构",
"否,先重构影响小的部分",
"告诉我每个的影响详情",
"其他"
]
}
]
})
```
#### 2.3 提交方案供确认
**必须向用户展示**
1. 完整的重构点清单如2.1格式)
2. 风险评估和影响分析
3. 建议的执行顺序
4. 预计改动的文件数量
**必须调用 `question` 工具获得最终确认**
```javascript
question({
header: "最终确认",
questions: [{
question: "我已列出所有重构点和影响分析,是否开始执行?",
options: [
"是,按计划执行",
"需要调整部分重构点",
"取消重构",
"其他问题"
]
}]
})
```
**重要**
- ❌ 不要在得到明确的"是,按计划执行"之前修改任何代码
- ❌ 不要假设用户会同意
- ✅ 如用户选择"需要调整"返回阶段1重新理解需求
### 阶段3: 执行重构
#### 3.1 执行原则
- **小步快跑**: 一次完成一个重构点,不要多个同时进行
- **频繁验证**: 每完成一个点就运行测试或构建验证
- **保持可逆**: 确保随时可以回滚
- **记录进度**: 使用 `manage_todo_list` 跟踪进度
#### 3.2 执行步骤
1. **创建TODO清单**:
```javascript
manage_todo_list({
todoList: [
{
id: 1,
title: "抽取重复验证逻辑到ValidationHelper",
description: "TransactionController.cs L45-L60, L120-L135",
status: "not-started"
},
{
id: 2,
title: "移除BudgetService.cs中的未使用导入",
description: "删除using System.Text.RegularExpressions",
status: "not-started"
},
// ... 更多任务
]
})
```
2. **逐个执行**:
- 标记任务为 `in-progress`
- 使用 `multi_replace_string_in_file``replace_string_in_file` 修改代码
- 运行测试验证: `dotnet test``pnpm test`
- 标记任务为 `completed`
- 继续下一个
3. **验证每个步骤**:
- 后端重构后运行: `dotnet build && dotnet test`
- 前端重构后运行: `pnpm lint && pnpm build`
- 确保没有引入编译错误或测试失败
#### 3.3 异常处理
**如果遇到预期外的问题**
- ✅ 立即停止后续重构
- ✅ 报告问题详情
- ✅ 调用 `question` 工具询问如何处理
```javascript
question({
header: "重构遇到问题",
questions: [{
question: "抽取方法后发现测试 `TestValidation` 失败了,如何处理?",
options: [
"回滚这个改动",
"修复测试用例",
"暂停,我来看看",
"继续其他重构点"
]
}]
})
```
### 阶段4: 验证和总结
#### 4.1 全面验证
**必须执行的验证**
- 所有单元测试通过
- 项目成功构建
- Lint检查通过
- 关键功能手动验证(如适用)
**验证命令**
```bash
# 后端
dotnet clean
dotnet build EmailBill.sln
dotnet test WebApi.Test/WebApi.Test.csproj
# 前端
cd Web
pnpm lint
pnpm build
```
#### 4.2 总结报告
**提供清晰的总结**
```
## 重构完成总结
### ✅ 已完成的重构
1. 抽取重复验证逻辑 (ValidationHelper.cs)
- 消除了 3 处重复代码
- 减少代码行数 45 行
2. 移除未使用的导入和变量
- BudgetService.cs: 移除 2 个未使用的 using
- TransactionController.cs: 移除 1 个未使用字段
3. 改善方法命名
- DoWork → ProcessTransactionData (4 处调用点已更新)
- Calculate → CalculateMonthlyBudget (2 处调用点已更新)
### 📊 重构影响
- 修改文件数: 6
- 新增文件数: 1 (ValidationHelper.cs)
- 删除代码行数: 78
- 新增代码行数: 42
- 净减少代码: 36 行
### ✅ 验证结果
- ✓ 所有测试通过 (23/23)
- ✓ 项目构建成功
- ✓ Lint检查通过
- ✓ 功能验证正常
### 📝 建议的后续工作
- 考虑为 ValidationHelper 添加单元测试
- 可以进一步重构 DataProcessor 类的其他方法
```
## 常见重构模式
### 1. 抽取公共方法
**识别标准**: 代码块在多处重复出现≥2次
**操作**:
- 创建独立方法或工具类
- 保持方法签名简洁明确
- 添加必要的注释和文档
### 2. 抽取公共组件
**识别标准**: UI组件或业务逻辑在多个视图/页面重复
**操作**:
- 创建可复用组件Vue组件、Service类等
- 使用Props/参数传递可变部分
- 确保组件职责单一
### 3. 移除死代码
**识别标准**:
- 未被调用的方法
- 未被使用的变量、导入、依赖
- 注释掉的代码
**操作**:
- 使用 `list_code_usages` 确认真正未使用
- 谨慎删除(可能有隐式调用)
- 使用Git历史作为备份
### 4. 改善命名
**识别标准**:
- 名称不能表达意图(如 `DoWork`, `Process`, `temp`
- 名称与实际功能不符
- 违反命名规范
**操作**:
- 使用 `list_code_usages` 找到所有使用点
- 使用 `multi_replace_string_in_file` 批量更新
- 确保命名符合项目规范见AGENTS.md
### 5. 简化复杂逻辑
**识别标准**:
- 深层嵌套(>3层
- 过长方法(>50行
- 复杂条件判断
**操作**:
- 早返回模式guard clauses
- 拆分子方法
- 使用策略模式或查表法
## 注意事项
### ❌ 不要做
- 在重构中添加新功能
- 在重构中修复bug除非bug是重构导致的
- 未经确认就大范围修改
- 改变公开API而不考虑兼容性
- 跳过测试验证
### ✅ 要做
- 保持每次重构的范围可控
- 频繁提交代码(每完成一个重构点提交一次)
- 确保测试覆盖率不降低
- 保持代码风格一致
- 记录重构的原因和收益
## 项目特定规范
### C# 代码重构
- 遵循 `AGENTS.md` 中的 C# 代码风格
- 使用 file-scoped namespace
- 公共方法使用 XML 注释
- 业务逻辑使用中文注释
- 工具方法考虑放入 `Common` 项目
### Vue/TypeScript 代码重构
- 使用 Composition API
- 组件放入 `src/components`
- 遵循 ESLint 和 Prettier 规则
- 使用 `@/` 别名避免相对路径
- 提取的组件使用 Vant UI 风格
## 总结
代码重构是一个**谨慎的、迭代的、需要充分确认的**过程。核心要点:
1. **理解先于行动** - 彻底理解需求和约束
2. **交互式确认** - 使用 `question` 工具消除歧义
3. **计划后执行** - 列出修改点并获得确认
4. **小步快跑** - 逐个完成重构点,频繁验证
5. **功能不变** - 始终确保行为一致性