A code smell hints at a defect — a defect suggests a vulnerability
Stateful code smells stink the loudest
Bugs are not random; they follow patterns. These are the families of stateful defects — how they read on the page, why they happen, and the philosophies that defuse them.
Code Smell
A pattern that hints at a structural problem. Rotting code does not cause smells — code causes smells.
Software Defect
The latent fault the smell was pointing at. It may pass every test and still be there.
Vulnerability
What the defect becomes once it ships and meets the real world.
Families of defect
Bugs of Mutated State
Bugs caused by changing the state of a program in ways that create unpredictability, where information and control flow become untraced.
- Wrong or unexpected results
- Unpredictable function output or operation
- Edge cases abounding in code
Bugs of Unstructured State
Bugs caused by consuming unknown or inadequately validated input as state, without type checking or structural contracts.
- Information doesn't fit its expected container
- Latent, lingering bugs even with more tests
- Poor big-O performance with respect to input size
Bugs of Shared State
Bugs caused by concurrency, caching, and the distribution of state across multiple independent actors or processes.
- Data is inaccessible or out of order
- Resources are slow or unavailable
- Information is wrong or outdated
Common Software Defects
The everyday defects in every codebase, read by how they're caught: readability smells a reviewer sees (duplication, magic numbers, bad names), correctness bugs tests catch (DRY violations, off-by-one, sloppy error handling), and security defects a scanner finds (SCA, SAST, DAST). Most don't crash on their own -- they make the stateful bugs harder to see, and the worst of them become vulnerabilities.
- The same change has to be made in several places
- Numbers and strings with no explanation
- Names that have to be decoded before they're understood
Compound Defects
Bugs with no single line number: they emerge where two stateful defects meet. You can only name them by their symptom, because the cause lives in the interaction.
- The bug cannot be reproduced consistently
- Whack-a-mole fixes that won't stay fixed
- Crashes first seen live, in the demo
This is why we can't have nice things
A code smell is not the bug. It is the smell of one nearby. A defect that ships does not stay a defect. It becomes something an attacker can use.
Software that crashes becomes a Denial-of-Service attack.
Edge cases & complexity becomes an Abuse of Terms.
Race conditions & lag becomes a way to cheat and scam.
- naming things
- off-by-one errors
- cache invalidation