Martin Fowler's Refactoring Techniques Enhanced by AI
Introduction
Martin Fowler's "Refactoring: Improving the Design of Existing Code" has been the definitive guide for improving code quality. With AI, we can apply these techniques more effectively and discover new refactoring opportunities.
AI-Enhanced Refactoring Catalog
1. Extract Method
AI can identify code that should be extracted into separate methods and suggest the extraction.
// Before: Long method with multiple responsibilities
function processOrder(order) {
// Validate order
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
if (!order.customerId) {
throw new Error('Order must have customer');
}
if (order.total <= 0) {
throw new Error('Order total must be positive');
}
// Calculate discounts
let discount = 0;
if (order.customer.isPremium) {
discount = order.total * 0.1;
} else if (order.total > 100) {
discount = order.total * 0.05;
}
// Apply discount
order.finalTotal = order.total - discount;
// Save order
return orderRepository.save(order);
}
// After: AI-suggested refactoring
function processOrder(order) {
validateOrder(order);
applyDiscounts(order);
return orderRepository.save(order);
}
function validateOrder(order) {
if (!order.items || order.items.length === 0) {
throw new Error('Order must have items');
}
if (!order.customerId) {
throw new Error('Order must have customer');
}
if (order.total <= 0) {
throw new Error('Order total must be positive');
}
}
function applyDiscounts(order) {
let discount = 0;
if (order.customer.isPremium) {
discount = order.total * 0.1;
} else if (order.total > 100) {
discount = order.total * 0.05;
}
order.finalTotal = order.total - discount;
}
2. Replace Conditional with Polymorphism
AI can identify complex conditional logic and suggest polymorphic solutions.
// Before: Complex conditional logic
function calculateShippingCost(order) {
if (order.shippingType === 'standard') {
return order.weight * 2.5;
} else if (order.shippingType === 'express') {
return order.weight * 5.0;
} else if (order.shippingType === 'overnight') {
return order.weight * 10.0;
} else {
throw new Error('Unknown shipping type');
}
}
// After: AI-suggested polymorphic solution
abstract class ShippingCalculator {
abstract calculateCost(weight: number): number;
}
class StandardShipping extends ShippingCalculator {
calculateCost(weight: number): number {
return weight * 2.5;
}
}
class ExpressShipping extends ShippingCalculator {
calculateCost(weight: number): number {
return weight * 5.0;
}
}
class OvernightShipping extends ShippingCalculator {
calculateCost(weight: number): number {
return weight * 10.0;
}
}
class ShippingCalculatorFactory {
static create(type: string): ShippingCalculator {
switch (type) {
case 'standard': return new StandardShipping();
case 'express': return new ExpressShipping();
case 'overnight': return new OvernightShipping();
default: throw new Error('Unknown shipping type');
}
}
}
function calculateShippingCost(order) {
const calculator = ShippingCalculatorFactory.create(order.shippingType);
return calculator.calculateCost(order.weight);
}
3. Introduce Parameter Object
AI can identify methods with many parameters and suggest parameter objects.
// Before: Method with many parameters
function createUser(
firstName, lastName, email, password,
dateOfBirth, address, phoneNumber,
preferences, isActive, role
) {
// Implementation
}
// After: AI-suggested parameter object
class CreateUserRequest {
constructor(
public firstName: string,
public lastName: string,
public email: string,
public password: string,
public dateOfBirth: Date,
public address: Address,
public phoneNumber: string,
public preferences: UserPreferences,
public isActive: boolean = true,
public role: UserRole = UserRole.USER
) {}
}
function createUser(request: CreateUserRequest) {
// Implementation
}
AI-Powered Refactoring Tools
1. Code Smell Detection
AI can identify code smells that humans might miss:
- Long Methods: Methods with too many lines of code
- Large Classes: Classes with too many responsibilities
- Duplicate Code: Repeated code patterns
- Complex Conditionals: Nested if statements
- Primitive Obsession: Using primitives instead of objects
2. Refactoring Suggestions
AI can suggest specific refactoring techniques based on code analysis:
// AI Analysis Output:
// File: UserService.js
// Issues Found:
// 1. Method 'processUserData' is 45 lines long (threshold: 20)
// Suggestion: Extract methods 'validateUserData', 'transformUserData'
// 2. Class 'UserService' has 8 methods (threshold: 6)
// Suggestion: Extract 'UserValidationService', 'UserTransformationService'
// 3. Duplicate validation logic in methods 'createUser', 'updateUser'
// Suggestion: Extract common validation to 'UserValidator' class
Refactoring Best Practices with AI
- Small Steps: Make small, incremental changes
- Test After Each Change: Ensure tests pass after each refactoring
- Review AI Suggestions: Don't blindly accept AI recommendations
- Maintain Code Intent: Ensure refactoring preserves original functionality
Bibliography
- Fowler, M. (2018). "Refactoring: Improving the Design of Existing Code"
- Fowler, M. (2002). "Patterns of Enterprise Application Architecture"
- Fowler, M. (2006). "Domain-Specific Languages"
- Beck, K. (2003). "Test-Driven Development: By Example"
Conclusion
AI enhances Martin Fowler's refactoring techniques by providing better detection of code smells and more accurate refactoring suggestions. However, human judgment remains essential for making the final refactoring decisions.