• Shift Elevate
  • Posts
  • Long Method: Extract Method Refactoring | Clean Code

Long Method: Extract Method Refactoring | Clean Code

Long methods (over 20 lines) are a common code smell that makes code harder to read and test.

We will see how we can refactor them effectively.

Clean Code Reference

⚠️ Code Smell: Long Method
Refactoring: Extract Method
🎯 Goal: Single responsibility per method

The Long Method code smell occurs when a method becomes too long and handles multiple responsibilities. The Extract Method refactoring technique breaks down these long methods into smaller, focused methods that each have a single responsibility.

The Code Smell: Long Method

Long Method is one of the most widespread code smells in software development. When a method exceeds 20-30 lines, it becomes difficult to understand, test, and maintain. The method tries to do too many things, violating the Single Responsibility Principle.

Symptoms

Impact

Methods with 20+ lines

Reduced readability

Multiple levels of nesting

Difficult testing

Comments explaining code

Higher bug risk

Here's a typical example of a long method:

public class OrderProcessor {
    public void processOrder(Order order) {
        // Validate order
        if (order == null) {
            throw new IllegalArgumentException("Order cannot be null");
        }
        if (order.getItems().isEmpty()) {
            throw new IllegalArgumentException("Order must contain at least one item");
        }
        if (order.getCustomer() == null) {
            throw new IllegalArgumentException("Order must have a customer");
        }
        
        // Calculate total
        double total = 0.0;
        for (OrderItem item : order.getItems()) {
            double itemPrice = item.getPrice();
            int quantity = item.getQuantity();
            double itemTotal = itemPrice * quantity;
            total += itemTotal;
        }
        
        // Apply discounts
        if (order.getCustomer().isPremium()) {
            total = total * 0.9; // 10% discount for premium customers
        }
        if (total > 100.0) {
            total = total * 0.95; // 5% discount for orders over $100
        }
        
        // Update order
        order.setTotal(total);
        order.setStatus(OrderStatus.PROCESSED);
        
        // Save to database
        orderRepository.save(order);
    }
}

This method is doing too many things: validation, calculation, discount application, and database operations. It's hard to test each behavior independently and difficult to understand at a glance.

The Refactoring: Extract Method

The Extract Method refactoring technique breaks down Long Method into smaller, focused methods that each have a single responsibility. This improves readability, testability, and maintainability.

Step by Step Refactoring Process:

  1. Identify distinct behaviors within the long method.

  2. Extract each behavior into a separate method with a descriptive name.

  3. Replace the original code with calls to the new methods.

  4. Test each extracted method independently.

Here's the refactored version:

public class OrderProcessor {
    public void processOrder(Order order) {
        validateOrder(order);
        double total = calculateOrderTotal(order);
        double discountedTotal = applyDiscounts(order, total);
        updateOrderStatus(order, discountedTotal);
        saveOrder(order);
    }
    
    private void validateOrder(Order order) {
        if (order == null) {
            throw new IllegalArgumentException("Order cannot be null");
        }
        if (order.getItems().isEmpty()) {
            throw new IllegalArgumentException("Order must contain at least one item");
        }
        if (order.getCustomer() == null) {
            throw new IllegalArgumentException("Order must have a customer");
        }
    }
    
    private double calculateOrderTotal(Order order) {
        double total = 0.0;
        for (OrderItem item : order.getItems()) {
            total += calculateItemTotal(item);
        }
        return total;
    }
    
    private double calculateItemTotal(OrderItem item) {
        return item.getPrice() * item.getQuantity();
    }
    
    private double applyDiscounts(Order order, double total) {
        double discountedTotal = total;
        
        if (order.getCustomer().isPremium()) {
            discountedTotal *= 0.9; // 10% discount for premium customers
        }
        if (discountedTotal > 100.0) {
            discountedTotal *= 0.95; // 5% discount for orders over $100
        }
        
        return discountedTotal;
    }
    
    private void updateOrderStatus(Order order, double total) {
        order.setTotal(total);
        order.setStatus(OrderStatus.PROCESSED);
    }
    
    private void saveOrder(Order order) {
        orderRepository.save(order);
    }
}

Benefits of Extract Method

Benefit

Description

Improved Readability

The main processOrder method now reads like a high level workflow, making it easy to understand the overall process.

Enhanced Testability

Each extracted method can be tested independently with focused unit tests.

Better Maintainability

Changes to specific behaviors (like discount logic) are isolated to single methods.

When to Apply Extract Method Refactoring

  • Methods longer than 20-30 lines.

  • Methods with multiple levels of nesting.

  • Methods that need comments to explain their behavior.

  • Methods that are difficult to test.

  • Methods that violate the Single Responsibility Principle.

Apply Extract Method refactoring to one Long Method in your current project today. Start with the method that's causing you the most pain during debugging or testing.

Repository & Resources

Complete Code Examples: Clean Code Repository

Find the complete implementation of Extract Method refactoring and other clean code techniques in our dedicated repository. Each example includes:

  • Before and after code comparisons

  • Unit tests demonstrating the improvements

Found this helpful? Share it with a colleague who's struggling with long methods. Have questions about refactoring complex methods in your codebase? Email us directly, we read every message and the best questions become future newsletter topics.