Locality Over Perfection: The Realisation

February 12, 2025

I was tracing a late‑night production bug—one of those mystery 500s that only shows up in the logs when everyone else is asleep.
The class looked squeaky‑clean: each tiny method followed the Single‑Responsibility Principle (SRP) to the letter.
Problem was, the logic for a single user action was scattered across five files and three packages. My mental stack overflowed long before the call stack did.

The aha moment

  • Locality of behavior—all the code that changes together should live together—would have let me fix the issue in ten minutes.
  • Chasing SRP purity had created a treasure hunt instead of a clear path.
  • At 2 AM, elegance is the file where the bug lives, not the diagram in a design book.

What I changed

  1. Group by feature, not by theme. UserSignup package holds controller, validator, and event logic side‑by‑side.
  2. Accept larger files if it means fewer mental jumps. Readability is about flow, not line count.
  3. Refactor only when behaviors truly diverge. If two functions change in lockstep, keep them neighbors.

Why it matters

Clean architecture guidelines are tools, not commandments. SRP helps, but local reasoning speed decides whether a junior on‑call can save the night or wake the whole roster.
Now, when code reviews drift toward splitting hair‑thin classes, I ask, “Will this make debugging easier or harder?” If harder, the split can wait.

Shipping value is a team sport; keeping related code in one place is the best assist I’ve found.