Fluent in a Dead Idiom
updated
Confidence two real review moments; the mechanism is argument from them, not data
“The greatest obstacle to discovery is not ignorance—it is the illusion of knowledge.” — Daniel J. Boorstin
A newer engineer left a note on my pull request: this array should be readonly. He was right. Readonly-by-default had become the house convention a while back — and I had missed it, in my own code, on a review I’d have sworn I read carefully. When I went looking, I hadn’t been flagging it in anyone else’s code either. The convention was in the codebase. It wasn’t yet in me.
The cause is the same one that makes fast reading fast. Reading code quickly is trained pattern recognition, and the training is time-stamped. What you learned as correct is what your eye reads as correct — and both the rules you adopted late and the rules you adopted early drift out from under you. The late ones you don’t have yet. The early ones you can’t let go of. The second kind is the dangerous one.
Bottom line up front
- Fast reading is a trained reflex, and the reflex is time-stamped. You read fluently in the idioms you trained on. That calibration drifts two ways.
- Adoption lag: a convention adopted after you trained isn’t in your reflex yet, so you don’t snag on its absence — you miss it in your own code and in review. (The readonly note above: the newer engineer had it, I didn’t.)
- Deprecation lag — the sharp one: an idiom you learned as correct stays correct to your eye. When the standard later turns against it, your reflex still reads it as fluent, so no snag fires and you don’t catch it in review.
- This is structural, not laziness. The reading reflex catches the wrong shape. A deprecated idiom is the right shape to you — so the guard meant to catch it is the very thing that waves it through. It’s typo-blindness: you can’t proofread your own idioms.
- You can’t teach against what you can’t see. If your eye never flags it, you never tell anyone to stop — so it ships and becomes “the way we do it here” by silent non-correction.
- The fix is an explicit rule, not more reading. A written rule fires on both the missing-new and the clung-to-old, whoever’s eye is running it — and its why teaches the deprecation your eye can’t even flag. That’s the case Rules Are the Alpha is making.
Reading is a reflex, and reflexes are dated
I’ve argued elsewhere that reading code fast is pattern recognition — you stop spelling out every token and start seeing shapes, the way a fluent reader sees words instead of letters. (Thinking at the Speed of Code is that argument; I won’t re-run it here.) The part I skipped is the cost of the shortcut: a reflex is calibrated to a moment. You trained it on the idioms that were current when you learned to read the language, and it keeps reading in those idioms after they change.
So fluency isn’t a fixed asset. It’s time-stamped. And it goes out of date in two directions.
The easy direction: the rule you don’t have yet
The readonly note is the easy direction, and it still caught me. Readonly-by-default arrived as a convention after my reading reflex had set. So when I read my own array declaration, nothing snagged — the code looked right, because it looked like the code I trained on. The newer engineer’s eye had been trained after the rule landed, so readonly was part of his baseline and its absence jumped out at him. He wasn’t more careful than me. He was calibrated later.
This direction is easy because it’s recoverable. The rule exists; someone has it; the fix is to internalise it, or better, to write it down so nobody has to carry it in their head. The gap is a lag, and lags close.
The hard direction: the idiom you can’t stop seeing as fine
Now the direction that doesn’t close on its own.
Years ago, writing JavaScript, I taught a teammate a little trick for a sort comparator. Two booleans, true ones first: return bSatisfied - aSatisfied. Subtract the booleans, let the language coerce them to 1 and 0, and you get your comparator for free. Compact, clever, and I was a little proud of it.
It leans on a language quirk to save a few characters, and the next reader has to know the quirk to read the line at all — and nothing I had switched on flagged it. With no lint enabled for it, the reviewer’s eye is the only guard. I’d fix it if you pointed at it. But I wouldn’t point at it. If I saw that line in review today, my eye would slide right over it — it reads as fluent to me, because I’m the one who made it fluent. I’ve got a matching habit on record: casting to string with a concat, "" + value instead of String(value). That one a linter can catch — it’s what ESLint’s no-implicit-coercion flags — but only if you’ve turned the rule on, and with it off my eye is the sole guard again. It reads as correct to me, because when I trained, it was.
That’s the deprecation lag, and it has two faces. One is production: I still reach for the old idiom when I write, because it’s the mechanised move — psychologists call it Einstellung, the state of mind that keeps applying a learned solution after a simpler one exists. That face is annoying but survivable; a linter or another reviewer can catch what I produce. The other face is the one that matters here: I can’t catch it in review. And that isn’t about discipline.
Why the guard is blind to exactly this
The reason is structural. The reading reflex works by flagging the wrong shape — code that doesn’t match the idioms you trained on. That’s what a snag is: a mismatch between the text and your pattern. A deprecated idiom, by construction, isn’t a mismatch. It’s the shape you trained on. So the very mechanism that makes you a fast reviewer — reading for the familiar shape — is the mechanism that waves your own dead idioms through. Fluency can’t audit itself. The thing that would catch the bad idiom is the thing that recognises it as good. You can override it — but only deliberately, by knowing to look for the specific idiom. Left to the reflex, it passes.
You know this feeling from prose: you can’t proofread your own writing. You read what you meant, your brain fills in the familiar shape, and the typo you’d catch in a heartbeat in someone else’s draft is invisible in yours. Reading is automatic and top-down — it serves up meaning and skips the surface. A deprecated idiom is a typo your eye has been trained to read as correctly spelled. Cognitive fluency does the rest.
There’s a worse consequence than the miss itself. If your eye never flags the idiom, you never tell anyone to stop using it. You can’t teach against what you can’t see. So a newer engineer picks it up from the codebase, it slips past everyone who trained when you did — they share the blind spot — and it graduates to house style by silent non-correction. No one defends the idiom. It survives because no reviewer’s reflex objects.
The rule snags where the reflex can’t
This is the sharpest case I know for the explicit, written rule. A rule doesn’t read for shape. It checks for a pattern whether or not that pattern feels fluent to the person running it — which is exactly the check your reflex can’t run on its own idioms. Write down “no implicit coercion — say what you mean” and whoever runs the checklist catches the line my eye slides over — mechanise it as a lint and it fires with no eye at all. Write down “arrays are readonly by default” and the same holds for the gap the newer engineer saw and I didn’t. Another reviewer with a differently-dated eye might catch either one by luck; the rule catches them on purpose. It holds still while fluency drifts, in both directions at once: the rule I don’t have yet and the idiom I can’t let go of, whoever happens to be reading.
And it does the one thing the reflex can’t: it teaches the deprecation. The rule’s why — leans on a coercion quirk, taxes the next reader with knowledge they shouldn’t need — is the explanation I’d never generate on my own, because I can’t see that the thing needs explaining. The rule catches what fluency misses and says out loud what fluency can’t.
That’s the corollary to reading fast. The reflex is what makes you quick, and the reflex is dated the day you finish training it. The rule is how you keep reviewing in a standard that has moved on from the one in your head.
How sure I am: the two receipts are lived — a readonly note I missed and a coercion trick I taught, both real review moments, genericised. The mechanism — that the fast reading reflex is blind to its own idioms — is reasoned from how fluency works plus those receipts, not measured; treat it as argument, not data. “Deprecated” here means a standard or a lint rule turned against the idiom, not that the language removed it. The prior art is real and named, but I’m citing established effects by analogy — I’m not claiming the studies tested code review.
Sources
- Thinking at the Speed of Code — reading fast as trained pattern recognition; this post is the corollary (the reflex is time-stamped). The author’s own argument, cited not re-derived.
- Abraham Luchins, “Mechanization in problem solving: the effect of Einstellung” (1942) — the mechanised state of mind that keeps applying a learned solution after a simpler one exists. The production-side prior art.
- Erik Dane, “Reconsidering the trade-off between expertise and flexibility: a cognitive entrenchment perspective,” Academy of Management Review (2010) — expertise trades flexibility for entrenchment; the expert-specific cousin.
- Rolf Reber, Piotr Winkielman & Norbert Schwarz, Effects of Perceptual Fluency on Affective Judgments, Psychological Science 9(1):45–48 (1998) — stimuli processed more fluently are judged more positively. The follow-on — Reber & Schwarz, Effects of Perceptual Fluency on Judgments of Truth, Consciousness and Cognition 8(3):338–342 (1999) — extends it to judged truth, the mechanism behind an idiom that reads as fluent being read as correct. Cited by analogy — the studies are on perception and judgment generally, not code review. (The everyday version: you can’t proofread your own writing because you read what you meant, not what’s on the page.)
- ESLint
no-implicit-coercion— flags shorthand type coercions such as"" + value(useString(value)). Opt-in, which is the point: with it off, only the reviewer’s eye guards the line. It does not flag the boolean-subtraction sort trick — and I had no lint enabled that would, which is why the eye was the sole guard there. - Rules Are the Alpha — the explicit rule as the durable asset; this post is the fluency-drift case for it.
Related: Thinking at the Speed of Code (the sibling — building the reading reflex; this is its time-stamp and its blind spot); Rules Are the Alpha (the explicit rule that stays put while fluency drifts); Familiarity Isn’t Trust and Confidently Wrong (fluency as a false signal — here turned on your own idioms).