🔄 Developer’s Guide to Refactoring

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

đźš© Code Smells

Here are the main categories of code smells that developers should watch out for:

🏋️ Bloaters

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).

Large Class

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() { /* ... */ }
}

Primitive Obsession

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
    ) {}

Long Parameter List

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
}