- 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:
Identify distinct behaviors within the long method.
Extract each behavior into a separate method with a descriptive name.
Replace the original code with calls to the new methods.
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.