Code Smell Catalog
A comprehensive reference of the 12 most impactful code smells, based on Martin Fowler's taxonomy and updated with modern business impact data. Each entry includes severity, detection hints, refactoring strategies, and estimated annual cost.
Long Method
Bloaters
A method that has grown too large to understand at a glance. Generally any method over 20 lines deserves scrutiny; over 50 lines is a clear smell.
Detection
Cyclomatic complexity > 10, method length > 30 lines, high nesting depth
Business Impact
Long methods resist unit testing, harbour hidden bugs, and slow every code review. Research shows methods over 50 lines have 4x the defect density of shorter ones.
Refactoring
Extract Method, Replace Temp with Query, Decompose Conditional
God Class
Object-Orientation Abusers
A single class that knows too much or does too much. Often accumulates hundreds of methods and thousands of lines as the system grows without clear ownership.
Detection
Class with > 20 public methods, > 500 LOC, high afferent coupling (many dependents)
Business Impact
God Classes are merge-conflict hotspots and make parallel development nearly impossible. Teams report 3x longer PR review times on files containing god classes.
Refactoring
Extract Class, Extract Interface, Move Method, Introduce Facade
Duplicate Code
Bloaters
Identical or nearly identical code appearing in two or more places. Includes exact copies, structural duplication, and semantic duplication across classes.
Detection
Code clone detection tools (PMD CPD, SonarQube), diff-based review
Business Impact
Every bug fix must be applied in multiple places, and inconsistencies between copies create subtle production defects. Duplication accounts for an estimated 10-15% of all maintenance bugs.
Refactoring
Extract Method, Pull Up Method, Form Template Method
Feature Envy
Couplers
A method that seems more interested in the data of another class than in its own. Typically calls many getters on a foreign object.
Detection
Method makes 3+ calls to another class's methods or fields
Business Impact
Feature envy misrepresents system boundaries. Developers place new behaviour in the wrong module, causing logic to scatter and increasing the cognitive load of the codebase.
Refactoring
Move Method, Extract Method then Move Method
Data Clumps
Bloaters
Groups of data items that always appear together (e.g., street, city, postcode in every method signature) but are not wrapped in an object.
Detection
Three or more parameters consistently appearing together across multiple methods
Business Impact
Data clumps produce fragile parameter lists. Adding a field requires updating every call site. Validation logic duplicates instead of centralising.
Refactoring
Introduce Parameter Object, Preserve Whole Object
Primitive Obsession
Object-Orientation Abusers
Using primitive types (strings, integers, booleans) to represent domain concepts such as money, addresses, or phone numbers rather than proper value objects.
Detection
String fields representing structured values, magic strings/numbers in conditionals
Business Impact
Validation is scattered across the codebase. A single domain rule change (e.g., phone number format) requires hunting down every usage. Increases bug surface considerably.
Refactoring
Replace Data Value with Object, Introduce Value Object, Replace Type Code with Class
Switch Statements
Object-Orientation Abusers
Large switch or if-else chains that dispatch on a type code, usually duplicated across multiple methods in the codebase.
Detection
Switch on type fields, repeated if-instanceof chains, parallel conditionals
Business Impact
Violates the Open/Closed Principle. Adding a new type requires modifying every switch, which spreads change risk. Easily missed cases create runtime errors.
Refactoring
Replace Conditional with Polymorphism, Replace Type Code with Strategy
Parallel Inheritance Hierarchies
Change Preventers
Every time you add a subclass in one hierarchy, you must add a corresponding subclass in another hierarchy. A special case of shotgun surgery.
Detection
Subclass names with identical prefixes/suffixes in two separate hierarchies
Business Impact
Adding a feature requires at least two parallel changes. Teams underestimate effort, leading to missed deadlines. Forgotten updates in one hierarchy cause inconsistent behaviour.
Refactoring
Move Method, Move Field to eliminate one hierarchy
Lazy Class
Dispensables
A class that is not doing enough to justify its existence. Often a victim of overly optimistic abstraction or leftover from earlier refactoring.
Detection
Classes with fewer than 3 methods, classes that simply delegate to one other class
Business Impact
Lazy classes add indirection without value. Developers waste time locating logic that could be in a nearby class. They become confusion traps during onboarding.
Refactoring
Inline Class, Collapse Hierarchy
Speculative Generality
Dispensables
Code written to handle scenarios that do not currently exist - hooks, parameters, and abstractions added 'just in case'. Often characterised by vague naming.
Detection
Abstract classes with one implementation, unused parameters, hook methods never overridden
Business Impact
Speculative generality inflates complexity without delivering value. YAGNI violations cost teams an estimated 20% extra maintenance overhead on affected modules.
Refactoring
Collapse Hierarchy, Remove Parameter, Rename Method
Temporary Field
Object-Orientation Abusers
An instance variable that is only set and used in certain circumstances. The rest of the time it is null or meaningless, making the object's state unpredictable.
Detection
Fields set only in one method path, null checks before field use
Business Impact
Null pointer exceptions and unexpected state are the primary cost. Code reviewers cannot reliably reason about class invariants, slowing review and increasing bug escape rate.
Refactoring
Extract Class, Introduce Null Object
Message Chains
Couplers
A sequence of calls like a.getB().getC().getD().doSomething(). The code is tightly coupled to the entire navigation path.
Detection
Method chains longer than 3 hops, Law of Demeter violations
Business Impact
Any change to an intermediate object breaks all chains through it. Refactoring the middle of a chain requires updating every consumer. Increases fragility of the object graph significantly.
Refactoring
Hide Delegate, Extract Method