java-best-practices-refactor-legacy
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseJava Legacy Code Refactoring
Java遗留代码重构
Quick Start
快速开始
Point to any legacy Java file and receive a refactored version:
bash
undefined指定任意遗留Java文件,即可获得重构后的版本:
bash
undefinedRefactor a single legacy class
Refactor a single legacy class
Refactor LegacyUserService.java to modern Java
Refactor LegacyUserService.java to modern Java
Refactor entire legacy package
Refactor entire legacy package
Modernize all Java files in src/main/java/com/example/legacy/
undefinedModernize all Java files in src/main/java/com/example/legacy/
undefinedWhen to Use
适用场景
Use this skill when you need to:
- Modernize pre-Java 8 code to use streams, lambdas, and Optional
- Refactor legacy applications to modern Java patterns
- Convert anonymous inner classes to lambda expressions
- Replace imperative loops with Stream API
- Apply SOLID principles to existing code
- Extract methods from long methods (>50 lines)
- Break up god classes into focused components
- Replace null returns with Optional
- Convert to try-with-resources for resource management
- Apply design patterns (Strategy, Builder, etc.)
- Migrate from old frameworks to modern alternatives
- Improve error handling with custom exceptions
在以下场景中使用本技能:
- 将Java 8之前的代码现代化,使用流、Lambda表达式和Optional
- 将遗留应用重构为现代Java模式
- 将匿名内部类转换为Lambda表达式
- 用Stream API替代命令式循环
- 对现有代码应用SOLID原则
- 从超长方法(超过50行)中提取方法
- 将“上帝类”拆分为职责单一的组件
- 用Optional替代空返回值
- 使用try-with-resources进行资源管理
- 应用设计模式(策略模式、建造者模式等)
- 从旧框架迁移到现代替代方案
- 通过自定义异常改进错误处理
Instructions
操作步骤
Step 1: Analyze Legacy Code
步骤1:分析遗留代码
Read the target file and identify legacy patterns:
Pre-Java 8 Patterns:
- Anonymous inner classes instead of lambdas
- Manual iteration instead of Stream API
- Null checks instead of Optional
- Manual resource management instead of try-with-resources
- StringBuffer instead of StringBuilder
- Vector/Hashtable instead of modern collections
Code Smells:
- God classes (classes doing too much)
- Long methods (over 50 lines)
- Deep nesting (over 3 levels)
- Code duplication
- Poor naming
- Magic numbers and strings
- Tight coupling
Anti-Patterns:
- Singleton abuse
- Service locator pattern
- God objects
- Anemic domain models
- Transaction script pattern
读取目标文件,识别遗留模式:
Java 8之前的模式:
- 使用匿名内部类而非Lambda表达式
- 手动迭代而非Stream API
- 空值检查而非Optional
- 手动资源管理而非try-with-resources
- StringBuffer而非StringBuilder
- Vector/Hashtable而非现代集合类
代码坏味道:
- 上帝类(承担过多职责的类)
- 超长方法(超过50行)
- 深层嵌套(超过3层)
- 代码重复
- 命名不规范
- 魔法值(数字和字符串)
- 紧耦合
反模式:
- 单例模式滥用
- 服务定位器模式
- 上帝对象
- 贫血领域模型
- 事务脚本模式
Step 2: Plan Refactoring Strategy
步骤2:制定重构策略
Prioritize refactorings by impact and risk:
High Priority (High Impact, Low Risk):
- Extract constants for magic numbers/strings
- Rename poorly named variables/methods
- Convert to try-with-resources
- Replace StringBuffer with StringBuilder
Medium Priority (High Impact, Medium Risk):
- Convert loops to Stream API
- Replace null returns with Optional
- Extract methods from long methods
- Apply design patterns
Low Priority (Medium Impact, High Risk):
- Extract classes from god classes
- Restructure architecture
- Change public APIs
根据影响和风险优先级排序重构任务:
高优先级(高影响、低风险):
- 为魔法值(数字/字符串)提取常量
- 重命名命名不规范的变量/方法
- 转换为try-with-resources
- 用StringBuilder替代StringBuffer
中优先级(高影响、中风险):
- 将循环转换为Stream API
- 用Optional替代空返回值
- 从超长方法中提取方法
- 应用设计模式
低优先级(中影响、高风险):
- 从上帝类中拆分出独立类
- 重构架构
- 修改公共API
Step 3: Apply Modern Java Features
步骤3:应用现代Java特性
Lambda Expressions:
java
// Before: Anonymous inner class
Comparator<User> comparator = new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
return u1.getName().compareTo(u2.getName());
}
};
// After: Lambda and method reference
Comparator<User> comparator = Comparator.comparing(User::getName);Stream API:
java
// Before: Imperative loops
List<String> names = new ArrayList<>();
for (User user : users) {
if (user.isActive()) {
names.add(user.getName().toUpperCase());
}
}
Collections.sort(names);
// After: Functional streams
List<String> names = users.stream()
.filter(User::isActive)
.map(User::getName)
.map(String::toUpperCase)
.sorted()
.toList();Optional:
java
// Before: Null returns
public User findUser(String id) {
User user = repository.findById(id);
return user != null ? user : DEFAULT_USER;
}
// After: Optional
public Optional<User> findUser(String id) {
return repository.findById(id);
}
// Usage
User user = findUser(id).orElse(DEFAULT_USER);Records (Java 14+):
java
// Before: Boilerplate DTO
public class UserDTO {
private final String name;
private final String email;
// constructor, getters, equals, hashCode...
}
// After: Record
public record UserDTO(String name, String email) {}Try-with-resources:
java
// Before: Manual resource management
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("file.txt"));
// use reader
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) {}
}
}
// After: Try-with-resources
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
// use reader
} catch (IOException e) {
log.error("Failed to read file", e);
}Lambda表达式:
java
// Before: Anonymous inner class
Comparator<User> comparator = new Comparator<User>() {
@Override
public int compare(User u1, User u2) {
return u1.getName().compareTo(u2.getName());
}
};
// After: Lambda and method reference
Comparator<User> comparator = Comparator.comparing(User::getName);Stream API:
java
// Before: Imperative loops
List<String> names = new ArrayList<>();
for (User user : users) {
if (user.isActive()) {
names.add(user.getName().toUpperCase());
}
}
Collections.sort(names);
// After: Functional streams
List<String> names = users.stream()
.filter(User::isActive)
.map(User::getName)
.map(String::toUpperCase)
.sorted()
.toList();Optional:
java
// Before: Null returns
public User findUser(String id) {
User user = repository.findById(id);
return user != null ? user : DEFAULT_USER;
}
// After: Optional
public Optional<User> findUser(String id) {
return repository.findById(id);
}
// Usage
User user = findUser(id).orElse(DEFAULT_USER);Records (Java 14+):
java
// Before: Boilerplate DTO
public class UserDTO {
private final String name;
private final String email;
// constructor, getters, equals, hashCode...
}
// After: Record
public record UserDTO(String name, String email) {}Try-with-resources:
java
// Before: Manual resource management
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("file.txt"));
// use reader
} finally {
if (reader != null) {
try { reader.close(); } catch (IOException e) {}
}
}
// After: Try-with-resources
try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) {
// use reader
} catch (IOException e) {
log.error("Failed to read file", e);
}Step 4: Extract Methods and Classes
步骤4:提取方法和类
Extract Method:
java
// Before: Long method
public void processOrder(Order order) {
// Validation (20 lines)
// Calculate total (15 lines)
// Save order (10 lines)
}
// After: Extracted methods
public void processOrder(Order order) {
validateOrder(order);
double total = calculateTotal(order);
saveOrder(order, total);
}Extract Class:
java
// Before: God class
public class OrderProcessor {
public void processOrder(Order order) { /* ... */ }
public void validateOrder(Order order) { /* ... */ }
public double calculateTotal(Order order) { /* ... */ }
public void sendEmail(Order order) { /* ... */ }
public void updateInventory(Order order) { /* ... */ }
}
// After: Separated responsibilities
public class OrderProcessor {
private final OrderValidator validator;
private final OrderCalculator calculator;
private final OrderNotifier notifier;
private final InventoryManager inventory;
public void processOrder(Order order) {
validator.validate(order);
double total = calculator.calculateTotal(order);
order.setTotal(total);
inventory.updateInventory(order);
notifier.sendOrderConfirmation(order);
}
}提取方法:
java
// Before: Long method
public void processOrder(Order order) {
// Validation (20 lines)
// Calculate total (15 lines)
// Save order (10 lines)
}
// After: Extracted methods
public void processOrder(Order order) {
validateOrder(order);
double total = calculateTotal(order);
saveOrder(order, total);
}提取类:
java
// Before: God class
public class OrderProcessor {
public void processOrder(Order order) { /* ... */ }
public void validateOrder(Order order) { /* ... */ }
public double calculateTotal(Order order) { /* ... */ }
public void sendEmail(Order order) { /* ... */ }
public void updateInventory(Order order) { /* ... */ }
}
// After: Separated responsibilities
public class OrderProcessor {
private final OrderValidator validator;
private final OrderCalculator calculator;
private final OrderNotifier notifier;
private final InventoryManager inventory;
public void processOrder(Order order) {
validator.validate(order);
double total = calculator.calculateTotal(order);
order.setTotal(total);
inventory.updateInventory(order);
notifier.sendOrderConfirmation(order);
}
}Step 5: Apply Design Patterns
步骤5:应用设计模式
See references/design-patterns.md for:
- Strategy pattern for conditional logic
- Builder pattern for complex objects
- Factory pattern for object creation
- Repository pattern for data access
参考references/design-patterns.md了解:
- 用于条件逻辑的策略模式
- 用于复杂对象的建造者模式
- 用于对象创建的工厂模式
- 用于数据访问的仓库模式
Step 6: Improve Error Handling
步骤6:改进错误处理
Replace printStackTrace with Logging:
java
// Before
try {
processPayment(order);
} catch (Exception e) {
e.printStackTrace();
}
// After
try {
processPayment(order);
} catch (PaymentException e) {
log.error("Payment processing failed for order {}", order.getId(), e);
throw new OrderProcessingException("Failed to process order payment", e);
}Create Custom Exceptions:
java
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(Long id) {
super("User not found with ID: " + id);
}
}用日志替代printStackTrace:
java
// Before
try {
processPayment(order);
} catch (Exception e) {
e.printStackTrace();
}
// After
try {
processPayment(order);
} catch (PaymentException e) {
log.error("Payment processing failed for order {}", order.getId(), e);
throw new OrderProcessingException("Failed to process order payment", e);
}创建自定义异常:
java
public class UserNotFoundException extends RuntimeException {
public UserNotFoundException(Long id) {
super("User not found with ID: " + id);
}
}Supporting Files
支持文件
- references/refactoring-examples.md - Comprehensive before/after examples
- references/design-patterns.md - Strategy, Builder, Factory patterns
- references/modernization-guide.md - Java 8+ feature migration guide
- references/refactoring-examples.md - 完整的前后对比示例
- references/design-patterns.md - 策略、建造者、工厂模式
- references/modernization-guide.md - Java 8+特性迁移指南
Requirements
要求
Tools Needed
所需工具
- Java 8+ (for lambdas, streams, Optional)
- Java 11+ (for var, improved String methods)
- Java 14+ (for records, switch expressions)
- Java 17+ (for sealed classes, pattern matching)
- Modern IDE with refactoring support
- Java 8+(支持Lambda、流、Optional)
- Java 11+(支持var、改进的String方法)
- Java 14+(支持Records、switch表达式)
- Java 17+(支持密封类、模式匹配)
- 支持重构的现代IDE
Dependencies
依赖项
xml
<!-- Lombok (for reducing boilerplate) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- SLF4J for logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>xml
<!-- Lombok (for reducing boilerplate) -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
<!-- SLF4J for logging -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>2.0.9</version>
</dependency>Refactoring Checklist
重构检查清单
Before refactoring:
- Ensure tests exist (or create them first)
- Understand the current behavior completely
- Create a backup or commit current state
During refactoring:
- Make one change at a time
- Run tests after each change
- Keep commits small and focused
After refactoring:
- Verify all tests pass
- Check for performance regressions
- Review code with team
重构前:
- 确保存在测试(或先创建测试)
- 完全理解当前行为
- 创建备份或提交当前状态
重构中:
- 每次只做一处修改
- 每次修改后运行测试
- 保持提交小而聚焦
重构后:
- 验证所有测试通过
- 检查是否有性能退化
- 与团队一起评审代码
Output Format
输出格式
When refactoring, provide:
- Analysis of legacy code issues
- Refactoring plan with prioritized changes
- Refactored code with detailed explanations
- Before/After comparison highlighting improvements
- Testing recommendations for validation
重构时需提供:
- 遗留代码问题的分析报告
- 包含优先级排序的重构计划
- 带详细说明的重构后代码
- 突出改进点的前后对比
- 用于验证的测试建议
Red Flags to Avoid
需避免的警示
- Never refactor code without understanding its purpose
- Never refactor without tests to validate behavior
- Avoid changing multiple patterns simultaneously
- Don't optimize prematurely
- Don't refactor code you can't test
- Never break public APIs without migration strategy
- 永远不要在不理解代码用途的情况下进行重构
- 永远不要在没有测试验证行为的情况下进行重构
- 避免同时修改多种模式
- 不要过早优化
- 不要重构无法测试的代码
- 永远不要在没有迁移策略的情况下破坏公共API
Notes
注意事项
- Focus on one refactoring pattern at a time
- Prioritize safety over cleverness
- Maintain backward compatibility when possible
- Document breaking changes clearly
- Run full test suite after each refactoring step
- 一次专注于一种重构模式
- 优先保证安全而非技巧性
- 尽可能保持向后兼容性
- 清晰记录破坏性变更
- 每次重构步骤后运行完整测试套件