A code smell isn't a bug — the code still works. It's a pattern that reliably predicts where a bug, or a painful change, is more likely to happen later, which is exactly what makes it worth noticing before it becomes either.
Beginner
2 min read
A smell isn't a bug — it's a prediction
Refactoring, covered earlier in this domain, is the discipline of improving
code's structure in small, safe steps. Before refactoring anything, though,
you need a reason to — and "code smells" are the specific, recognizable
patterns experienced engineers learn to notice as predictors of future pain,
even though the code in front of them runs correctly right now.
Common smells worth recognizing on sight
Long functions doing several unrelated things. Not long because the
logic is inherently complex, but long because it's handling validation,
business logic, and formatting all in one place — each new requirement
has to be threaded through all of it at once.
Duplicated logic in more than one place. The same calculation or rule
copy-pasted into two files means every future change to that rule has to
remember to happen twice — and eventually, one copy gets updated and the
other doesn't.
A function whose name doesn't match what it does.validateUser()
that also saves the user to the database is a smell specifically because
the name is now actively lying to the next person who calls it expecting
only validation.
Deeply nested conditionals. Four levels of nested if statements
aren't wrong exactly, but they're a strong predictor that a future
developer (including you) will misread which branch a given line
actually belongs to.
A class or module that changes for many unrelated reasons. If a single
file gets edited for billing changes, UI changes, and email changes alike,
it's doing more than one job, and each unrelated change risks breaking the
others.
A smell is a signal to investigate, not a rule to obey blindly
Noticing a smell doesn't automatically mean refactor it right now — a smell
in code nobody touches often and that works fine may not be worth the risk
and time of changing. The value of recognizing smells is knowing where to
look when you're already about to touch that code for another reason, or
when a bug keeps recurring in the same area — at which point the smell you
already noticed usually points straight at the actual root cause.
Why this matters day to day
Learning to recognize these patterns on sight, the same way a proofreader
learns to spot a run-on sentence without consciously parsing grammar rules,
is a skill that develops with exposure to enough real code. It's also one of
the most useful things a code reviewer brings to a review that automated
tools can't — a linter can catch a missing semicolon, but "this function is
doing three unrelated things" still requires a person who's seen enough code
to recognize the shape of the problem.