Code Smells

A code smell is a surface hint that a design may be rotting. It is not a compiler error and not a mandate to rewrite. Fowler’s catalog is still the shared language: name the smell, then decide if the design is actually wrong.

Smells worth a reflex

  • Long method / large class — too many reasons to change. Extract until a name is obvious.
  • Feature envy — a method that lives on A but talks only to B. Move it.
  • Data clumps — the same three parameters always travel together; they wanted a type.
  • Shotgun surgery — one change edits twelve files. The concept has no home.
  • Divergent change — one file changes for unrelated reasons. Split along the axes.
  • Primitive obsession — string email, int cents everywhere instead of small types.
  • Long parameter list — the same arguments on every method. They wanted a type.
  • Refused bequest — a subclass that ignores what the parent promised. That is Liskov substitution.
  • Speculative generality — abstract factory for a single implementation. YAGNI still applies.
  • Comments that explain the code — the code lost. Rename; keep comments for why, not what.

What a smell is not

A 40-line function that does one thing well. A switch over a closed set of HTTP status codes. Duplication of two similar lines you will not evolve together (the rule of three is a heuristic).

Example

Money and Email travel as one argument each.

readonly record struct Money(int Cents, string Currency);
sealed record Email(string Value);

static void Charge(Email email, Money amount) { }

What breaks it

The same three primitives are on charge, refund, and hold. The next currency rule is a three-place edit. Use the types above.

static void Charge(string email, int amount, string currency) { }
static void Refund(string email, int amount, string currency) { }
static void Hold(string email, int amount, string currency) { }

Pitfalls

  • Refactoring without tests — you are rearranging bugs.
  • Cleaning a module you will delete next week.
  • Treating linter “complexity” as truth without reading the code.

SOLID often names the same problems from the other side: The SOLID Principles.