← Blog

August 22, 2026 · Steve Johnson

Code Review Comments That Catch Bugs vs. Comments That Catch Style

I went back through six months of my own code review comments on a project to see what I actually spent review time on, expecting a rough split between substance and style. It wasn't a split. It was a landslide — the overwhelming majority of comments were about naming, formatting, and minor structural preference, and the bugs that actually shipped in that window had sailed through review without a single comment near them.

Style comments are easy to write and easy to justify

A naming or formatting comment is low-risk to leave: it's rarely wrong, it's fast to write, it demonstrates that you read the diff, and the author usually just accepts it without pushback. A correctness comment is higher-risk: it requires actually tracing what the code does under conditions the diff doesn't make obvious, it can be wrong in a way that's embarrassing, and it takes real time. Given a fixed review budget, the easy, low-risk comments crowd out the hard, high-value ones by default, not because anyone decides style matters more, but because style comments are simply cheaper to produce and the cost difference isn't visible unless you go measure it.

That's what the six-month sample showed starkly: reviews that felt thorough — plenty of comments, active back-and-forth — were thorough at the wrong altitude. A pull request with fifteen comments about variable names and import ordering and zero comments about what happens when the new function receives an empty list isn't a well-reviewed pull request. It's a pull request that got a lot of attention pointed in a direction that didn't matter.

The bugs that got through had a pattern

Looking specifically at the bugs that shipped despite going through review, they clustered around a specific gap: edge cases the diff itself didn't surface. A new function handled the three cases exercised by its accompanying test, and the code review, reading the diff top to bottom, naturally followed the same three cases the author had already thought about. The case that broke in production — an empty input, a duplicate key, a null field the type system allowed but the business logic didn't expect — wasn't absent from the code by omission so much as absent from what the diff made salient to a reviewer reading it linearly.

That's a structural blind spot, not a carelessness problem: a code review that reads the diff as written will reliably find the same cases the author already tested, because that's what the diff is shaped around, and will just as reliably skip the cases the author didn't think of, because nothing about the diff points a reader there either.

What changed the ratio

The fix wasn't "review harder" — that's not an actionable instruction. It was adding one deliberate step to my own review process, done before reading a single line of the diff: read the PR description and ask what the three worst inputs to this function would be, independent of what the diff tests. Only after writing that down did I read the actual code, checking each of those three cases explicitly against what the function does. That single step, applied consistently, moved my own comment ratio dramatically toward substance, not because I got better at reading code, but because I stopped letting the diff's own framing dictate which cases I checked.

Comment volume was never the right proxy for review quality, and a code review that leaves fifteen comments without ever asking "what breaks this" has done less real work than one that leaves two comments after actually asking that question first.