Code Smells
Purpose
Help spot, name, and treat code smells — surface indicators that usually correspond to deeper problems in a system. A smell is not a bug: the code works. It's a sign that the design will be costly to extend, understand, or change. Naming the smell precisely points to the right refactoring.
What is a code smell?
"Code smells are certain structures in the code that indicate violation of fundamental design principles and negatively impact design quality."
Smells don't crop up all at once — they accumulate over time as a program evolves, especially when nobody actively removes them. Treat them as heuristics that warrant a closer look, not automatic defects: context decides whether a given smell is worth fixing now.
When To Use
Use this skill when the user asks to:
- Find smells in a file, module, or PR ("what smells do you see here?", "review this for code smells").
- Refactor code and wants the change anchored to a named smell and its standard treatment.
- Author code and wants a pre-merge check against common smells.
- Diagnose why a change is painful (e.g., "every time I touch X I have to edit five files").
When to ease off
Smells are defaults, not laws. Apply a lighter bar when the user signals urgency or disposability: production hotfix, time-boxed spike, or generated/boilerplate code they won't own. A short method, a small switch on a stable discriminant, or a tiny data holder can be perfectly fine. Prefer clarity and safe change over checklist compliance; escalate a treatment only when duplication, churn, or comprehension cost justifies it.
The Five Categories
Each smell belongs to one family. Detail for every smell — signs & symptoms, reasons it occurs, treatment (refactorings), and payoff — lives in REFERENCE.md.
Bloaters
Code, methods, and classes that have grown to unmanageable proportions. They accumulate gradually.
- Long Method
- Large Class
- Primitive Obsession
- Long Parameter List
- Data Clumps
Object-Orientation Abusers
Incomplete or incorrect application of object-oriented principles.
- Alternative Classes with Different Interfaces
- Refused Bequest
- Switch Statements
- Temporary Field
Change Preventers
A change in one place forces many changes elsewhere — development becomes slow and expensive.
- Divergent Change
- Parallel Inheritance Hierarchies
- Shotgun Surgery
Dispensables
Something pointless and unneeded whose removal makes code cleaner and easier to understand.
- Comments
- Duplicate Code
- Data Class
- Dead Code
- Lazy Class
- Speculative Generality
Couplers
Excessive coupling between classes, or what happens when coupling is replaced by excessive delegation.
- Feature Envy
- Inappropriate Intimacy
- Incomplete Library Class
- Message Chains
- Middle Man
Review Workflow
- Read from high level to detail (public API → implementation).
- Tag each issue with a smell name and its category from the index above.
- Assign severity:
blocker(correctness/safety risk),major(maintainability risk),minor(clarity),nit(style only). Most smells aremajor/minor, notblocker. - Propose the standard treatment (the named refactoring), not vague advice.
- Cite the relevant
REFERENCE.mdsection anchor (e.g.,REFERENCE.md#feature-envy).
Output Contract
Emit findings one line each where possible:
[severity] [smell] path:line — what's wrong → suggested refactoring (REFERENCE.md#anchor)
Optional summary at the end: counts by category and the top 3 recommended refactorings.
Quick Heuristics (highest leverage)
- A method longer than ~10 lines or that needs a comment to explain a block → suspect Long Method.
- A class with many fields/methods doing several jobs → Large Class / Divergent Change.
- The same group of fields/params appearing together repeatedly → Data Clumps / Long Parameter List.
- Primitives standing in for concepts (strings for currency, ints for state) → Primitive Obsession.
- A method more interested in another class's data than its own → Feature Envy.
a.getB().getC().getD()→ Message Chains.- One change forces edits in many classes → Shotgun Surgery; one class changed for many reasons → Divergent Change.
- Adding a subclass forces a parallel subclass elsewhere → Parallel Inheritance Hierarchies.
switch/ifchains on a type code that recur → Switch Statements.
Anti-Patterns to Flag Aggressively
- Duplicated business rules across files (Duplicate Code).
- Commented-out code and dead branches (Dead Code).
- Comments that excuse bad names instead of fixing them (Comments).
- Subclasses that throw/no-op inherited methods they don't want (Refused Bequest).
- Classes built for imagined future needs that never arrived (Speculative Generality).
- Fields only populated in certain circumstances (Temporary Field).