关于 code-refactor-master
面向希望改善代码结构且保持行为不变的开发者的重构 Skill,涵盖代码异味、常见重构、Java 与 Python 实践及渐进式测试流程。
主要功能
- 01识别常见代码异味
- 02应用方法与类级重构
- 03采用 Java 专属重构方式
- 04采用 Python 专属重构方式
- 05结合测试逐步重构
- 06在不改变行为时提升性能
适用场景
- 01减少重复代码与复杂度
- 02提升旧代码可维护性
- 03重构 Java 或 Python 解法
- 04优化算法实现
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ yennanliu/ cs_basics --skill code-refactor-master安装后在 Claude Code 中输入/code-refactor-master确认已加载。
详细介绍
代码重构大师
何时使用此技能
在以下情况下使用此技能:
- 重构现有代码,提升质量
- 消除代码异味
- 提高代码的可读性和可维护性
- 在不改变行为的前提下优化性能
- 应用设计模式
- 降低复杂度
- 清理技术债务
重构原则
1. 核心规则
黄金法则:改进代码的内部结构,但不改变外部行为
核心原则:
- 一次只进行一项重构
- 每次重构后运行测试
- 频繁提交,并使用清晰的提交信息
- 将重构与功能开发分开
- 除非明确要更改 API,否则保持向后兼容
需要重构的警示信号:
- 代码重复(DRY 原则)
- 方法过长(>20-30 行)
- 类过大(>300-500 行)
- 参数列表过长(>3-4 个参数)
- 条件语句嵌套过深(>3 层)
- 注释在解释代码的作用(代码应能自我解释)
2. 常见代码异味
膨胀症:
- 过长方法
- 过大类
- 基本类型偏执
- 参数列表过长
- 数据团块
面向对象滥用:
- Switch 语句(考虑使用多态)
- 临时字段
- 拒绝继承
- 接口不同的替代类
变更阻碍因素:
- 发散式变化(一个类因多种原因而变更)
- 散弹式修改(一次变更需要进行许多小改动)
- 并行继承体系
可有可无的内容:
- 注释(代码本应能自我解释的情况)
- 重复代码
- 懒惰类
- 死代码
- 推测性通用性
耦合症:
- 特性嫉妒
- 不恰当的亲密关系
- 消息链
- 中间人
3. 重构目录
方法级重构:
提取方法
// Before
void printOwing() {
printBanner();
// print details
System.out.println("name: " + name);
System.out.println("amount: " + getOutstanding());
}
// After
void printOwing() {
printBanner();
printDetails(getOutstanding());
}
void printDetails(double outstanding) {
System.out.println("name: " + name);
System.out.println("amount: " + outstanding);
}
内联方法
// Before - method too simple
int getRating() {
return moreThanFiveLateDeliveries() ? 2 : 1;
}
boolean moreThanFiveLateDeliveries() {
return numberOfLateDeliveries > 5;
}
// After
int getRating() {
return numberOfLateDeliveries > 5 ? 2 : 1;
}
用查询替换临时变量
// Before
double calculateTotal() {
double basePrice = quantity * itemPrice;
if (basePrice > 1000) {
return basePrice * 0.95;
}
return basePrice * 0.98;
}
// After
double calculateTotal() {
if (basePrice() > 1000) {
return basePrice() * 0.95;
}
return basePrice() * 0.98;
}
double basePrice() {
return quantity * itemPrice;
}
变量级重构:
重命名变量
# Before
d = 10 # elapsed time in days
# After
elapsed_time_in_days = 10
拆分临时变量
// Before
double temp = 2 * (height + width);
System.out.println(temp);
temp = height * width;
System.out.println(temp);
// After
double perimeter = 2 * (height + width);
System.out.println(perimeter);
double area = height * width;
System.out.println(area);
类级重构:
提取类
// Before
class Person {
String name;
String officeAreaCode;
String officeNumber;
String getTelephoneNumber() {
return "(" + officeAreaCode + ") " + officeNumber;
}
}
// After
class Person {
String name;
TelephoneNumber officeTelephone = new TelephoneNumber();
String getTelephoneNumber() {
return officeTelephone.getTelephoneNumber();
}
}
class TelephoneNumber {
String areaCode;
String number;
String getTelephoneNumber() {
return "(" + areaCode + ") " + number;
}
}
以多态替换条件语句
# Before
class Bird:
def get_speed(self):
if self.type == "EUROPEAN":
return self.get_base_speed()
elif self.type == "AFRICAN":
return self.get_base_speed() - self.get_load_factor()
elif self.type == "NORWEGIAN_BLUE":
return 0 if self.is_nailed else self.get_base_speed()
# After
class Bird:
def get_speed(self):
pass # Abstract
class European(Bird):
def get_speed(self):
return self.get_base_speed()
class African(Bird):
def get_speed(self):
return self.get_base_speed() - self.get_load_factor()
class NorwegianBlue(Bird):
def get_speed(self):
return 0 if self.is_nailed else self.get_base_speed()
4. Java 专属重构
使用现代 Java 特性:
用 Lambda 替换匿名类
// Before
list.sort(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
// After
list.sort((a, b) -> a.compareTo(b));
// Or even better
list.sort(String::compareTo);
使用 Streams API
// Before
List<String> result = new ArrayList<>();
for (String s : list) {
if (s.length() > 3) {
result.add(s.toUpperCase());
}
}
// After
List<String> result = list.stream()
.filter(s -> s.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
替换字符串拼接
// Before - inefficient in loops
String result = "";
for (String s : list) {
result += s + ", ";
}
// After
StringBuilder result = new StringBuilder();
for (String s : list) {
result.append(s).append(", ");
}
// Or better
String result = String.join(", ", list);
使用 Optional
// Before
public User findUser(int id) {
User user = database.getUser(id);
return user != null ? user : new User();
}
// After
public Optional<User> findUser(int id) {
return Optional.ofNullable(database.getUser(id));
}
用 Enum 替换类型码
// Before
public static final int TYPE_A = 1;
public static final int TYPE_B = 2;
// After
public enum Type {
A, B
}
5. Python 专属重构
使用列表推导式
# Before
result = []
for item in items:
if item > 0:
result.append(item * 2)
# After
result = [item * 2 for item in items if item > 0]
使用 Collections 模块
# Before
counts = {}
for item in items:
if item in counts:
counts[item] += 1
else:
counts[item] = 1
# After
from collections import Counter
counts = Counter(items)
使用上下文管理器
# Before
file = open('file.txt')
data = file.read()
file.close()
# After
with open('file.txt') as file:
data = file.read()
使用 f-string
# Before
message = "Hello, %s! You are %d years old." % (name, age)
# After
message = f"Hello, {name}! You are {age} years old."
使用类型提示
# Before
def process(data):
return [x * 2 for x in data]
# After
def process(data: list[int]) -> list[int]:
return [x * 2 for x in data]
使用 Dataclasses
# Before
class Point:
def __init__(self, x, y):
self.x = x
self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
# After
from dataclasses import dataclass
@dataclass
class Point:
x: int
y: int
6. 整洁代码原则
命名:
// Bad
int d; // elapsed time in days
// Good
int elapsedTimeInDays;
// Bad
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<>();
for (int[] x : theList) {
if (x[0] == 4) {
list1.add(x);
}
}
return list1;
}
// Good
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<>();
for (Cell cell : gameBoard) {
if (cell.isFlagged()) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
函数:
- 短小(最多 20-30 行)
- 只做一件事
- 只处于一个抽象层级
- 使用描述性名称
- 参数尽量少(理想情况下为 0-3 个)
注释:
// Bad - comment explains what code does
// Check to see if employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
// Good - code is self-explanatory
if (employee.isEligibleForFullBenefits())
7. 性能重构
算法优化:
# Before - O(n²)
def has_duplicates(arr):
for i in range(len(arr)):
for j in range(i + 1, len(arr)):
if arr[i] == arr[j]:
return True
return False
# After - O(n)
def has_duplicates(arr):
return len(arr) != len(set(arr))
惰性求值:
// Before - computes all values
List<Integer> results = list.stream()
.map(this::expensiveOperation)
.collect(Collectors.toList());
return results.get(0);
// After - computes only what's needed
return list.stream()
.map(this::expensiveOperation)
.findFirst()
.orElse(null);
记忆化:
# Before
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
# After
from functools import lru_cache
@lru_cache(maxsize=None)
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
8. 重构工作流
逐步流程:
- 识别:找到代码异味或改进机会
- 规划:决定要应用哪种重构
- 测试:确保测试已编写且通过
- 重构:进行一项小改动
- 测试:再次运行测试
- 提交:保存可正常工作的状态
- 重复:继续进行下一项重构
工作流示例:
# 1. Create feature branch
git checkout -b refactor/improve-user-service
# 2. Identify issue (e.g., long method)
# Read code, find UserService.processUser() is 150 lines
# 3. Run existing tests
mvn test # or pytest
# 4. Extract method
# Break processUser into smaller methods
# 5. Run tests
mvn test # Ensure still passing
# 6. Commit
git commit -m "refactor: extract validateUser method"
# 7. Continue
# Extract next method, repeat
9. 重构检查清单
重构前:
- 测试已编写且通过
- 理解代码行为
- 有明确的目标
- 知道要应用哪种重构
重构过程中:
- 进行小幅、渐进式改动
- 每次改动后运行测试
- 始终确保代码可正常工作
- 频繁提交
重构后:
- 所有测试均通过
- 代码更易读
- 复杂度降低
- 行为未发生变化
- 如有需要,更新文档
10. LeetCode 专属重构
优化暴力解法:
// Before - Brute force O(n²)
public int[] twoSum(int[] nums, int target) {
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[i] + nums[j] == target) {
return new int[]{i, j};
}
}
}
return new int[]{};
}
// After - Hash map O(n)
public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), i};
}
map.put(nums[i], i);
}
return new int[]{};
}
提取辅助方法:
# Before - monolithic
def solve(self, grid):
# 50 lines of code mixing concerns
# After - modular
def solve(self, grid):
if not self.is_valid(grid):
return []
processed = self.preprocess(grid)
result = self.compute(processed)
return self.format_output(result)
def is_valid(self, grid):
# validation logic
def preprocess(self, grid):
# preprocessing logic
def compute(self, data):
# core algorithm
def format_output(self, result):
# formatting logic
重构反模式
不要:
- 在没有测试的情况下重构
- 在重构期间改变行为
- 一次进行多项更改
- 同时重构和添加功能
- 对简单代码过度设计
- 过早优化
项目背景
对于 CS_basics 仓库:
- 重构
leetcode_java/和leetcode_python/中的解法 - 保持不同语言实现之间的一致性
- 更新算法说明
- 遵循项目规范
- 使用示例输入测试重构后的代码
- 记录复杂度改进
工具和资源
IDE 重构工具:
- IntelliJ IDEA:重构菜单(Ctrl+Alt+Shift+T)
- VS Code:Python 重构扩展
- PyCharm:重构操作
在可用时使用自动重构:
- 重命名:安全地在整个项目中重命名
- 提取方法/变量:自动提取
- 内联:预览后安全地内联
- 移动:重组包/模块
评论
支持 Markdown