Originally published on decentphp.dev — part of the Writing decent PHP course. View this lesson on the original site.

Preventing code rot with practical team habits

Code rot is mostly prevented through habits, not heroics.
The five habits to keep repeating are: train, identify, test, document, and stay calm.

1) Train: align the team on what "good" means

Training is not a one-off slide deck. It is shared expectations used in daily work.
If two developers have different definitions of "clean enough", code rot grows quietly between PRs.

What this looks like in practice:

  • short standards for naming, branching, and data consistency
  • examples of acceptable and unacceptable changes
  • review comments that teach, not just block

Common pitfall: assuming senior developers will "just know" and everyone else will copy by osmosis.

2) Identify: spot rot early while changes are still cheap

Most teams wait until a bug or incident forces cleanup. That is late and expensive.
You need a light way to flag risky areas before they fail in production.

What this looks like in practice:

  • tag modules with repeated regressions or confusing data shapes
  • keep a short list of "high-risk files" to improve gradually
  • call out ambiguous naming and duplicated rules in review

Common pitfall: creating a backlog of cleanup tickets that never gets time allocated.

3) Test: protect behaviour before changing structure

Refactoring without test coverage in fragile areas is guesswork.
The goal is confidence, not perfect coverage.

What this looks like in practice:

  • add a narrow test around the behaviour you are about to touch
  • verify current behaviour first, then refactor in small steps
  • prioritise flaky or high-change paths for better coverage

Common pitfall: attempting large rewrites before establishing behavioural safety checks.

4) Document: reduce tribal knowledge

Documentation here means useful context, not heavyweight manuals.
If the reason for a rule lives only in one person's head, it will be broken later.

What this looks like in practice:

  • write down naming decisions and canonical field choices
  • add brief notes in PRs when introducing or removing constraints
  • keep runbook steps for known fragile areas up to date

Common pitfall: writing docs once, then never revisiting them after behaviour changes.

5) Stay calm: avoid panic rewrites

When code feels messy, the instinct is often "rewrite it all".
That usually swaps known problems for unknown problems under deadline pressure.

What this looks like in practice:

  • break improvements into small, reviewable slices
  • stabilise one hotspot at a time
  • leave each change safer than you found it

Common pitfall: trying to fix architecture, naming, and behaviour in one massive PR.

A weekly loop your team can sustain

  • choose one risky area
  • define one concrete improvement
  • protect behaviour with a test or observable check
  • ship a small cleanup
  • document what changed and why

This is how teams prevent code rot without stalling feature delivery.

From Writing decent PHP — What decent PHP looks like