Common Code Mistakes Every Engineer Eventually Learns the Hard Way

As engineers grow, the biggest shift is not learning new syntax, but learning to recognize bad code early. These mistakes have names for a reason, they show up everywhere, across teams, languages, and seniority levels.

This post is a practical breakdown of common code mistakes, why they happen, and why seniors care so much about them.


1. Dead Code

What it is

Code that never runs or is no longer used.

‘If this condition is never true, why is it still here?’

Why it’s bad

  • Adds noise and confusion
  • Makes refactoring risky
  • Hides real logic

Why it happens

Old features, rushed fixes, fear of deleting things.


2. Unreachable Code

What it is

Code that can never be executed, for example after a return or throw.

Why it’s bad

  • Signals poor control flow
  • Misleads future readers

This is often caught by linters, but still common in messy codebases.


3. Duplicate Code

What it is

The same logic copied across multiple places.

Why it’s bad

  • One change requires many edits
  • Bugs multiply fast

Classic symptom

You fix one bug, three more appear elsewhere.


4. God Class / God Object

What it is

One class that knows everything and does everything.

Why it’s bad

  • Impossible to test properly
  • Hard to change safely
  • Becomes a bottleneck

If you’re afraid to touch a file, it’s probably this.


5. Spaghetti Code

What it is

Tangled logic with no clear structure or flow.

Why it’s bad

  • Hard to reason about
  • Small changes cause big side effects

This often comes from feature-by-feature hacking without refactoring.


6. Shotgun Surgery

What it is

One logical change requires touching many files.

Why it’s bad

  • Easy to miss something
  • High regression risk

This is usually caused by poor separation of responsibilities.


7. Middleman Code

What it is

Code that adds no real value and just passes data through.

Why it’s bad

  • Extra indirection
  • Makes debugging slower

Abstraction is good. Useless abstraction is not.


8. Tight Coupling

What it is

Components depend heavily on each other’s internals.

Why it’s bad

  • Changes ripple everywhere
  • Testing becomes painful

Seniors optimize for loose coupling because it buys future flexibility.


9. Over-Engineering

What it is

Too many layers, patterns, or abstractions for a simple problem.

Why it’s bad

  • Slows development
  • Confuses new team members

Not every problem needs a framework or a design pattern.


10. Under-Engineering

What it is

No structure at all, everything hacked together.

Why it’s bad

  • Doesn’t scale
  • Becomes fragile very fast

This often happens under time pressure.


11. Flaky Tests

What it is

Tests that randomly pass or fail.

Why it’s bad

  • Destroys trust in the test suite
  • Slows teams down

Flakiness is worse than no tests.


12. Brittle Tests

What it is

Tests that break on minor, irrelevant changes.

Why it’s bad

  • High maintenance cost
  • Encourages disabling tests

Good tests verify behavior, not implementation details.


13. Magic Numbers

What it is

Hardcoded values with no explanation.

Why it’s bad

  • No context
  • Easy to misuse

If a number matters, name it.


14. Long Methods

What it is

Functions that do too much.

Why it’s bad

  • Hard to test
  • Hard to understand

If you need to scroll, it’s probably too long.


The Senior Perspective

Juniors ask: Does it work?

Seniors ask: Will this still work in a year?

Most bugs don’t come from syntax errors. They come from these patterns repeating quietly until the system becomes fragile.

Recognizing these mistakes early is what separates execution from real engineering judgment.