Writing Code Review Comments That Actually Help Developers Improve


I’ve reviewed thousands of pull requests over the years. I’ve also received thousands of review comments on my code. The quality difference between helpful and unhelpful code reviews is massive.

Bad code reviews block progress, create defensiveness, and teach nothing. Good code reviews improve code quality, develop skills, and strengthen teams. The difference isn’t about being “nice” versus “critical”—it’s about how you communicate.

The Useless Review Patterns

These review comment patterns waste everyone’s time:

“This is wrong” without explanation: Telling someone their code is wrong without explaining what’s wrong or why it matters doesn’t help them learn. They might fix this instance but won’t understand the principle.

Nitpicking without priority: Commenting on minor style preferences without indicating what actually matters creates work without value. Not every preference deserves a comment.

“I would have done it differently”: Your alternative approach might be valid, but if both approaches work fine, this comment just creates unnecessary revision work.

Demanding changes without context: “Change this” without explaining the reasoning creates confusion and doesn’t help the author understand why.

Vague criticism: “This seems off” or “I don’t like this” without specific actionable feedback leaves authors guessing what you want.

Passive-aggressive comments: “Interesting choice” or “Bold approach” communicates disapproval indirectly and unproductively.

Holy war topics: Fighting about tabs vs spaces, brace placement, framework preferences in code reviews wastes time better spent on actual issues.

I’ve received all these comment types. They’re frustrating and unhelpful.

The Helpful Review Patterns

Effective code reviews share characteristics:

Explain the why: Don’t just point out problems, explain why they’re problems. “This creates a memory leak because X” teaches more than “memory leak here.”

Prioritize feedback: Clearly distinguish between must-fix issues (bugs, security problems) and nice-to-have suggestions (style preferences, optimizations). Use labels like “blocking,” “suggestion,” “nit.”

Provide context: Reference documentation, explain the broader system implications, link to similar code, mention relevant constraints the author might not know.

Suggest solutions: When pointing out problems, propose possible fixes. This teaches approaches the author might not have considered.

Ask questions: “Is there a reason you chose X over Y?” invites discussion rather than demanding changes. Maybe the author has good reasoning you haven’t considered.

Recognize good code: Point out what was done well, not just problems. Positive feedback reinforces good practices.

Be specific: “The error handling in lines 45-52 doesn’t catch NetworkExceptions” is actionable. “Error handling is incomplete” is vague.

These approaches make reviews constructive learning experiences rather than gatekeeping exercises.

The Teaching Comments

The best review comments teach concepts beyond the immediate code change:

Explain patterns: “This is where we’d typically use the repository pattern because…” teaches architectural approaches.

Share experience: “I tried this approach in ProjectX and ran into performance issues when…” provides concrete experience.

Reference resources: “Check out this article on handling async errors: [link]” directs to deeper learning.

Point out edge cases: “This works for normal cases but will fail when…” helps authors think about robustness.

Explain tradeoffs: “You could use X for better performance but it costs readability. In this case, readability matters more because…” teaches decision-making.

These comments take more effort than just pointing out problems, but they actually improve team skill over time.

The Tone Question

Code review tone matters more than people acknowledge. Consider the difference:

Demanding: “Change this to use dependency injection.” Collaborative: “This would be easier to test with dependency injection. What do you think about refactoring?”

Judgmental: “This is the wrong approach.” Constructive: “Have you considered X approach? It handles the edge cases better.”

Dismissive: “This doesn’t work.” Helpful: “This fails when the input is null. Adding a null check at line 23 would fix it.”

The collaborative, constructive, helpful versions communicate the same technical content with less defensiveness and more learning.

I’m not suggesting sugar-coating everything or avoiding critical feedback. Direct, honest technical assessment is valuable. But you can be direct and kind simultaneously.

The Automation Question

Some review comments should be automated away:

Code formatting: Use automated formatters (Prettier, Black, gofmt). Don’t waste review time on formatting that tools can fix.

Style enforcement: Linters catch style violations. Configure them appropriately and don’t relitigate their decisions in reviews.

Basic bugs: Static analysis tools catch many bug classes. Run them in CI before review rather than manually finding these issues.

Security vulnerabilities: Automated security scanning finds many vulnerabilities faster than human reviewers.

Automate what’s automatable, save human review for things requiring judgment, context, and understanding.

The Scope Creep Problem

Code reviews often expand beyond the pull request’s scope:

“While you’re changing this file, can you also refactor that unrelated function?”

This creates scope creep. The PR that was supposed to be a small bug fix becomes a major refactoring. Original changes get lost in expanded scope. Review takes much longer.

Good practice: keep feedback scoped to the PR’s purpose. If you notice unrelated improvements, create separate tickets rather than demanding them in current review.

The Blocking vs. Non-Blocking Distinction

Clearly distinguish between:

Blocking issues: Bugs, security vulnerabilities, performance problems, violations of critical requirements. These must be fixed before merging.

Important but not urgent: Improvements that would be good but can happen later. Create follow-up tickets.

Suggestions: Nice-to-have improvements author can choose to implement or not.

Preferences: Minor style differences that don’t matter enough to block merging.

Many reviews treat everything as blocking, creating unnecessary back-and-forth and slowing development. Separating these categories helps authors prioritize and maintain momentum.

The Response to Disagreement

Authors sometimes disagree with review feedback. How you handle disagreement matters:

Ask for their reasoning: “Can you explain why you chose this approach?” Understanding their thinking might reveal they’re right and you missed something.

Explain concerns clearly: If you still think there’s a problem, articulate it specifically and completely so they understand your perspective.

Escalate true deadlocks: If you genuinely disagree on something important, involve a third person or team lead rather than arguing in comments.

Accept being wrong: If the author makes good arguments you hadn’t considered, acknowledge it and approve. Reviews aren’t about winning arguments.

Distinguish preferences from requirements: If you prefer A but they chose B and both work fine, that’s a preference not worth fighting over.

I’ve been on both sides of disagreements. The reviews that resolved productively involved genuine attempts to understand each other’s perspectives rather than defending positions.

The Junior Developer Factor

Reviewing junior developers’ code requires different approach than reviewing peers:

Be explicitly teaching: Junior developers benefit from explanations of why, not just what. Take time to explain concepts.

Prioritize learning: Sometimes accepting suboptimal but functional code while explaining better approaches for next time works better than demanding perfection immediately.

Provide examples: Showing specific code examples of better approaches helps juniors understand concrete alternatives.

Balance feedback: Don’t overwhelm with 50 comments on minor issues. Focus on most important learning opportunities.

Encourage questions: Create safe environment where asking “why?” doesn’t feel like challenging authority.

The goal is developing their skills over time, not perfecting every PR.

The Self-Review Practice

Before submitting code for review, I self-review:

  1. Read through the diff as if I’m a reviewer
  2. Add comments explaining complex sections
  3. Look for issues I’d flag in others’ code
  4. Check for items I commonly forget
  5. Verify tests cover the changes

This catches many issues before others spend time reviewing, making the formal review process faster and more focused on genuine questions.

The Review Speed Expectation

Slow reviews block progress and frustrate authors. Fast reviews keep work flowing.

Aim to review within 24 hours, ideally same-day. If you can’t review quickly, communicate that so authors know their work isn’t being ignored.

Large PRs take longer to review. If you receive 2000-line PRs regularly, the problem is PR size not review speed. Work with team to split changes into reviewable chunks.

Making Your Reviews Actually Help

To write code reviews that improve code and develop skills:

  1. Explain why, not just what
  2. Distinguish blocking from suggested changes
  3. Teach concepts, not just fix immediate code
  4. Be specific and actionable
  5. Suggest solutions, not just problems
  6. Ask questions to understand reasoning
  7. Recognize good code, not just problems
  8. Maintain collaborative tone
  9. Automate what’s automatable
  10. Review promptly

Code review is teaching opportunity, knowledge sharing, and quality gate all at once. Done well, reviews make everyone better. Done poorly, they’re bureaucratic gatekeeping that slows work without improving quality.

The difference is mostly about how you communicate feedback, not whether you provide it. Critical, thorough reviews can be helpful and collaborative. Gentle reviews can be useless if they don’t address real issues. Focus on making your feedback clear, actionable, and educational regardless of tone.