Code Review as Mentoring, Not Gatekeeping
The comments on a team's pull requests reveal more about its health than any standup. How to review so people learn a class of problem rather than a rule — explaining consequences, separating blocking from optional, and treating review as a conversation with a merge button.
Hessam Rastegari
Senior Android Developer · 12 years shipping Android
TL;DR — Review the decision, not just the code. A comment that states a rule produces compliance; a comment that explains the consequence produces an engineer who catches the next one without you. Label blocking versus optional so authors aren't guessing, ask questions when you don't know, and say specifically what's good. The measurable outcome is that the same defect stops appearing.
What review comments tell you
Give me ten minutes with a team's recent pull requests and I'll tell you more about how they work than a month of standups would. Not from the code — from the comments.
Teams where review is gatekeeping produce short, declarative notes: "use X", "rename this", "we don't do that here". They're efficient and they teach nothing. The same issues reappear in the next PR from the same person, because nobody explained why.
Teams where review is mentoring produce comments with reasoning in them, and their defect patterns change over time. That's the whole difference, and it compounds.
Explain the consequence, not the rule
The same defect, reviewed two ways:
"Don't use
!!here."
"This
!!will crash if the API omitsaddress— which it does for accounts created before 2023. Could we make it nullable and show the fallback? We hit this in the profile screen last quarter: [link to the incident]."
The first teaches someone to avoid a character. The second teaches them that our API has historical
data with missing fields, that !! is a claim about data you don't control, and that this has bitten
us before. They will catch the next instance themselves — including in code you never review.
The cost difference is about ninety seconds. The return is a colleague who needs you less.
Label blocking versus optional
A large share of review friction is authors guessing which of your fourteen comments they're actually required to act on. Remove the guessing:
blocking: this leaks the Activity — the listener is never removed in onDestroy
question: is this called on the main thread? if so the disk read will jank
nit: `userList` → `users`, optional
praise: the error handling here is much cleaner than the old path
Four prefixes, adopted in an afternoon, and the tone of a whole team's reviews changes. The author
knows exactly what stands between them and merge, and a nit: no longer reads as an obligation.
Ask when you don't know
The most useful review comments I've received were questions:
"What happens if
refresh()is called while the previous one is still running?"
The reviewer didn't know either. But the question made me trace it, and there was a race. A confident wrong assertion would have produced a defensive reply and no investigation.
Questions also model something junior engineers rarely see: senior engineers not knowing things. If every comment you leave is a confident directive, you're teaching that seniority means certainty, which is both false and quietly corrosive.
Approve with comments more often
Blocking a PR over naming teaches people that review is a gate to get through. That produces smaller truthful conversations and larger, less honest PRs.
My rule: block for correctness, security, data loss, and decisions that are expensive to reverse. Everything else is a comment on an approved PR. If a naming suggestion matters enough to enforce, it's a lint rule — automate it and stop spending human attention on it.
This does require trust, which is precisely why it's worth doing: extending it is how you build it.
Say what's good, specifically
The cheapest teaching tool available, and the least used:
"Extracting this into a fake instead of a mock is exactly right — this test will survive the repository refactor we've got planned."
Specific praise tells someone which of their instincts to keep. Generic praise ("LGTM 👍") tells them nothing. And a review thread that contains only criticism trains people to submit less, later, and bigger.
Review the decision, not just the code
The reframe that changed how I review:
You're not reviewing code. You're reviewing a decision someone made with the information they had.
So the useful questions are: what did they know? What would they have needed to know to decide better? Is that knowledge written down anywhere, or does it live in my head?
That last question is the important one. If the answer is "my head", the real fix isn't a review comment — it's an ADR, a lint rule, or a section in the onboarding doc. A defect you explain in review ten times is a documentation failure, not ten individual mistakes.
How to know it's working
The measurable signal isn't review speed or comment count. It's whether the same class of defect stops appearing from the same people. If you're leaving the same comment on the same person's PRs in month six, the reviews aren't teaching — and that's a fixable problem with your comments, not with them.