Make the Unsafe Unrepresentable
Prefer a type that forbids to a comment that warns.
Overview
Where a mistake would be serious, change the shape of the code so the mistake cannot be written. A convention that must be remembered will eventually be forgotten; a signature with no parameter for the dangerous value cannot carry it.
Why
Most safety properties are enforced by vigilance, a review comment, a naming convention, a rule in a document. Vigilance degrades: under deadline, under fatigue, under a new contributor who never read the document. Structure does not. This costs more than the documented-rule alternative, every time. It is worth paying precisely where the rule being forgotten once would be unacceptable rather than merely bad.
Standard
For any property whose violation would be serious, ask what change would make the violation unrepresentable rather than forbidden, then weigh that cost honestly against the cost of the rule being forgotten once. The moves that work: remove the parameter, so the dangerous value cannot be passed; model variants so a contradictory combination fails to compile; force the safe setting in the environment where it matters rather than reading it from configuration; and pin a deliberate looseness with a test, so nobody can later tighten a hint into a second copy of an authoritative rule. Apply it hardest at a boundary you own but do not control. The point where someone else's code calls yours is exactly where your conventions stop being enforceable.
What This Forbids
- Security or correctness properties that depend on remembering to call something
- Optional parameters whose omission is unsafe
- A safety flag that a configuration value can switch off in the environment where it matters
- Free-form open records in a place where a leak matters
- Shipping a shared component that weakens a guarantee its consumers already had
Examples
- A log-record builder whose input type admits only a statement, a duration, a row count and a performance tier. There is no field for parameters and no field for result rows, so leaking either requires a visible change to a function signature, which a reviewer cannot miss.
- A scaffolding tool that deliberately generates placeholder values passing shape checks, a placeholder address is still a valid address, paired with a validator taught to refuse scaffold text specifically. The failure it prevents is a deployment going live with the generator's own text as its public contact details.
- A command-line tool whose interactive validation hint is deliberately looser than the authoritative rule it defers to, with a test pinning the looseness, so a well-meaning contributor cannot tighten it into a drifting second copy.
- A session cookie's security flag forced on in production regardless of the environment variable, because the cookie is the entire credential and a wrong value is a full account takeover.
Counter Examples
- A tenant-scoping helper that routes the filter through one place so it is "impossible to silently forget", but is opt-in, so an unscoped query still compiles and runs. Half of this principle applied is a convention with a helper attached.
- A shared declaration format that typed its permission keys as plain strings while the consuming products already had typed unions. Adopting the shared format therefore removed a guarantee those products already had, and a misspelled key compiled.
- An upload policy that could express "lossless, at quality 80", two settings that contradict each other, kept apart only by convention. Modelling the variants would make the contradiction fail to compile.
- A helper accepting a location parameter it silently ignores, with a comment conceding that records pointing at the old location will read as missing.
Lessons Learned
- Every instance of this cost more than the documented-rule alternative, and every instance has already paid for itself.
- The strongest version of the idea is a signature change: making a leak require an edit that shows up in a diff is worth more than any amount of reviewer attention.
- A test can protect a deliberate imprecision as well as a precision. Pinning something to stay loose is a legitimate control when the alternative is a second copy of the rules.
- This principle is most often violated by accident at a boundary, the moment a rule has to survive being called by code you do not own.
Learned From
- DentraA log-record type with no field for values, a validator that refuses scaffold text, a forced cookie flag, and a test that pins a hint to stay looser than the rule it defers to.
- ZothKitThe inverse case: a shared vocabulary that weakened a consumer's existing type safety, found at the framework's own front door.
Related Principles· 2
Related Documents· 2
Referenced By· 10
Version History
- v0.1.0
Established from a set of controls that were converted from remembered rules into structural ones, each after a near miss.