---
name: aipatterns-code-smells
description: Detect code smells such as Long Method, Large Class, Primitive Obsession, Feature Envy, Shotgun Surgery, Duplicate Code, Speculative Generality and 17 more. Maps each smell to the refactorings that treat it, and says when to leave a smell alone. Use when reviewing code, when asked "what's wrong with this code", when planning a refactor, or when deciding whether code is worth changing.
license: MIT
metadata:
  source: https://aipatterns.dev/refactoring/smells
  version: "1.0.0"
---

# Code smells

A smell is a symptom, not a bug. It tells you where to look, not what to do. Some smells are acceptable. Every reference file has a **When to ignore** section. Read it before recommending changes.

## Review procedure

1. Scan the code with the quick checks below and list the smells you find, with locations.
2. For each smell, open its reference and check it against **Signs**. Then read **When to ignore**.
3. Rank by cost of the next likely change: smells in code that changes often come first, and smells in stable code come last.
4. For each smell you keep, name the treatment technique from its reference and hand it to the `aipatterns-refactoring` skill.
5. Report the findings as: smell → location → why it hurts here → proposed technique. Leave out smells you chose to ignore, or say in one line why you ignored them.

## Quick checks

**Bloaters**: code that grew too big.

- Function longer than one screen, or needs comments to explain sections: [Long Method](references/long-method.md)
- Class with many unrelated fields or methods: [Large Class](references/large-class.md)
- Strings and numbers standing in for domain concepts: [Primitive Obsession](references/primitive-obsession.md)
- More than three or four parameters: [Long Parameter List](references/long-parameter-list.md)
- The same few variables always appear together: [Data Clumps](references/data-clumps.md)

**Object-orientation abusers**

- `switch` on a type code repeated in several places: [Switch Statements](references/switch-statements.md)
- Fields that are set only in some situations: [Temporary Field](references/temporary-field.md)
- Subclass ignores or overrides away its parent's behavior: [Refused Bequest](references/refused-bequest.md)
- Two classes do the same job through different method names: [Alternative Classes with Different Interfaces](references/alternative-classes-with-different-interfaces.md)

**Change preventers**

- One class changes for many unrelated reasons: [Divergent Change](references/divergent-change.md)
- One change needs edits in many classes: [Shotgun Surgery](references/shotgun-surgery.md)
- Adding a subclass here forces one there: [Parallel Inheritance Hierarchies](references/parallel-inheritance-hierarchies.md)

**Dispensables**

- Comments that explain _what_ unclear code does: [Comments](references/comments.md)
- Copy-pasted logic: [Duplicate Code](references/duplicate-code.md)
- Class that doesn't pull its weight: [Lazy Class](references/lazy-class.md)
- Class that only holds fields: [Data Class](references/data-class.md)
- Unreachable or unused code: [Dead Code](references/dead-code.md)
- Hooks, parameters or abstractions "for later": [Speculative Generality](references/speculative-generality.md)

**Couplers**

- Method more interested in another object's data: [Feature Envy](references/feature-envy.md)
- Classes poke at each other's internals: [Inappropriate Intimacy](references/inappropriate-intimacy.md)
- `a.b().c().d()`: [Message Chains](references/message-chains.md)
- Class that only delegates: [Middle Man](references/middle-man.md)

**Other**

- A library lacks a method you need: [Incomplete Library Class](references/incomplete-library-class.md)
- One task chains several pass-through API tools over raw payloads: [Thin Tool Wrapper](references/thin-tool-wrapper.md)

Category overviews: [bloaters](references/bloaters.md), [OO abusers](references/oo-abusers.md), [change preventers](references/change-preventers.md), [dispensables](references/dispensables.md), [couplers](references/couplers.md), [other](references/other.md).

## Warnings

- Agent-written code often introduces **Speculative Generality**: interfaces, options and layers nobody asked for. Check your own changes for it.
- Don't "fix" a smell in code that is about to be deleted or is not going to change.
- Removing one smell can create its opposite. For example, over-applying Extract Class produces Lazy Class and Middle Man.
