AdviceWeb Development

Code Review: What It's For and How to Make It Actually Useful

Aurélien Debord
Code Review: What It's For and How to Make It Actually Useful

Code review is the moment when one developer reads code written by another before it ships. On paper, it's simple. In practice, it's one of the clearest dividing lines between teams that ship reliable code and those that spend their time putting out fires. Done well, it catches bugs early and lifts the whole team's skill level. Done badly, it becomes a bottleneck that frustrates everyone.

What is a code review?

It's a reading of the code by one or more people who didn't write it. In concrete terms, a developer proposes their changes (most often through a pull request), a colleague reads them, asks questions, flags problems, suggests improvements. Once the feedback is handled, the code is approved and merged.

What you actually look at

A review isn't just hunting for typos. You check several things at once: does the code do what it's supposed to, does it handle edge cases, will it stay readable for whoever picks it up in six months, does it follow the project's conventions, does it introduce a security or performance risk. The "does it compile and is it properly indented" part should be delegated to tools. The human brain is there to judge what a machine can't evaluate: whether the approach makes sense.

Take a concrete case. The code below compiles, passes the linter, and still hides a defect a reviewer spots in seconds:

cart.js
function averageOrder(orders) {
  const total = orders.reduce((sum, o) => sum + o.amount, 0);
  return total / orders.length;
}

The day orders is an empty array, the function returns NaN and breaks the display downstream. No tool will flag it: that's exactly the kind of case a review catches. The matching comment would look like this:

issue (blocking)orders.length can be 0 here, which produces a division by zero. Add a guard at the start of the function and return 0 for an empty cart.

What a code review is not

It's not a test suite. A review doesn't replace unit tests: a reviewer won't run every scenario by hand. The two are complementary. It's also not a trial. The goal isn't to judge the developer's worth, but to improve one specific piece of code, at one specific moment.

Why take the time to review

Slow down to speed up — that's the whole paradox. Here's what you actually get out of it.

Catching problems as early as possible

A bug caught in review costs a few minutes to fix. The same bug found in production can cost a full day, not counting the impact on users. The earlier a defect is caught in the cycle, the cheaper it is to fix. The review is the last net before code touches the real world.

Spreading knowledge across the team

When only one developer knows a part of the code, their absence becomes a risk. Reviews force you to explain your choices and let others discover areas they never touch. It's also the best way for a junior to pick up a senior's reflexes — and for a senior to spot an obvious simplification a fresh pair of eyes caught.

Keeping things consistent over time

Without reviews, each developer applies their own habits. After a few months, the codebase looks like a patchwork where every file has its own style. That inconsistency is one of the quietest sources of technical debt. Reviews keep a shared line, project after project.

The different forms of review

There's no single way to review code. The format depends on the context.

The pull request

This is the standard today. The developer opens a pull request on GitHub, GitLab, or similar, reviewers comment line by line, and the discussion stays tracked. The upside: it's asynchronous, everyone reviews when they have time, and the history of exchanges is kept. The risk: pull requests so big nobody really reviews them.

Pair review

Two developers in front of the same screen, one writing, the other commenting live. Pair programming is, in a sense, a continuous review. More expensive in immediate time, but formidable on complex or critical parts where you want to avoid any mistake.

The quick check

For a one-line fix, there's no point triggering a heavy process. A glance over the shoulder or a quick approval is enough. Matching the depth of the review to the size of the change keeps the team from burning out on trivia.

An effective code review, in practice

This is where most teams get it wrong. A few rules make all the difference between a review that smooths things along and one that grinds them to a halt.

Keep reviews small

Past 400 lines, the ability to spot defects collapses: you start skimming. Better to split a big feature into several short pull requests than to ask a colleague to swallow 2,000 lines at once. A review under 200 lines, handled in less than an hour, is far more effective.

Critique the code, not the person

"This function does too much" lands better than "you split this badly." The nuance seems trivial; it changes everything over time. You comment on the code, never on the person who wrote it. And when you block a change, you explain why: a reviewer who just drops a "no" without justification wastes everyone's time.

Automate what can be automated

Formatting, convention compliance, catching obvious errors: all of that should run automatically before the review even starts. A linter, a formatter, and a test coverage measure wired into your CI free the reviewer from the tedious so they can focus on substance. It's also what keeps the team from arguing about spaces and semicolons.

Separate the essential from the detail

Not every comment carries the same weight. A security flaw should block the merge; a naming preference is just a suggestion. Clearly flagging what's blocking and what isn't — some teams use a prefix convention like Conventional Comments — keeps a minor remark from dragging a pull request out for days. In practice, it looks like this:

praise: nice call extracting this helper, the rest reads much better now.
issue (blocking): this query concatenates user input → SQL injection risk.
suggestion (non-blocking): renaming `tmp` to `pendingOrders` would be clearer.
question: why a 30s timeout here instead of the default value?

The prefix tells the developer right away what must be fixed before merging and what's just polish. An issue (blocking) gets fixed; a suggestion (non-blocking) gets discussed.

Pitfalls to avoid

The rubber-stamp review first: approving without reading, just to unblock a colleague. That's worse than no review at all, because it gives a false sense of safety. At the other end, perfectionism: demanding flawless code before every merge blocks delivery and saps morale. "Good enough" beats "perfect but never shipped."

Another common failing: the late review. A pull request sitting for three days means a developer returning to forgotten context and a branch that's diverged. Handling reviews within the day is part of a team's hygiene. Finally, watch out for bottlenecks: if one person approves everything, they become a single point of blocking — and a risk the moment they're away.

Conclusion

Code review is neither a luxury nor a formality. It's an investment that pays off with every bug avoided and every developer who levels up. The key comes down to a few things: short reviews, handled kindly, automated on the mechanical parts, and dealt with quickly. If you're taking over a codebase whose quality worries you, that's often where to start — and sometimes with an audit of the existing code before you even put a process in place. A team that reads its own code seriously ships with more peace of mind, over the long run.

Ready to get started?

From scoping to prototype, to AI integration.

We support your business software projects from start to finish.

Develop my project