Code Smells to Avoid

About

A code smell is a surface-level symptom in the code that may indicate deeper problems in structure, readability, or maintainability. In the context of code style, code smells refer to patterns that make the code harder to read, understand, test, or evolve—even if the code “works.”

Recognizing and avoiding these smells leads to cleaner, more professional code that’s easier to review, maintain, and extend.

Importance of Identifying Style-Based Code Smells

  • Improves Code Quality: Enforces clarity and prevents errors caused by ambiguity.

  • Enhances Maintainability: Clean, smell-free code is easier to modify without breaking.

  • Simplifies Reviews: Code reviewers can focus on logic instead of formatting or cleanup.

  • Promotes Team Consistency: Everyone follows the same principles, reducing friction.

  • Facilitates Onboarding: New developers can quickly understand code structure and intent.

Common Code Style Smells to Avoid

1. Long Methods

Symptom: A single method spans dozens or hundreds of lines.

Why It’s a Smell:

  • Violates Single Responsibility Principle (SRP).

  • Hard to read and test.

Preferred Style:

  • Break into smaller, well-named private methods.

// Bad
public void processRequest(Request request) {
    // dozens of lines...
}

// Good
public void processRequest(Request request) {
    validate(request);
    enrich(request);
    persist(request);
}

2. Inconsistent Indentation or Spacing

Symptom: Mixed tabs and spaces, irregular line breaks, or misaligned code blocks.

Why It’s a Smell:

  • Reduces readability.

  • Causes noise in diffs.

Preferred Style:

  • Use 4-space indentation.

  • Apply auto-formatting tools consistently.

3. Excessive Inline Comments for Obvious Code

Symptom: Comments explaining what a clearly named method or variable already implies.

// Bad
int age = 18; // user's age
processData(); // call the process data method

// Good
int userAge = 18;
processUserData();

Why It’s a Smell:

  • Adds noise, clutters code.

  • Indicates poor naming rather than a need for a comment.

4. Magic Numbers and Strings

Symptom: Hard-coded literals scattered in logic.

// Bad
if (statusCode == 500) {
    retry();
}

// Good
private static final int SERVER_ERROR = 500;

Why It’s a Smell:

  • Reduces readability.

  • Makes changes error-prone.

5. Poor Naming Conventions

Symptom: Non-descriptive, inconsistent, or abbreviated variable and method names.

// Bad
int x; // what's x?
void doStuff() {}


// Good
int retryAttempts;
void calculateTransactionTotal() {}

Why It’s a Smell:

  • Makes intent unclear.

  • Slows down understanding and maintenance.

6. Duplicated Code Blocks

Symptom: Identical or very similar logic repeated in multiple places.

Why It’s a Smell:

  • Violates DRY (Don’t Repeat Yourself).

  • Increases risk of bugs during updates.

Preferred Style:

  • Extract common code into a shared method.

7. Empty Catch Blocks

Symptom: Catching an exception and doing nothing or just adding a comment.

// Bad
try {
    callService();
} catch (Exception e) {
    // ignored
}

Why It’s a Smell:

  • Silently swallows errors.

  • Makes debugging nearly impossible.

Fix:

  • Log the error or rethrow it with context.

8. Deep Nesting

Symptom: Excessive levels of if, for, or try blocks.

// Bad
if (user != null) {
    if (user.getProfile() != null) {
        if (user.getProfile().getAddress() != null) {
            ...
        }
    }
}

Why It’s a Smell:

  • Reduces readability.

  • Increases cognitive load.

Preferred Style:

  • Use guard clauses and null-safe methods (e.g., Optional).

9. Large Classes (“God Classes”)

Symptom: A class doing too many unrelated things.

Why It’s a Smell:

  • Difficult to understand, test, or reuse.

Preferred Style:

  • Split by responsibility.

  • Use service decomposition, interfaces, or helper classes.

10. Unnecessary Comments or TODOs Left Behind

Symptom: Outdated or vague comments that no longer match the code.

// TODO: Fix this later
processOrder();  // Already fixed

// Bad
// This function adds two numbers
public int add(int a, int b) {
    return a + b;
}

Why It’s a Smell:

  • Misleads readers.

  • Adds clutter and confusion.

11. Overuse of Static Utility Methods

Symptom: Everything in a utility class is static, even if state or configuration might be needed.

Why It’s a Smell:

  • Reduces testability and flexibility.

  • Can violate object-oriented principles.

Preferred Style:

  • Use dependency injection where appropriate.

12. Non-Descriptive Test Names

Symptom: Unit tests with names like test1(), validateSomething(), or shouldWork().

Why It’s a Smell:

  • Test purpose is unclear.

  • Hard to diagnose failures.

Preferred Style:

@Test
void shouldReturnValidTokenWhenCredentialsAreCorrect() {
    // ...
}

Last updated