java-best-practices-refactor-legacy

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Java Legacy Code Refactoring

Java遗留代码重构

Quick Start

快速开始

Point to any legacy Java file and receive a refactored version:
bash
undefined
指定任意遗留Java文件,即可获得重构后的版本:
bash
undefined

Refactor 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/
undefined
Modernize all Java files in src/main/java/com/example/legacy/
undefined

When 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):
  1. Extract constants for magic numbers/strings
  2. Rename poorly named variables/methods
  3. Convert to try-with-resources
  4. Replace StringBuffer with StringBuilder
Medium Priority (High Impact, Medium Risk):
  1. Convert loops to Stream API
  2. Replace null returns with Optional
  3. Extract methods from long methods
  4. Apply design patterns
Low Priority (Medium Impact, High Risk):
  1. Extract classes from god classes
  2. Restructure architecture
  3. Change public APIs
根据影响和风险优先级排序重构任务:
高优先级(高影响、低风险):
  1. 为魔法值(数字/字符串)提取常量
  2. 重命名命名不规范的变量/方法
  3. 转换为try-with-resources
  4. 用StringBuilder替代StringBuffer
中优先级(高影响、中风险):
  1. 将循环转换为Stream API
  2. 用Optional替代空返回值
  3. 从超长方法中提取方法
  4. 应用设计模式
低优先级(中影响、高风险):
  1. 从上帝类中拆分出独立类
  2. 重构架构
  3. 修改公共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:
  1. Analysis of legacy code issues
  2. Refactoring plan with prioritized changes
  3. Refactored code with detailed explanations
  4. Before/After comparison highlighting improvements
  5. Testing recommendations for validation
重构时需提供:
  1. 遗留代码问题的分析报告
  2. 包含优先级排序的重构计划
  3. 带详细说明的重构后代码
  4. 突出改进点的前后对比
  5. 用于验证的测试建议

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
  • 一次专注于一种重构模式
  • 优先保证安全而非技巧性
  • 尽可能保持向后兼容性
  • 清晰记录破坏性变更
  • 每次重构步骤后运行完整测试套件