software engineering3 min read
Ten common anti-patterns in software development

Software development needs close attention to detail. This guide covers ten common anti-patterns: habits that look convenient at the time and cost more later. Knowing them helps you avoid the traps and write better code. For each one I've listed why it's tempting and why it hurts.
Global state
Global state is data that many parts of an application can read and change. It often leads to unexpected behaviour and bugs that are hard to trace.
Why it's tempting
- Easy to implement.
- Fewer parameters to pass around.
Why it hurts
- Makes code harder to test.
- Increases the risk of data corruption.
God objects
A god object is an object that knows too much or does too much. It breaks the single responsibility principle (see SOLID principles).
Why it's tempting
- Quick to build functionality around a single object.
Why it hurts
- Hard to maintain.
- Goes against the principles of object-oriented design.
Spaghetti code
Spaghetti code is tangled and unstructured, with no clear architecture or design.
Why it's tempting
- Quick to write at first.
Why it hurts
- Very hard to maintain.
- Hard to understand and debug.
Hard-coded values
Hard-coding means embedding configuration options directly in the code.
Why it's tempting
- Quick and easy to implement.
Why it hurts
- Makes the application less flexible.
- Makes code harder to reuse.
Singleton abuse
A singleton makes sure a class has only one instance and gives global access to it. Singleton abuse is using the pattern where it isn't needed.
Why it's tempting
- Easy access to data.
Why it hurts
- Brings all the risks of global state.
- Makes unit testing harder.
Deep nesting
Deep nesting is when loops or conditionals are nested many levels inside each other.
Why it's tempting
- Can be a quick way to solve a complicated problem.
Why it hurts
- Makes code harder to read.
- Increases cognitive load, and the number of paths to test. Cyclomatic complexity is one way to measure it.
Missing or misleading documentation
The codebase has little or no documentation, or documentation and comments that no longer match the code. Clear names and structure do much of the work; comments and docs should explain why, not repeat what the code already says.
Why it's tempting
- Faster initial development.
Why it hurts
- Makes maintenance harder.
- Confuses future developers, including your future self.
Magic numbers
Magic numbers are raw numbers in the code with no explanation and no named constant.
Why it's tempting
- Quick to write.
Why it hurts
- Makes code harder to read.
- Makes future changes harder.
Premature optimisation
Premature optimisation is spending a lot of time optimising code before knowing whether it's necessary. Donald Knuth's 1974 warning that premature optimisation is "the root of all evil" is the best-known statement of it.
Why it's tempting
- May give more efficient code early on.
Why it hurts
- Wastes time.
- Can make the code more complex.
Copy-pasting code
Copying and pasting the same or similar lines of code in several places.
Why it's tempting
- Saves time at first.
Why it hurts
- Makes the codebase harder to maintain.
- Increases the risk of bugs, because a fix in one copy is easily missed in the others.
Summary
Knowing these anti-patterns is the first step to avoiding them. Each has its short-term appeal and its long-term cost, and understanding the trade-off leads to better decisions.