refactoring
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRefactoring
代码重构
Overview
概述
This skill focuses on improving code quality through systematic refactoring techniques. It identifies code smells and applies proven refactoring patterns to enhance maintainability while preserving functionality.
Use this skill when the user requests:
- Code restructuring or cleanup
- Reducing technical debt
- Improving code organization
- Applying design patterns
- Breaking up large files or functions
- Removing duplication
- Modernizing legacy code
- Improving testability
本Skill专注于通过系统化的重构技术提升代码质量。它能识别代码异味,并应用经过验证的重构模式,在保留功能的同时增强代码的可维护性。
当用户提出以下需求时,可使用本Skill:
- 代码重构或清理
- 减少技术债务
- 优化代码结构
- 应用设计模式
- 拆分大型文件或函数
- 消除重复代码
- 现代化遗留代码
- 提升可测试性
Scope Selection
范围选择
When to use this skill:
- Local refactoring (single module/file)
- Pattern application (extract method, introduce interface)
- Test refactoring and test suite improvements
- Data pipeline restructuring
- Safe refactoring with test coverage
When to escalate to senior-software-engineer:
- Architectural changes affecting multiple modules
- API redesign requiring migration paths
- Cross-cutting refactoring with unclear scope
- Performance optimization requiring profiling
- Infrastructure refactoring (use infrastructure-related skills like /terraform, /kubernetes)
- Security-sensitive refactoring (use /security-audit and /threat-model skills)
何时使用本Skill:
- 局部重构(单个模块/文件)
- 模式应用(提取方法、引入接口)
- 测试重构与测试套件优化
- 数据流水线重构
- 基于测试覆盖率的安全重构
何时升级至senior-software-engineer:
- 影响多个模块的架构变更
- 需要迁移路径的API重新设计
- 范围不明确的跨领域重构
- 需要性能分析的性能优化
- 基础设施重构(请使用与基础设施相关的Skill,如/terraform、/kubernetes)
- 涉及安全的敏感重构(请使用/security-audit和/threat-model Skill)
Instructions
操作指南
1. Identify Refactoring Opportunities
1. 识别重构机会
Code Smells to Search For:
- Long methods (>50 lines) or large classes (>300 lines)
- Duplicated code blocks
- High cyclomatic complexity
- Magic numbers and string literals
- Deep nesting (>3 levels)
- Feature envy (method using data from another class)
- Shotgun surgery (one change requires many edits)
- Data clumps (same group of parameters)
- Primitive obsession (using primitives instead of objects)
Use Grep/Glob to find patterns:
bash
undefined需要排查的代码异味:
- 过长方法(超过50行)或过大类(超过300行)
- 重复代码块
- 高圈复杂度
- 魔法数字与字符串字面量
- 深层嵌套(超过3层)
- 特性依恋(方法依赖其他类的数据)
- 霰弹式修改(一处变更需要多处编辑)
- 数据泥团(重复出现的参数组)
- 基本类型偏执(使用基本类型而非对象)
使用Grep/Glob查找模式:
bash
undefinedFind long functions (rough heuristic)
查找长函数(粗略 heuristic)
rg "^(\s*)(def|function|fn|func)\s+\w+" --after-context=60
rg "^(\s*)(def|function|fn|func)\s+\w+" --after-context=60
Find duplicated code
查找重复代码
rg --multiline "pattern.*\n.*pattern"
rg --multiline "pattern.*\n.*pattern"
Find magic numbers
查找魔法数字
rg "\b\d{2,}\b" --type=py --type=js --type=rs
undefinedrg "\b\d{2,}\b" --type=py --type=js --type=rs
undefined2. Plan the Refactoring
2. 规划重构方案
Before starting:
- Verify test coverage - Run tests to establish baseline
- List all changes - Document sequence of refactorings
- Identify dependencies - What code depends on what you're changing?
- Plan rollback points - Where can you safely commit?
- Check for impact - Grep for references to functions/classes being changed
Red flags that require escalation:
- No test coverage exists
- Changes affect public APIs with external consumers
- Unclear ownership or multiple teams involved
- Performance-critical hot paths
开始前的准备:
- 验证测试覆盖率 - 运行测试建立基准
- 列出所有变更 - 记录重构步骤顺序
- 识别依赖关系 - 哪些代码依赖你要修改的内容?
- 规划回滚点 - 确定可以安全提交的节点
- 检查影响范围 - 搜索被修改函数/类的引用
需要升级处理的危险信号:
- 不存在测试覆盖率
- 变更影响有外部消费者的公共API
- 所有权不明确或涉及多个团队
- 性能关键的热点路径
3. Apply Refactoring Patterns
3. 应用重构模式
Code Organization Patterns
代码组织模式
Extract Method/Function:
- Break down long functions into smaller, focused ones
- Each function should do one thing
- Improves readability and testability
Extract Class:
- Split large classes with multiple responsibilities
- Follow Single Responsibility Principle
- Improves cohesion and reduces coupling
Move Method/Field:
- Relocate methods to classes that use their data
- Reduces feature envy
- Improves encapsulation
Inline Method/Variable:
- Remove unnecessary indirection
- Simplify overly abstracted code
- Use when abstraction doesn't add value
Rename:
- Improve naming clarity
- Use domain language
- Make intent explicit
提取方法/函数:
- 将长函数拆分为更小、职责单一的函数
- 每个函数只做一件事
- 提升可读性与可测试性
提取类:
- 拆分具有多个职责的大类
- 遵循单一职责原则
- 提升内聚性并降低耦合度
移动方法/字段:
- 将方法迁移至使用其数据的类中
- 减少特性依恋
- 提升封装性
内联方法/变量:
- 移除不必要的间接层
- 简化过度抽象的代码
- 当抽象无法带来价值时使用
重命名:
- 提升命名清晰度
- 使用领域语言
- 明确表达意图
Structural Patterns
结构模式
Replace Conditional with Polymorphism:
- Replace type switches with subclass methods
- Enables Open/Closed Principle
- Improves extensibility
Introduce Parameter Object:
- Group related parameters into objects
- Reduces parameter lists
- Makes data relationships explicit
Replace Magic Numbers with Constants:
- Define named constants for literals
- Improves readability and maintainability
- Centralizes configuration
Decompose Conditional:
- Extract complex conditions into named functions
- Replace nested ifs with guard clauses
- Improves readability
用多态替代条件判断:
- 用子类方法替代类型分支
- 遵循开闭原则
- 提升可扩展性
引入参数对象:
- 将相关参数分组为对象
- 缩短参数列表
- 明确数据关系
用常量替代魔法数字:
- 为字面量定义命名常量
- 提升可读性与可维护性
- 集中管理配置
分解条件判断:
- 将复杂条件提取为命名函数
- 用卫语句替代嵌套if
- 提升可读性
Test Refactoring Patterns
测试重构模式
Extract Test Fixture:
- Move common setup into fixture/factory
- Reduces duplication in test files
- Improves test maintainability
Introduce Test Data Builder:
- Replace complex object construction with builders
- Makes test intent clearer
- Simplifies test setup
Replace Assertion Roulette:
- Use descriptive assertion messages
- One logical assertion per test
- Clear failure messages
Extract Test Helper:
- Move repeated test logic into helpers
- Keep tests focused on behavior
- Improves test readability
提取测试夹具:
- 将通用设置移至夹具/工厂
- 减少测试文件中的重复代码
- 提升测试可维护性
引入测试数据构建器:
- 用构建器替代复杂对象构造
- 使测试意图更清晰
- 简化测试设置
替换断言轮盘:
- 使用描述性的断言消息
- 每个测试对应一个逻辑断言
- 明确的失败提示
提取测试助手:
- 将重复的测试逻辑移至助手
- 让测试聚焦于行为
- 提升测试可读性
Data Pipeline Patterns
数据流水线模式
Extract Transformation:
- Isolate data transformation logic
- Make transformations composable
- Improves testability
Introduce Pipeline Interface:
- Define standard input/output contracts
- Enable stage composition
- Simplifies testing and debugging
Replace Inline Processing with Stages:
- Break monolithic processing into stages
- Each stage has single responsibility
- Enables parallelization and monitoring
提取转换逻辑:
- 隔离数据转换逻辑
- 使转换逻辑可组合
- 提升可测试性
引入流水线接口:
- 定义标准的输入/输出契约
- 支持阶段组合
- 简化测试与调试
用阶段替换内联处理:
- 将单体式处理拆分为多个阶段
- 每个阶段职责单一
- 支持并行化与监控
4. Safe Refactoring Workflow
4. 安全重构工作流
For each refactoring step:
- Make the change - One refactoring at a time
- Run tests - Verify behavior preserved
- Commit - Create checkpoint with clear message
- Repeat - Move to next refactoring
If tests fail:
- Revert immediately (git checkout)
- Analyze failure - is it a test issue or behavior change?
- Fix or adjust approach
Commit message format:
text
refactor: extract calculate_discount from process_order
Improves testability by isolating discount logic.
No behavior change.每个重构步骤需执行:
- 执行变更 - 每次只进行一项重构
- 运行测试 - 验证行为未改变
- 提交代码 - 创建带有清晰信息的检查点
- 重复操作 - 进行下一项重构
如果测试失败:
- 立即回滚(git checkout)
- 分析失败原因 - 是测试问题还是行为变更?
- 修复或调整方案
提交信息格式:
text
refactor: extract calculate_discount from process_order
Improves testability by isolating discount logic.
No behavior change.5. Verify Changes
5. 验证变更
Verification checklist:
- All tests pass (existing + any new tests)
- No regressions in functionality
- Performance hasn't degraded (for hot paths)
- Code coverage maintained or improved
- Linting passes
- Build succeeds
For large refactorings:
- Run additional smoke tests
- Check memory usage (if applicable)
- Review error handling preservation
验证清单:
- 所有测试通过(现有测试 + 新增测试)
- 功能无回归
- 性能未退化(针对热点路径)
- 代码覆盖率保持或提升
- 代码检查通过
- 构建成功
针对大型重构:
- 运行额外的冒烟测试
- 检查内存使用情况(如适用)
- 确认错误处理逻辑未被破坏
Best Practices
最佳实践
- Small Steps: Make incremental changes, not big bang rewrites
- Test First: Ensure tests exist before refactoring - write them if missing
- One Thing at a Time: Focus on single refactoring per commit
- Preserve Behavior: External behavior must remain unchanged
- Keep It Working: Code should pass tests after each step
- Document Intent: Explain why refactoring was needed in commits
- Refactor Tests Too: Keep tests clean and maintainable
- Use Type Safety: Leverage type systems to catch errors early
- Measure Don't Guess: Profile before optimizing performance
- Know When to Stop: Don't over-engineer or add unnecessary abstraction
- 小步迭代:进行增量变更,而非大规模重写
- 先写测试:重构前确保存在测试 - 若缺失则先编写
- 一次一事:每次提交只聚焦于一项重构
- 保留行为:外部行为必须保持不变
- 保持可用:每一步后代码都应通过测试
- 记录意图:在提交信息中说明重构原因
- 重构测试:保持测试代码简洁可维护
- 利用类型安全:借助类型系统尽早发现错误
- 基于数据决策:优化性能前先进行性能分析
- 适可而止:不要过度设计或添加不必要的抽象
Common Patterns with Examples
常见模式及示例
Pattern 1: Extract Method
模式1:提取方法
python
undefinedpython
undefinedBefore: Long method with multiple responsibilities
Before: Long method with multiple responsibilities
def process_order(order):
# Validate order
if not order.items:
raise ValueError("Empty order")
if order.total < 0:
raise ValueError("Invalid total")
# Calculate discount
discount = 0
if order.customer.is_premium:
discount = order.total * 0.1
if order.total > 1000:
discount += order.total * 0.05
# Apply discount and save
order.final_total = order.total - discount
order.save()def process_order(order):
# Validate order
if not order.items:
raise ValueError("Empty order")
if order.total < 0:
raise ValueError("Invalid total")
# Calculate discount
discount = 0
if order.customer.is_premium:
discount = order.total * 0.1
if order.total > 1000:
discount += order.total * 0.05
# Apply discount and save
order.final_total = order.total - discount
order.save()After: Extracted methods with single responsibility
After: Extracted methods with single responsibility
def process_order(order):
validate_order(order)
discount = calculate_discount(order)
finalize_order(order, discount)
def validate_order(order):
if not order.items:
raise ValueError("Empty order")
if order.total < 0:
raise ValueError("Invalid total")
def calculate_discount(order) -> float:
discount = 0
if order.customer.is_premium:
discount = order.total * 0.1
if order.total > 1000:
discount += order.total * 0.05
return discount
def finalize_order(order, discount: float):
order.final_total = order.total - discount
order.save()
undefineddef process_order(order):
validate_order(order)
discount = calculate_discount(order)
finalize_order(order, discount)
def validate_order(order):
if not order.items:
raise ValueError("Empty order")
if order.total < 0:
raise ValueError("Invalid total")
def calculate_discount(order) -> float:
discount = 0
if order.customer.is_premium:
discount = order.total * 0.1
if order.total > 1000:
discount += order.total * 0.05
return discount
def finalize_order(order, discount: float):
order.final_total = order.total - discount
order.save()
undefinedPattern 2: Replace Magic Numbers with Constants
模式2:用常量替代魔法数字
javascript
// Before
if (response.status === 200) {
setTimeout(retry, 3000);
if (attempts > 5) {
throw new Error("Max retries exceeded");
}
}
// After
const HTTP_OK = 200;
const RETRY_DELAY_MS = 3000;
const MAX_RETRY_ATTEMPTS = 5;
if (response.status === HTTP_OK) {
setTimeout(retry, RETRY_DELAY_MS);
if (attempts > MAX_RETRY_ATTEMPTS) {
throw new Error("Max retries exceeded");
}
}javascript
// Before
if (response.status === 200) {
setTimeout(retry, 3000);
if (attempts > 5) {
throw new Error("Max retries exceeded");
}
}
// After
const HTTP_OK = 200;
const RETRY_DELAY_MS = 3000;
const MAX_RETRY_ATTEMPTS = 5;
if (response.status === HTTP_OK) {
setTimeout(retry, RETRY_DELAY_MS);
if (attempts > MAX_RETRY_ATTEMPTS) {
throw new Error("Max retries exceeded");
}
}Pattern 3: Replace Nested Conditionals with Guard Clauses
模式3:用卫语句替代嵌套条件
python
undefinedpython
undefinedBefore
Before
def get_payment_amount(employee):
if employee.is_active:
if employee.is_full_time:
if employee.tenure > 5:
return employee.salary * 1.1
else:
return employee.salary
else:
return employee.hourly_rate * employee.hours
else:
return 0
def get_payment_amount(employee):
if employee.is_active:
if employee.is_full_time:
if employee.tenure > 5:
return employee.salary * 1.1
else:
return employee.salary
else:
return employee.hourly_rate * employee.hours
else:
return 0
After
After
def get_payment_amount(employee):
if not employee.is_active:
return 0
if not employee.is_full_time:
return employee.hourly_rate * employee.hours
if employee.tenure > 5:
return employee.salary * 1.1
return employee.salaryundefineddef get_payment_amount(employee):
if not employee.is_active:
return 0
if not employee.is_full_time:
return employee.hourly_rate * employee.hours
if employee.tenure > 5:
return employee.salary * 1.1
return employee.salaryundefinedPattern 4: Introduce Parameter Object
模式4:引入参数对象
typescript
// Before
function createUser(
firstName: string,
lastName: string,
email: string,
phone: string,
street: string,
city: string,
state: string,
zip: string,
) {
// ...
}
// After
interface UserDetails {
name: PersonName;
contact: ContactInfo;
address: Address;
}
interface PersonName {
first: string;
last: string;
}
interface ContactInfo {
email: string;
phone: string;
}
interface Address {
street: string;
city: string;
state: string;
zip: string;
}
function createUser(details: UserDetails) {
// ...
}typescript
// Before
function createUser(
firstName: string,
lastName: string,
email: string,
phone: string,
street: string,
city: string,
state: string,
zip: string,
) {
// ...
}
// After
interface UserDetails {
name: PersonName;
contact: ContactInfo;
address: Address;
}
interface PersonName {
first: string;
last: string;
}
interface ContactInfo {
email: string;
phone: string;
}
interface Address {
street: string;
city: string;
state: string;
zip: string;
}
function createUser(details: UserDetails) {
// ...
}Pattern 5: Replace Type Code with Polymorphism
模式5:用多态替代类型码
rust
// Before
enum ShapeType { Circle, Rectangle, Triangle }
struct Shape {
shape_type: ShapeType,
radius: f64,
width: f64,
height: f64,
base: f64,
}
impl Shape {
fn area(&self) -> f64 {
match self.shape_type {
ShapeType::Circle => 3.14159 * self.radius * self.radius,
ShapeType::Rectangle => self.width * self.height,
ShapeType::Triangle => 0.5 * self.base * self.height,
}
}
}
// After
trait Shape {
fn area(&self) -> f64;
}
struct Circle { radius: f64 }
struct Rectangle { width: f64, height: f64 }
struct Triangle { base: f64, height: f64 }
impl Shape for Circle {
fn area(&self) -> f64 {
3.14159 * self.radius * self.radius
}
}
impl Shape for Rectangle {
fn area(&self) -> f64 {
self.width * self.height
}
}
impl Shape for Triangle {
fn area(&self) -> f64 {
0.5 * self.base * self.height
}
}rust
// Before
enum ShapeType { Circle, Rectangle, Triangle }
struct Shape {
shape_type: ShapeType,
radius: f64,
width: f64,
height: f64,
base: f64,
}
impl Shape {
fn area(&self) -> f64 {
match self.shape_type {
ShapeType::Circle => 3.14159 * self.radius * self.radius,
ShapeType::Rectangle => self.width * self.height,
ShapeType::Triangle => 0.5 * self.base * self.height,
}
}
}
// After
trait Shape {
fn area(&self) -> f64;
}
struct Circle { radius: f64 }
struct Rectangle { width: f64, height: f64 }
struct Triangle { base: f64, height: f64 }
impl Shape for Circle {
fn area(&self) -> f64 {
3.14159 * self.radius * self.radius
}
}
impl Shape for Rectangle {
fn area(&self) -> f64 {
self.width * self.height
}
}
impl Shape for Triangle {
fn area(&self) -> f64 {
0.5 * self.base * self.height
}
}Pattern 6: Extract Data Pipeline Stage
模式6:提取数据流水线阶段
python
undefinedpython
undefinedBefore: Monolithic processing
Before: Monolithic processing
def process_data(raw_data):
# Validate
if not raw_data:
raise ValueError("Empty data")
# Clean
cleaned = []
for item in raw_data:
if item.get('status') == 'valid':
cleaned.append(item)
# Transform
transformed = []
for item in cleaned:
transformed.append({
'id': item['id'],
'value': item['raw_value'] * 100,
'timestamp': item['ts']
})
# Aggregate
total = sum(item['value'] for item in transformed)
return {'items': transformed, 'total': total}def process_data(raw_data):
# Validate
if not raw_data:
raise ValueError("Empty data")
# Clean
cleaned = []
for item in raw_data:
if item.get('status') == 'valid':
cleaned.append(item)
# Transform
transformed = []
for item in cleaned:
transformed.append({
'id': item['id'],
'value': item['raw_value'] * 100,
'timestamp': item['ts']
})
# Aggregate
total = sum(item['value'] for item in transformed)
return {'items': transformed, 'total': total}After: Pipeline with composable stages
After: Pipeline with composable stages
def validate_input(raw_data):
if not raw_data:
raise ValueError("Empty data")
return raw_data
def filter_valid(data):
return [item for item in data if item.get('status') == 'valid']
def transform_items(data):
return [
{
'id': item['id'],
'value': item['raw_value'] * 100,
'timestamp': item['ts']
}
for item in data
]
def aggregate_results(transformed):
total = sum(item['value'] for item in transformed)
return {'items': transformed, 'total': total}
def process_data(raw_data):
return (raw_data
|> validate_input
|> filter_valid
|> transform_items
|> aggregate_results)
undefineddef validate_input(raw_data):
if not raw_data:
raise ValueError("Empty data")
return raw_data
def filter_valid(data):
return [item for item in data if item.get('status') == 'valid']
def transform_items(data):
return [
{
'id': item['id'],
'value': item['raw_value'] * 100,
'timestamp': item['ts']
}
for item in data
]
def aggregate_results(transformed):
total = sum(item['value'] for item in transformed)
return {'items': transformed, 'total': total}
def process_data(raw_data):
return (raw_data
|> validate_input
|> filter_valid
|> transform_items
|> aggregate_results)
undefinedPattern 7: Simplify Test with Builder
模式7:用构建器简化测试
go
// Before
func TestUserRegistration(t *testing.T) {
user := &User{
FirstName: "John",
LastName: "Doe",
Email: "john@example.com",
Phone: "555-0100",
Address: Address{
Street: "123 Main St",
City: "Springfield",
State: "IL",
Zip: "62701",
},
Preferences: Preferences{
NewsletterEnabled: true,
Theme: "dark",
},
CreatedAt: time.Now(),
}
err := RegisterUser(user)
assert.NoError(t, err)
}
// After
func TestUserRegistration(t *testing.T) {
user := NewUserBuilder().
WithName("John", "Doe").
WithEmail("john@example.com").
Build()
err := RegisterUser(user)
assert.NoError(t, err)
}
// Test builder focuses on what matters for each test
func TestUserWithNewsletter(t *testing.T) {
user := NewUserBuilder().WithNewsletter(true).Build()
// ...
}go
// Before
func TestUserRegistration(t *testing.T) {
user := &User{
FirstName: "John",
LastName: "Doe",
Email: "john@example.com",
Phone: "555-0100",
Address: Address{
Street: "123 Main St",
City: "Springfield",
State: "IL",
Zip: "62701",
},
Preferences: Preferences{
NewsletterEnabled: true,
Theme: "dark",
},
CreatedAt: time.Now(),
}
err := RegisterUser(user)
assert.NoError(t, err)
}
// After
func TestUserRegistration(t *testing.T) {
user := NewUserBuilder().
WithName("John", "Doe").
WithEmail("john@example.com").
Build()
err := RegisterUser(user)
assert.NoError(t, err)
}
// Test builder focuses on what matters for each test
func TestUserWithNewsletter(t *testing.T) {
user := NewUserBuilder().WithNewsletter(true).Build()
// ...
}When to Stop Refactoring
何时停止重构
Stop if:
- Tests start failing unexpectedly
- Scope is expanding beyond initial plan
- Unsure about architectural implications
- Performance concerns arise
- Security implications unclear
In these cases:
- Commit current progress
- Document remaining work
- Escalate to senior-software-engineer or relevant specialist
出现以下情况时停止:
- 测试意外失败
- 范围超出初始计划
- 对架构影响不确定
- 出现性能问题
- 安全影响不明确
在这些情况下:
- 提交当前进度
- 记录剩余工作
- 升级至senior-software-engineer或相关专家