Optimize for Maintainability
Write code for the engineer who maintains it next.
Overview
Most of a system's cost is paid after it ships. We favour clarity, documentation and low coupling so the system stays cheap to change.
Why
The person who pays that cost has less context than the author had, and what they lack is not the code, they can read the code. What they lack is the reasoning. That gap has a specific consequence. A control that looks unnecessary will eventually be simplified away by someone acting in good faith, unless the reason it exists is written next to it. A comment describing what a line does is redundant with the line. A comment recording why the safer-looking alternative was rejected is the only thing standing between the control and its removal. And the reasoning has to be written down at the time. A system whose decisions were never recorded is indistinguishable, later, from a system whose decisions were never made.
Standard
Comments record decisions and rejected alternatives, not descriptions. Keep the reasoning next to the thing it protects. Split documents by the question each answers, have each name the others, and state which one wins in a disagreement. Ask of inherited structure whether it was decided or received. Received structure is held to a different standard, because keeping it is an active choice rather than a constraint. When a unit grows past the point where its concerns can be named, split it along those concerns and verify behaviour is unchanged.
What This Forbids
- Comments that restate what the code already says
- Two documents covering the same question with no stated precedence
- Treating inherited structure as a constraint rather than a choice
- A placement chosen to break a dependency cycle and then left to become the architecture
Examples
- Comments that explain why a hop count is safer than a boolean, why silence must not mean an unencrypted connection, why a single container cannot serve two visibility levels, and why a log-record type admits no values. They are what stop a future maintainer from simplifying a security control back into a hole.
- Operational documents split by the question each answers, how a deployment is configured, whether one is ready to serve real users, how to change one that is already live, and what exact command to type. Each names the others and says which takes precedence.
- A service that had grown past 1,200 lines split by concern into lifecycle, read and scheduling, with tests repointed and behaviour verified unchanged rather than assumed.
Counter Examples
- A codebase with four months and hundreds of commits of genuinely original work whose own README was never edited from the generator's template. Everything transferable about it survives only because other projects wrote it down afterwards.
- A package holding a registry it is not named for, placed there to break a dependency cycle, with the misnaming conceded in a comment and left in place.
- A filename carrying a doubled extension that survived for months across two codebases, copied along with everything else.
Lessons Learned
- The most valuable thing in a repository is often not its code but the reasoning attached to the parts that look wrong until you know why.
- Documentation nobody wrote is indistinguishable from knowledge nobody had. A project can invent nearly everything in its family and leave no trace of how or why.
- A cycle-driven placement that survives becomes the architecture by default. Name the concept and give it a home before anything else depends on the temporary one.
Learned From
Related Principles· 2
Related Documents· 2
Referenced By· 5
Version History
- v0.1.0
Principle established with placeholder content.
- v0.2.0strengthened
Written from real experience. Added comments-carry-decisions, documents split by the question they answer, and the received-versus-decided test for inherited structure.