Skip to content

Refactoring


Definition

Refactoring Definition


Common Refactorings

// EXTRACT METHOD: Long method → shorter, named methods

// Before
void printOwing() {
    // Print banner
    System.out.println("********************");
    System.out.println("*** Customer Owes ***");
    System.out.println("********************");

    // Calculate outstanding
    double outstanding = 0;
    for (Order order : orders) {
        outstanding += order.getAmount();
    }

    // Print details
    System.out.println("Name: " + name);
    System.out.println("Amount: " + outstanding);
}

// After
void printOwing() {
    printBanner();
    double outstanding = calculateOutstanding();
    printDetails(outstanding);
}

private void printBanner() {
    System.out.println("********************");
    System.out.println("*** Customer Owes ***");
    System.out.println("********************");
}

private double calculateOutstanding() {
    return orders.stream()
        .mapToDouble(Order::getAmount)
        .sum();
}

private void printDetails(double outstanding) {
    System.out.println("Name: " + name);
    System.out.println("Amount: " + outstanding);
}

More Refactorings

// EXTRACT CLASS: Class doing too much

// Before
class Order {
    private String customerName;
    private String customerEmail;
    private String customerPhone;
    private List<LineItem> items;

    void sendConfirmation() { /* email logic */ }
    boolean validateCustomerEmail() { /* validation */ }
}

// After
class Order {
    private Customer customer;
    private List<LineItem> items;
}

class Customer {
    private String name;
    private String email;
    private String phone;

    void sendConfirmation() { /* email logic */ }
    boolean validateEmail() { /* validation */ }
}


// REPLACE CONDITIONAL WITH POLYMORPHISM

// Before
double calculatePay(Employee e) {
    switch (e.type) {
        case HOURLY: return e.hours * e.rate;
        case SALARIED: return e.salary / 12;
        case COMMISSIONED: return e.basePay + e.sales * e.commission;
    }
}

// After
abstract class Employee {
    abstract double calculatePay();
}

class HourlyEmployee extends Employee {
    double calculatePay() { return hours * rate; }
}

class SalariedEmployee extends Employee {
    double calculatePay() { return salary / 12; }
}

class CommissionedEmployee extends Employee {
    double calculatePay() { return basePay + sales * commission; }
}

Code Smells

Code Smells to Refactorings


Safe Refactoring Process

Safe Refactoring Process


Refactoring to Patterns

// Refactoring toward design patterns

// BEFORE: Conditional logic for discounts
class Order {
    double getTotal() {
        double total = calculateBaseTotal();

        if (customer.isGold()) {
            total *= 0.85;  // 15% off
        } else if (customer.isSilver()) {
            total *= 0.90;  // 10% off
        }

        if (isHolidaySeason()) {
            total *= 0.95;  // 5% off
        }

        return total;
    }
}

// AFTER: Strategy pattern
interface DiscountStrategy {
    double apply(double total);
}

class GoldDiscount implements DiscountStrategy {
    public double apply(double total) { return total * 0.85; }
}

class SilverDiscount implements DiscountStrategy {
    public double apply(double total) { return total * 0.90; }
}

class HolidayDiscount implements DiscountStrategy {
    public double apply(double total) { return total * 0.95; }
}

class Order {
    private List<DiscountStrategy> discounts;

    double getTotal() {
        double total = calculateBaseTotal();
        for (DiscountStrategy discount : discounts) {
            total = discount.apply(total);
        }
        return total;
    }
}

Tips & Tricks

Refactoring Tips & Tricks