Java遗留代码重构:从A到Z的逐步指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

重构遗留Java代码:从A到Z



处理遗留Java代码是每位开发者都会面临的挑战。旧代码往往缺乏测试、包含过时的模式且难以修改。然而,完全重写项目并不总是最佳解决方案。在本文中,我们将解析一种经过验证的遗留代码重构方法:从分析到实施变更,并附带Java具体示例。



1. 诊断与准备:在接触代码之前



第一步也是最重要的一步是了解你正在处理的内容。不要通过杂乱无章地编辑代码行来开始重构。而是:



  • 依赖关系图:可视化哪些类依赖于哪些类。使用IntelliJ IDEA依赖查看器或JDepend等工具。
  • 特征测试:编写能够捕获代码当前行为的测试。这是你的安全网。
  • 识别入口点:确定哪些方法被最频繁调用,以及主要变更发生在何处。


针对需要重构的方法的一个简单特征测试示例:



import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.assertEquals;

public class LegacyCalculatorTest {

@Test public void testLegacyCalculate() { LegacyCalculator calc = new LegacyCalculator(); // Capture current behavior int result = calc.calculate(10, 5, "add"); assertEquals(15, result, "Current behavior: addition"); result = calc.calculate(10, 5, "sub"); assertEquals(5, result, "Current behavior: subtraction"); }}


这样的测试并不从绝对意义上验证逻辑的正确性——它只是记录代码当前的功能。重构后,测试必须通过,否则你就改变了行为。



2. "外科手术式"重构策略:逐个方法进行



试图一次性重构整个类,是引入缺陷的必然途径。采用"战斗考古学"方法:



  • 选择一个方法或一组相关的小方法。
  • 为它们编写特征测试(如果尚不存在)。
  • 应用一种重构技术(例如提取方法或重命名变量)。
  • 运行测试。它们应该通过。
  • 使用清晰的描述提交变更。


示例:重构一个包含"魔法数字"和长参数列表的方法。



原始代码(不良):



public class OrderProcessor {    public double process(double amount, int type, double discount) {        double result;        if (type == 1) {            result = amount * 1.2; // 20% markup            if (discount > 0.1) {                result = result - result * 0.05; // 5% discount            }        } else if (type == 2) {            result = amount * 1.5; // 50% markup        } else {            result = amount;        }        return result;    }}


重构后(改进版):



public class OrderProcessor {    private static final double PREMIUM_MARKUP = 1.2;    private static final double STANDARD_MARKUP = 1.5;    private static final double LOYALTY_DISCOUNT = 0.05;    private static final double DISCOUNT_THRESHOLD = 0.1;

public double process(OrderType type, double amount, double discount) { double basePrice = applyMarkup(amount, type); return applyLoyaltyDiscount(basePrice, discount); }

private double applyMarkup(double amount, OrderType type) { return switch (type) { case PREMIUM -> amount * PREMIUM_MARKUP; case STANDARD -> amount * STANDARD_MARKUP; case BASIC

博客

书籍推荐