Refactoring is the process of restructuring existing code without changing its external behavior. This guide covers common code smells and their solutions.
📖 Learn more about refactoring patterns and techniques at: References Refactoring.guru - Comprehensive catalog of refactoring patterns and code smells Refactoring: Improving the Design of Existing Code - Martin Fowler’s definitive book on refactoring SourceMaking - Design patterns and refactoring techniques
Here are the main categories of code smells that developers should watch out for:
Code elements that have grown too large and unwieldy over time.
Bloaters are code, methods and classes that have increased to such gargantuan proportions that they are hard to work with. Usually these smells do not crop up right away, rather they accumulate over time as the program evolves (and especially when nobody makes an effort to eradicate them).
A class that has too many fields, methods, or lines of code.
// ❌ Bad Example
class UserManager {
private userData: any[];
private loginHistory: any[];
private preferences: any[];
createUser() { /* ... */ }
deleteUser() { /* ... */ }
updateUser() { /* ... */ }
validateUser() { /* ... */ }
handleLogin() { /* ... */ }
handleLogout() { /* ... */ }
resetPassword() { /* ... */ }
updatePreferences() { /* ... */ }
generateReport() { /* ... */ }
// ... many more methods
}
// âś… Good Example
class UserAuthentication {
handleLogin() { /* ... */ }
handleLogout() { /* ... */ }
resetPassword() { /* ... */ }
}
class UserProfile {
private userData: any[];
createUser() { /* ... */ }
updateUser() { /* ... */ }
deleteUser() { /* ... */ }
}
class UserPreferences {
private preferences: any[];
updatePreferences() { /* ... */ }
}
Using primitive types instead of small objects for simple tasks.
// ❌ Bad Example
class User {
constructor(
public firstName: string,
public lastName: string,
public streetAddress: string,
public city: string,
public state: string,
public zipCode: string,
public phoneAreaCode: string,
public phoneNumber: string
) {}
// âś… Good Example
class Name {
constructor(
public firstName: string,
public lastName: string
) {}
}
class Address {
constructor(
public street: string,
public city: string,
public state: string,
public zipCode: string
) {}
}
class PhoneNumber {
constructor(
public areaCode: string,
public number: string
) {}
}
class User {
constructor(
public name: Name,
public address: Address,
public phone: PhoneNumber
) {}
Methods with too many parameters are difficult to understand and maintain.
// ❌ Bad Example
function createUser(
firstName: string,
lastName: string,
age: number,
email: string,
phone: string,
address: string,
city: string,
country: string,
postalCode: string
) {
// Method implementation
}
// âś… Good Example
interface UserData {
firstName: string;
lastName: string;
age: number;
contact: {
email: string;
phone: string;
};
address: {
street: string;
city: string;
country: string;
postalCode: string;
};
}
function createUser(userData: UserData) {
// Method implementation
}