Code Smells¶
"A code smell is a surface indication that usually corresponds to a deeper problem in the system." — Martin Fowler, Refactoring
Code smells are not bugs. They don't break the program. They are warnings — patterns in code that have a high probability of indicating something wrong with the design. A smell is the question; a refactoring technique is the answer.
This section follows refactoring.guru's classification: 22 smells grouped into 5 categories by the kind of problem they signal.
The Five Categories¶
| Category | What it signals | Smells |
|---|---|---|
| Bloaters | Code that has grown so large it is hard to work with | 5 |
| Object-Orientation Abusers | OOP features incorrectly applied or under-used | 4 |
| Change Preventers | One change forces ripple changes elsewhere | 3 |
| Dispensables | Pointless code that can be removed | 6 |
| Couplers | Classes know too much about each other | 4 |
Each category is delivered as an 8-file suite (junior → professional + tasks/find-bug/optimize/interview), covering every smell in the category collectively.
All 22 Smells (with primary cures)¶
Bloaters — code blocks that have grown too large¶
| Smell | Symptom | Primary cure |
|---|---|---|
| Long Method | A method's body is large enough that it doesn't fit on one screen | Extract Method |
| Large Class | A class accumulates too many fields and methods, doing too much | Extract Class |
| Primitive Obsession | Primitives (String, int) used where a small class belongs | Replace Data Value with Object |
| Long Parameter List | More than 3–4 parameters; signals a missing object | Introduce Parameter Object |
| Data Clumps | The same group of fields appears together in many places | Extract Class |
Object-Orientation Abusers — OOP features misused¶
| Smell | Symptom | Primary cure |
|---|---|---|
| Switch Statements | Long switch or chained if-else on type code | Replace Conditional with Polymorphism |
| Temporary Field | Field used only sometimes; null otherwise | Extract Class |
| Refused Bequest | Subclass uses only some inherited methods, ignores the rest | Replace Inheritance with Delegation |
| Alternative Classes with Different Interfaces | Two classes do similar work but expose different APIs | Rename Method, Move Method |
Change Preventers — one change forces many¶
| Smell | Symptom | Primary cure |
|---|---|---|
| Divergent Change | One class is changed for many different reasons (violates SRP) | Extract Class |
| Shotgun Surgery | One logical change forces edits in many classes | Move Method, Inline Class |
| Parallel Inheritance Hierarchies | Every subclass of one hierarchy needs a corresponding subclass in another | Move Method, Move Field |
Dispensables — pointless code¶
| Smell | Symptom | Primary cure |
|---|---|---|
| Comments | Comments compensating for unclear code | Extract Method, Rename Method |
| Duplicate Code | The same fragment appears in multiple places | Extract Method, Pull Up Method |
| Lazy Class | A class that does too little to justify its existence | Inline Class, Collapse Hierarchy |
| Data Class | A class with only fields and accessors, no behaviour | Move Method, Encapsulate Field |
| Dead Code | Code that is never executed | Just delete it |
| Speculative Generality | Abstractions added "just in case" with no real consumer | Collapse Hierarchy, Inline Class |
Couplers — classes too tightly bound¶
| Smell | Symptom | Primary cure |
|---|---|---|
| Feature Envy | A method is more interested in another class's data than its own | Move Method |
| Inappropriate Intimacy | Two classes know too much about each other's internals | Move Method, Hide Delegate |
| Message Chains | a.getB().getC().getD().doIt() (Law of Demeter violation) | Hide Delegate |
| Middle Man | A class that delegates almost everything to another | Remove Middle Man, Inline Method |
How to Read This Section¶
Each category folder contains an 8-file suite, identical to the Design Patterns section:
| File | Focus | Audience |
|---|---|---|
junior.md | "What is it?" "How to spot it?" — definitions and simple examples | Just learned the language |
middle.md | "Why?" "When?" — trade-offs and real-world cases | 1–3 yr experience |
senior.md | Architecture-scale impact, tooling, CI integration | 3–7 yr experience |
professional.md | Runtime, JIT, GC, allocation patterns under the hood | 7+ yr / specialist |
interview.md | 50+ Q&A across all levels | Job preparation |
tasks.md | 10+ exercises with solutions | Practice |
find-bug.md | 10+ buggy snippets to fix | Critical reading |
optimize.md | 10+ inefficient implementations to refactor | Performance practice |
Recommended order: junior.md → middle.md → senior.md → professional.md → practice files → interview.md for review.
Each file in a category covers all smells in that category collectively — for example, 01-bloaters/middle.md discusses Long Method, Large Class, Primitive Obsession, Long Parameter List, and Data Clumps together, drawing comparisons and showing how they often appear in concert.
Categories at a Glance¶
Status¶
- ⬜ Bloaters (Long Method, Large Class, Primitive Obsession, Long Parameter List, Data Clumps) — 0/8 files
- ⬜ OO Abusers (Switch Statements, Temporary Field, Refused Bequest, Alternative Classes) — 0/8 files
- ⬜ Change Preventers (Divergent Change, Shotgun Surgery, Parallel Inheritance Hierarchies) — 0/8 files
- ⬜ Dispensables (Comments, Duplicate Code, Lazy Class, Data Class, Dead Code, Speculative Generality) — 0/8 files
- ⬜ Couplers (Feature Envy, Inappropriate Intimacy, Message Chains, Middle Man) — 0/8 files
References¶
- Source: refactoring.guru — Smells
- Foundational book: Refactoring: Improving the Design of Existing Code (1999, 2nd ed. 2018) — Martin Fowler
- Companion section: Refactoring Techniques — the cures for the smells in this section
- Related section: Design Patterns — many techniques here transition code into the patterns documented there
Project Context¶
This section is part of the Refactoring.Guru roadmap, itself part of the Senior Project.