Java遗留代码重构:分步指南

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

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

开始课程

Java遗留代码重构:逐步指南

处理Java遗留代码是开发人员面临的最常见且复杂的任务之一。这类代码通常缺乏测试,采用单体风格编写,并包含许多反模式。然而,完全重写系统成本高昂且风险巨大。更具效率的方法是进行系统性的重构。在本文中,我们将探讨重构Java遗留代码的实用方法,使代码更清晰、更安全且更易于维护。



1. 准备工作:分析与构建“安全网”

在修改代码之前,必须理解其功能以及如何不破坏现有逻辑。重构遗留代码的主要原则是不改变行为。为此,需要创建一个“安全网”——一套测试用例。

从研究代码开始。找到入口点(从外部调用的方法),并尝试确定预期的结果。即使代码编写得很糟糕,它也能正确完成某些功能。

分析之后,编写特征测试。这些测试用于记录代码的当前行为。它们不验证逻辑是否正确,而只是记录当前的情况。

示例:我们有一个处理订单的“怪物”类。

public class OrderProcessor {    public void process(Order order) {        // 200行意大利面条式代码        if (order.getTotal() > 100) {            order.setStatus("VIP");        } else {            order.setStatus("STANDARD");        }        // ... 许多其他逻辑    }}

我们不知道内部细节,但可以编写一个测试:

@Testpublic void testProcessOrderWithHighTotal() {    // 给定    Order order = new Order();    order.setTotal(150);    OrderProcessor processor = new OrderProcessor();

// 执行 processor.process(order);

// 然后(记录当前行为) assertEquals("VIP", order.getStatus());}

运行测试。如果通过,说明你已经记录了当前行为。现在你有了防止回归的保护。



2. 提取方法

对于大方法来说,这是最安全且最有效的重构。思路很简单:取出一段完成单一功能的代码,将其提取到一个名称明确的方法中。

考虑一个糟糕代码的示例:

public double calculateEmployeePay(Employee emp) {    double basePay = emp.getBasePay();    double overtimePay = 0;    if (emp.getHoursWorked() > 40) {        overtimePay = (emp.getHoursWorked() - 40) * basePay * 1.5;    }    double tax = basePay * 0.13;    double insurance = 5000;    return basePay + overtimePay - tax - insurance;}

这里,加班费、税款和保险的计算混合在一起。让我们将它们分离:

public double calculateEmployeePay(Employee emp) {    double basePay = emp.getBasePay();    double overtimePay = calculateOvertimePay(emp, basePay);    double tax = calculateTax(basePay);    double insurance = getInsuranceCost();    return basePay + overtimePay - tax - insurance;}

private double calculateOvertimePay(Employee emp, double basePay) { if (emp.getHoursWorked() > 40) { return (emp.getHoursWorked() - 40) * basePay * 1.5; } return 0;}

private double calculateTax(double basePay) { return basePay * 0.13;}

private double getInsuranceCost() { return 5000;}

现在每个方法只负责一个任务。代码变得更易读,且便于单独测试。



3. 消除重复(DRY原则)

遗留代码经常因复制粘贴而出现问题。同一段逻辑可能出现在不同的类中。这是危险的:当需求发生变化时,你可能会忘记修改其中一个副本。

假设两个不同的服务

博客

书籍推荐