What Are Code Smells? 12 Common Smells With Examples (2026)
A practical catalog of code smells with real code snippets, why each one hurts, the refactor that fixes it, and the tools that detect them automatically.
Published:
What is a code smell?
A code smell is a characteristic in source code that does not break anything but signals a deeper design weakness. The phrase comes from Kent Beck and was popularized by Martin Fowler’s book Refactoring. The key distinction is that a smell is not a bug. The code works. Tests pass. Users are happy. But the code is quietly becoming harder to change, and every smell you ignore raises the cost of the next feature.
Think of smells the way a mechanic thinks of a rattle. The car still drives, but the rattle tells you something is loose and worth investigating before it becomes a breakdown. In software, that breakdown is technical debt - the accumulated cost of shortcuts and eroding design. Smells are the early, visible symptoms. This guide catalogs the twelve you will meet most often, shows each one in real code, and maps each to the tools that catch it.
Why code smells matter
Smells matter because software spends most of its life being modified, not written. A codebase riddled with duplication and 400-line methods is not dangerous on the day it ships - it is dangerous six months later when a junior developer needs to change a business rule and cannot find all five places it lives. Left unaddressed, smells compound into the kind of fragile system where every change breaks something unrelated.
The good news is that smells are the most fixable category of code problem, because the fix is almost always a known refactoring that preserves behavior. The hard part is spotting them consistently, which is where automated detection earns its keep.
12 common code smells with examples
1. Duplicated code
The most common smell of all. The same logic appears in multiple places, so a fix must be applied everywhere - and inevitably one copy gets missed.
// Smell: the same discount math copied in two places
function checkoutTotal(cart) {
return cart.items.reduce((s, i) => s + i.price * (i.vip ? 0.8 : 1), 0);
}
function invoiceTotal(order) {
return order.lines.reduce((s, i) => s + i.price * (i.vip ? 0.8 : 1), 0);
}
The fix is to extract the shared rule into one function. Duplication is tracked so widely that we have a whole guide to duplicate code checker tools, and it maps to the code duplication glossary term.
2. Long method
A method that does too much. If you cannot see the whole thing without scrolling, or you need comments to mark its “sections,” those sections want to be separate methods. Extract them until each method does one thing.
3. Large class (god object)
A class that has accumulated dozens of fields and responsibilities becomes the place every change has to touch. Split it along its responsibilities so each class has a single reason to change.
4. Long parameter list
# Smell: seven positional parameters, easy to pass in the wrong order
def create_user(name, email, age, country, plan, referrer, is_admin):
...
More than three or four parameters usually means several of them belong together in an object. Introduce a parameter object or a config struct.
5. Feature envy
A method that reaches into another object’s data more than its own. It “envies” the other class and probably belongs there instead. Move the method to the data it actually uses.
6. Primitive obsession
Using raw strings and integers where a small type would carry meaning and validation - representing money as a float, a phone number as a string, or a currency as a bare code. The fix is to introduce small value types that encapsulate the rules.
7. Magic numbers
// Smell: what is 86400?
if (session.ageSeconds > 86400) { logout(); }
// Better: the constant explains itself
static final int SECONDS_PER_DAY = 86400;
if (session.ageSeconds > SECONDS_PER_DAY) { logout(); }
Unexplained literals scattered through code hide intent and invite inconsistency. Name them.
8. Deeply nested conditionals
Three or more levels of nested if inside a loop are hard to follow and hard to test. Flatten them with guard clauses that return early, so the main path is not buried. This smell overlaps directly with high cyclomatic complexity.
9. Dead code
Code that is never executed - unreachable branches, unused functions, commented-out blocks kept “just in case.” It adds cognitive load and misleads readers about what the system does. Delete it; version control remembers. See the dead code glossary entry.
10. Shotgun surgery
A single conceptual change forces edits across many unrelated files. This is the mirror image of a god object - responsibility is scattered too thinly. Consolidate the logic so one change lives in one place.
11. Data clumps
The same group of fields travels together everywhere - always startDate, endDate, and timezone side by side. That clump is asking to become a DateRange type.
12. Speculative generality
Abstractions, hooks, and parameters added for a future that never arrived. Unused flexibility is a cost, not an asset. Remove it until a real requirement demands it.
How code smells map to detection tools
You can memorize this catalog, but consistent enforcement across a team needs tooling. Here is how the major platforms cover the smells above.
SonarQube treats “code smell” as a first-class issue category distinct from bugs and vulnerabilities, with rules for duplication, method length, class size, complexity, and magic numbers across 35-plus languages. Its quality gates can block a merge when new smells push a file past a threshold, and it estimates the remediation time each smell adds to your technical debt.
DeepSource flags anti-patterns and structural smells among its 5,000-plus analyzers and, notably, offers Autofix for many of them - turning “here is a smell” into a one-click fix PR. Its sub-5 percent false-positive rate means the smells it reports are usually worth acting on.
Sourcery specializes in exactly this problem. It detects long methods, duplication, and nested conditionals in pull requests and proposes the concrete refactor, with the deepest support for Python. Codacy aggregates duplication and complexity detection across 49 languages with quality gates on top. For a focused comparison, see our roundup of the best code smell detection tools.
How to fix code smells without breaking things
The cardinal rule of removing smells is that behavior must not change. That is what makes it refactoring rather than rewriting. Follow this loop:
- Make sure the code is under test first. If the smelly code has no tests, add characterization tests that pin down its current behavior before you touch it.
- Apply one small refactoring at a time. Extract a method, rename a variable, introduce a parameter object - then run the tests.
- Commit each safe step. Small, green commits make it easy to back out if something surprises you.
- Let the tool re-scan. Confirm the smell count actually dropped and that you did not push the problem elsewhere.
Fix smells opportunistically, not in a grand cleanup sprint. The most sustainable approach is the “campground rule” - leave each file a little cleaner than you found it, whenever you happen to be editing it for another reason.
Conclusion
Code smells are the visible symptoms of design decay. They are not bugs, which is exactly why they are easy to ignore until changing the code becomes painful and slow. Learn the common dozen so you can name them in review, wire up a tool like SonarQube, DeepSource, or Sourcery so they surface automatically, and fix them in small, tested steps as you go. Do that consistently and the deeper problem - accumulating technical debt - never gets the chance to compound.
Further reading
- Best Code Smell Detection Tools in 2026
- Best Duplicate Code Checker Tools
- What Is Cyclomatic Complexity?
- Best Code Quality Tools in 2026
Further Reading
GitarComments are not enough
Gitar applies the fix, validates it in CI, and clears the queue.
See it on your repo Read our independent Gitar reviewFrequently Asked Questions
What is a code smell?
A code smell is a surface indication in source code that usually points to a deeper design problem. The code still compiles and passes tests - a smell is not a bug. It is a warning sign, like a duplicated block or a 300-line method, that the code will be hard to change, test, or extend later. The term was popularized by Kent Beck and Martin Fowler in the book Refactoring.
Are code smells the same as bugs?
No. A bug produces wrong behavior right now. A code smell produces correct behavior but signals fragile design that makes future bugs more likely and changes more expensive. You fix bugs because the software is broken. You fix smells because the software is becoming hard to work with. Static analysis tools report them in separate categories for exactly this reason.
What are the most common code smells?
The most frequently flagged smells are duplicated code, long methods, large classes (god objects), long parameter lists, feature envy, primitive obsession, magic numbers, deeply nested conditionals, dead code, and shotgun surgery. Duplicated code and long methods are by far the two most common in most codebases and the two that automated tools catch most reliably.
How do you detect code smells automatically?
Static analysis platforms detect smells by parsing code into an abstract syntax tree and applying rules for size, duplication, complexity, and structure. SonarQube, DeepSource, Sourcery, and Codacy all report smells as a distinct category with severity levels and suggested refactors, and can fail a pull request when new smells are introduced beyond a threshold you configure.
Explore More
Tool Reviews
Free Newsletter
Stay ahead with AI dev tools
Weekly insights on AI code review, static analysis, and developer productivity. No spam, unsubscribe anytime.
Join developers getting weekly AI tool insights.
Related Articles
Is CodeRabbit Free for Open Source? Yes - And for Private Repos Too
CodeRabbit's free tier covers unlimited public and private repositories, not just open source. Here is exactly what the free plan includes, where the rate limits bite, and when to pay.
July 31, 2026
guideIs SonarLint Deprecated? No - Here's What Actually Happened
SonarLint was not deprecated. It was renamed to SonarQube for IDE on October 29, 2024, as part of a company-wide rebrand. Here is what changed, what did not, and what to install.
July 31, 2026
guideIs Semgrep Free for Commercial Use? Yes, With Two Catches
Semgrep Community Edition is LGPL-2.1 and free for commercial use. The paid tier is also free up to 10 contributors. Here is where the line actually falls and what you give up.
July 31, 2026
SonarQube Review
DeepSource Review
Sourcery Review
Codacy Review