Java

Extract Method, Class, and Interface

Extraction is the most fundamental refactoring skill. When code is too long, too complex, or has too many responsibilities, extraction is usually the answer. This article covers the three core extractions - Method, Class, and Interface - with step-by-step techniques and real examples.

📋 At a Glance

AspectDetails
Patterns CoveredExtract Method, Extract Class, Extract Interface
Primary UseReducing complexity, improving cohesion
IDE SupportExcellent (all major IDEs)
Risk LevelLow (behavior-preserving)
Time InvestmentMinutes per extraction

🎯 What You'll Learn

  • Extract Method with proper parameter and return handling
  • Extract Class by identifying responsibility boundaries
  • Extract Interface for testability and flexibility
  • Introduce Parameter Object for long parameter lists
  • Safe extraction techniques that preserve behavior
  • IDE shortcuts for automated extraction

🔥 Production Story: The 1,000-Line Method Tamed

A fintech company had a TransactionProcessor method that had grown to 1,047 lines over 5 years. Nobody dared touch it because:
  • Any change took 2-3 days to understand the code
  • Tests took 15 minutes to run
  • 40% of production bugs originated from this method

The team spent 2 weeks systematically extracting:

  • 23 methods from the original monolith
  • 4 collaborating classes (Validator, Calculator, Persister, Notifier)
  • 3 interfaces for external dependencies
Results:
  • Average method: 18 lines (was: 1,047)
  • Test runtime: 45 seconds (was: 15 minutes)
  • Bug rate: Dropped 70% in following quarter
  • Developer satisfaction: "I actually understand this code now"

🧠 Mental Model: The Extraction Decision Tree

TEXT(21 lines)
Code
Loading syntax highlighter...

🔬 Deep Dive

Pattern 1: Extract Method

When to use:
  • Method longer than 20 lines
  • Code block has a comment explaining what it does
  • Same code appears in multiple places
  • Code block operates at different abstraction level

Step-by-Step Process

Step 1: Identify the code block
JAVA(20 lines)
Code
Loading syntax highlighter...
Step 2: Identify inputs and outputs
TEXT(3 lines)
Code
Loading syntax highlighter...
Step 3: Extract and name
JAVA(25 lines)
Code
Loading syntax highlighter...

Handling Complex Extractions

Multiple return values - use a result object:
JAVA(39 lines)
Code
Loading syntax highlighter...
Local variables modified - return the value:
JAVA(22 lines)
Code
Loading syntax highlighter...

Pattern 2: Extract Class

When to use:
  • Class has multiple distinct responsibilities
  • Groups of methods use different subsets of fields
  • Class name includes "And" or is vague ("Manager", "Handler", "Util")
  • LCOM metric suggests low cohesion

Step-by-Step Process

Step 1: Identify responsibility clusters
JAVA(25 lines)
Code
Loading syntax highlighter...
Step 2: Create new classes for each cluster
JAVA(46 lines)
Code
Loading syntax highlighter...
Step 3: Update dependencies and callers
JAVA(24 lines)
Code
Loading syntax highlighter...

Pattern 3: Extract Interface

When to use:
  • Need to mock a class for testing
  • Multiple implementations possible (now or future)
  • Want to define a contract separate from implementation
  • Breaking dependency cycles

For Testing

JAVA(47 lines)
Code
Loading syntax highlighter...

For Multiple Implementations

JAVA(46 lines)
Code
Loading syntax highlighter...

Pattern 4: Introduce Parameter Object

When to use:
  • Method has more than 4 parameters
  • Same group of parameters appears in multiple methods
  • Parameters are logically related
JAVA(62 lines)
Code
Loading syntax highlighter...

⚠️ Common Mistakes

Mistake 1: Extracting Too Little

JAVA(20 lines)
Code
Loading syntax highlighter...

Mistake 2: Passing Object When Part Suffices

JAVA(9 lines)
Code
Loading syntax highlighter...

Mistake 3: Extracting Without Good Names

JAVA(9 lines)
Code
Loading syntax highlighter...

🐛 Debug This: The Extraction That Broke Everything

A developer reports: "I extracted a method to make the code cleaner, but now random tests are failing. I didn't change any logic!"

JAVA(45 lines)
Code
Loading syntax highlighter...
Why do tests fail after "clean" extraction? Find the missing behavior!

✅ Solution:
The extraction lost a side effect - the original code filled in missing prices:
JAVA(3 lines)
Code
Loading syntax highlighter...

This side effect was embedded in the calculation loop. When extracted to a stream, this price-lookup logic was dropped.

Problems:
  1. Hidden side effect - calculation also modified item prices
  2. Incomplete extraction - functionality was lost, not just reorganized
  3. Mixed concerns - calculation + data fixing in one loop
The lesson: Before extracting, identify ALL behaviors in the code block. Side effects are easy to miss, especially when embedded in loops. The correct extraction would be:
JAVA(12 lines)
Code
Loading syntax highlighter...

💻 Exercises

Exercise 1: Extract Methods

⭐ Difficulty: Easy | ⏱️ Time: 15 minutes

Task: Refactor this method by extracting meaningful methods.
JAVA(36 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(39 lines)
Code
Loading syntax highlighter...

Exercise 2: Extract Class

⭐⭐ Difficulty: Medium | ⏱️ Time: 20 minutes

Task: Split this class into focused classes.
JAVA(21 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(32 lines)
Code
Loading syntax highlighter...

Exercise 3: Extract Interface

⭐⭐ Difficulty: Medium | ⏱️ Time: 15 minutes

Task: Extract an interface to enable polymorphism.
JAVA(11 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(29 lines)
Code
Loading syntax highlighter...

Exercise 4: Extract Superclass

⭐⭐⭐ Difficulty: Medium-Hard | ⏱️ Time: 20 minutes

Task: Identify common behavior and extract a superclass.
JAVA(26 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(36 lines)
Code
Loading syntax highlighter...

Exercise 5: Recognize Extraction Opportunities

⭐⭐⭐⭐ Difficulty: Hard | ⏱️ Time: 25 minutes

Task: Identify all extraction opportunities and implement them.
JAVA(39 lines)
Code
Loading syntax highlighter...
✅ Solution:
JAVA(55 lines)
Code
Loading syntax highlighter...

🎤 Senior-Level Interview Questions

Question #1: How do you decide what to extract?

Strong answer:

I look for these signals:

  1. Comments as section headers - "// Calculate totals" → Extract calculateTotals()
  2. Different abstraction levels - High-level flow mixed with low-level details
  3. Repeated code patterns - Same 3 lines in multiple places
  4. Conditional blocks - Complex if/else often extracts well
  5. Loop bodies - Loop setup + iteration + body can be separated

The goal is: after extraction, the original method reads like a high-level summary.


Question #2: When should you extract an interface vs just use the class?

Strong answer:

Extract interface when:

  • Testing requires mocking - Interface makes stubbing easy
  • Multiple implementations exist - Now or planned soon
  • Dependency inversion needed - High-level shouldn't depend on low-level
  • Plugin architecture - Allow extension without modification

Don't extract when:

  • Only one implementation will ever exist
  • Class is a simple data object
  • Testing can use the real class
  • It's an internal implementation detail

Question #3: How do you handle extraction in legacy code without tests?

Strong answer:

Safe extraction process for legacy code:

  1. Characterization test first - Capture current behavior
JAVA(5 lines)
Code
Loading syntax highlighter...
  1. Extract mechanically - Use IDE refactoring, don't modify logic
  2. Run characterization tests - Must still pass
  3. Add focused tests - Now that methods are smaller
  4. Commit after each extraction - Easy rollback if something breaks

📝 Summary & Key Takeaways

Extraction Quick Reference

PatternWhen to UseIDE Shortcut
Extract MethodLong method, duplicated codeCtrl+Alt+M
Extract ClassLow cohesion, multiple responsibilitiesRefactor menu
Extract InterfaceNeed mock, multiple implementationsCtrl+Shift+Alt+T
Parameter Object4+ parameters, related dataRefactor menu

Extraction Checklist

Before extracting:

  • Tests exist (or write characterization tests)
  • Clear name for extracted element
  • Identified inputs and outputs
  • Understand all side effects

After extracting:

  • Original code reads as high-level summary
  • Extracted element is cohesive
  • Names reveal intent
  • Tests still pass

🏁 Conclusion

Extraction is the workhorse of refactoring. Master these patterns and you'll be able to tame any complex codebase one extraction at a time.

Key insight: Good extraction makes code read like well-written prose - the main method tells the story, helper methods provide the details.
Your next step: Continue to Part 7 (Replace Conditional with Polymorphism) to learn how to eliminate complex switch/if-else chains.

📅 Review Schedule for This Article

DayTaskTime
Day 1Review Extract Method step-by-step diagram5 min
Day 3Redo Exercise 1 (Extract Methods from createInvoice)15 min
Day 7Answer interview questions without looking10 min
Day 14Redo Debug This (side effect preservation)10 min
Day 30Apply Extract Method to one long method in your project15 min

Next in series: [Part 7: Replace Conditional with Polymorphism]