Code Refactor Master When to use this Skill
Use this Skill when:
Refactoring existing code for better quality Eliminating code smells Improving code readability and maintainability Optimizing performance without changing behavior Applying design patterns Reducing complexity Cleaning up technical debt Refactoring Principles 1. Core Rules
Golden Rule: Make code changes that improve internal structure without altering external behavior
Key Principles:
One refactoring at a time Run tests after each refactoring Commit frequently with clear messages Keep refactoring separate from feature work Maintain backwards compatibility unless explicitly changing API
Red Flags to Refactor:
Code duplication (DRY principle) Long methods (>20-30 lines) Large classes (>300-500 lines) Long parameter lists (>3-4 parameters) Deeply nested conditionals (>3 levels) Comments explaining what code does (code should be self-explanatory) 2. Common Code Smells
Bloaters:
Long Method Large Class Primitive Obsession Long Parameter List Data Clumps
Object-Orientation Abusers:
Switch Statements (consider polymorphism) Temporary Field Refused Bequest Alternative Classes with Different Interfaces
Change Preventers:
Divergent Change (one class changes for many reasons) Shotgun Surgery (one change requires many small changes) Parallel Inheritance Hierarchies
Dispensables:
Comments (where code should be self-explanatory) Duplicate Code Lazy Class Dead Code Speculative Generality
Couplers:
Feature Envy Inappropriate Intimacy Message Chains Middle Man 3. Refactoring Catalog
Method-Level Refactorings:
Extract Method
// Before void printOwing() { printBanner(); // print details System.out.println("name: " + name); System.out.println("amount: " + getOutstanding()); }
// After void printOwing() { printBanner(); printDetails(getOutstanding()); }
void printDetails(double outstanding) { System.out.println("name: " + name); System.out.println("amount: " + outstanding); }
Inline Method
// Before - method too simple int getRating() { return moreThanFiveLateDeliveries() ? 2 : 1; }
boolean moreThanFiveLateDeliveries() { return numberOfLateDeliveries > 5; }
// After int getRating() { return numberOfLateDeliveries > 5 ? 2 : 1; }
Replace Temp with Query
// Before double calculateTotal() { double basePrice = quantity * itemPrice; if (basePrice > 1000) { return basePrice * 0.95; } return basePrice * 0.98; }
// After double calculateTotal() { if (basePrice() > 1000) { return basePrice() * 0.95; } return basePrice() * 0.98; }
double basePrice() { return quantity * itemPrice; }
Variable-Level Refactorings:
Rename Variable
Before
d = 10 # elapsed time in days
After
elapsed_time_in_days = 10
Split Temporary Variable
// Before double temp = 2 * (height + width); System.out.println(temp); temp = height * width; System.out.println(temp);
// After double perimeter = 2 * (height + width); System.out.println(perimeter); double area = height * width; System.out.println(area);
Class-Level Refactorings:
Extract Class
// Before class Person { String name; String officeAreaCode; String officeNumber;
String getTelephoneNumber() {
return "(" + officeAreaCode + ") " + officeNumber;
}
}
// After class Person { String name; TelephoneNumber officeTelephone = new TelephoneNumber();
String getTelephoneNumber() {
return officeTelephone.getTelephoneNumber();
}
}
class TelephoneNumber { String areaCode; String number;
String getTelephoneNumber() {
return "(" + areaCode + ") " + number;
}
}
Replace Conditional with Polymorphism
Before
class Bird: def get_speed(self): if self.type == "EUROPEAN": return self.get_base_speed() elif self.type == "AFRICAN": return self.get_base_speed() - self.get_load_factor() elif self.type == "NORWEGIAN_BLUE": return 0 if self.is_nailed else self.get_base_speed()
After
class Bird: def get_speed(self): pass # Abstract
class European(Bird): def get_speed(self): return self.get_base_speed()
class African(Bird): def get_speed(self): return self.get_base_speed() - self.get_load_factor()
class NorwegianBlue(Bird): def get_speed(self): return 0 if self.is_nailed else self.get_base_speed()
- Java-Specific Refactorings
Use Modern Java Features:
Replace Anonymous Class with Lambda
// Before
list.sort(new Comparator
// After list.sort((a, b) -> a.compareTo(b)); // Or even better list.sort(String::compareTo);
Use Streams API
// Before
List
// After
List
Replace String Concatenation
// Before - inefficient in loops String result = ""; for (String s : list) { result += s + ", "; }
// After StringBuilder result = new StringBuilder(); for (String s : list) { result.append(s).append(", "); } // Or better String result = String.join(", ", list);
Use Optional
// Before public User findUser(int id) { User user = database.getUser(id); return user != null ? user : new User(); }
// After
public Optional
Replace Type Code with Enum
// Before public static final int TYPE_A = 1; public static final int TYPE_B = 2;
// After public enum Type { A, B }
- Python-Specific Refactorings
Use List Comprehensions
Before
result = [] for item in items: if item > 0: result.append(item * 2)
After
result = [item * 2 for item in items if item > 0]
Use Collections Module
Before
counts = {} for item in items: if item in counts: counts[item] += 1 else: counts[item] = 1
After
from collections import Counter counts = Counter(items)
Use Context Managers
Before
file = open('file.txt') data = file.read() file.close()
After
with open('file.txt') as file: data = file.read()
Use f-strings
Before
message = "Hello, %s! You are %d years old." % (name, age)
After
message = f"Hello, {name}! You are {age} years old."
Use Type Hints
Before
def process(data): return [x * 2 for x in data]
After
def process(data: list[int]) -> list[int]: return [x * 2 for x in data]
Use Dataclasses
Before
class Point: def init(self, x, y): self.x = x self.y = y
def __repr__(self):
return f"Point(x={self.x}, y={self.y})"
After
from dataclasses import dataclass
@dataclass class Point: x: int y: int
- Clean Code Principles
Naming:
// Bad int d; // elapsed time in days
// Good int elapsedTimeInDays;
// Bad
public List
// Good
public List
Functions:
Small (20-30 lines max) Do one thing One level of abstraction Descriptive names Few arguments (0-3 ideal)
Comments:
// Bad - comment explains what code does // Check to see if employee is eligible for full benefits if ((employee.flags & HOURLY_FLAG) && (employee.age > 65))
// Good - code is self-explanatory if (employee.isEligibleForFullBenefits())
- Performance Refactorings
Algorithm Optimization:
Before - O(n²)
def has_duplicates(arr): for i in range(len(arr)): for j in range(i + 1, len(arr)): if arr[i] == arr[j]: return True return False
After - O(n)
def has_duplicates(arr): return len(arr) != len(set(arr))
Lazy Evaluation:
// Before - computes all values
List
// After - computes only what's needed return list.stream() .map(this::expensiveOperation) .findFirst() .orElse(null);
Memoization:
Before
def fibonacci(n): if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2)
After
from functools import lru_cache
@lru_cache(maxsize=None) def fibonacci(n): if n <= 1: return n return fibonacci(n-1) + fibonacci(n-2)
- Refactoring Workflow
Step-by-step process:
Identify: Find code smell or improvement opportunity Plan: Decide which refactoring to apply Test: Ensure tests exist and pass Refactor: Make one small change Test: Run tests again Commit: Save working state Repeat: Continue with next refactoring
Example workflow:
1. Create feature branch
git checkout -b refactor/improve-user-service
2. Identify issue (e.g., long method)
Read code, find UserService.processUser() is 150 lines
3. Run existing tests
mvn test # or pytest
4. Extract method
Break processUser into smaller methods
5. Run tests
mvn test # Ensure still passing
6. Commit
git commit -m "refactor: extract validateUser method"
7. Continue
Extract next method, repeat
- Refactoring Checklist
Before refactoring:
Tests exist and pass Understand the code behavior Have a clear goal Know which refactoring to apply
During refactoring:
Make small, incremental changes Run tests after each change Keep code working at all times Commit frequently
After refactoring:
All tests pass Code is more readable Complexity reduced No behavioral changes Documentation updated if needed 10. LeetCode-Specific Refactoring
Optimize brute force:
// Before - Brute force O(n²) public int[] twoSum(int[] nums, int target) { for (int i = 0; i < nums.length; i++) { for (int j = i + 1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { return new int[]{i, j}; } } } return new int[]{}; }
// After - Hash map O(n)
public int[] twoSum(int[] nums, int target) {
Map
Extract helper methods:
Before - monolithic
def solve(self, grid): # 50 lines of code mixing concerns
After - modular
def solve(self, grid): if not self.is_valid(grid): return []
processed = self.preprocess(grid)
result = self.compute(processed)
return self.format_output(result)
def is_valid(self, grid): # validation logic
def preprocess(self, grid): # preprocessing logic
def compute(self, data): # core algorithm
def format_output(self, result): # formatting logic
Refactoring Anti-Patterns
Don't:
Refactor without tests Change behavior during refactoring Make multiple changes at once Refactor and add features simultaneously Over-engineer simple code Prematurely optimize Project Context
For CS_basics repository:
Refactor solutions in leetcode_java/ and leetcode_python/ Maintain consistency across language implementations Keep algorithm explanations updated Follow project conventions Test refactored code with example inputs Document complexity improvements Tools and Resources
IDE Refactoring Tools:
IntelliJ IDEA: Refactor menu (Ctrl+Alt+Shift+T) VS Code: Python refactoring extensions PyCharm: Refactoring actions
Use automated refactoring when available:
Rename: Safe renaming across project Extract method/variable: Automatic extraction Inline: Safe inlining with preview Move: Restructure packages/modules