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()
4. Java-Specific Refactorings
Use Modern Java Features:
Replace Anonymous Class with Lambda
// Before
list.sort(new Comparator<String>() {
@Override
public int compare(String a, String b) {
return a.compareTo(b);
}
});
// After
list.sort((a, b) -> a.compareTo(b));
// Or even better
list.sort(String::compareTo);
Use Streams API
// Before
List<String> result = new ArrayList<>();
for (String s : list) {
if (s.length() > 3) {
result.add(s.toUpperCase());
}
}
// After
List<String> result = list.stream()
.filter(s -> s.length() > 3)
.map(String::toUpperCase)
.collect(Collectors.toList());
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<User> findUser(int id) {
return Optional.ofNullable(database.getUser(id));
}
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
}
5. 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
6. Clean Code Principles
Naming:
// Bad
int d; // elapsed time in days
// Good
int elapsedTimeInDays;
// Bad
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<>();
for (int[] x : theList) {
if (x[0] == 4) {
list1.add(x);
}
}
return list1;
}
// Good
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<>();
for (Cell cell : gameBoard) {
if (cell.isFlagged()) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
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())
7. 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<Integer> results = list.stream()
.map(this::expensiveOperation)
.collect(Collectors.toList());
return results.get(0);
// 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)
8. 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
9. 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<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[]{map.get(complement), i};
}
map.put(nums[i], i);
}
return new int[]{};
}
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/andleetcode_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