← Writings
·

The Code Review Is Not About the Code

We treat code reviews as a quality gate. They are something more important: the primary mechanism by which a team builds shared understanding of a system.

Most code review advice focuses on what to look for: security vulnerabilities, performance problems, test coverage. This advice is not wrong. It is just aimed at the wrong goal.

A code review that catches a bug is useful. A code review that teaches the author something is more useful. A code review that teaches the reviewer something is most useful of all. The artifact — the merged pull request — is a byproduct. The real product is the shared understanding that the team builds by reading each other’s work.

When teams optimize code reviews for throughput, treating them as a gate to clear as quickly as possible, they produce correct code. They also produce teams where nobody knows how the system actually works except the person who wrote a given module. This is a common failure mode, and it kills institutional knowledge quietly.

The Asymmetry of Author and Reviewer

Authors are terrible reviewers of their own code. Not because they are careless, but because they carry context that is invisible to the reviewer. The author knows why a particular structure was chosen, which alternatives were rejected, which edge cases were already considered. The reviewer knows none of this.

This asymmetry is not a problem to be solved. It is the entire point. A reviewer who is genuinely confused by a piece of code is not failing to understand — they are surfacing a future maintenance problem. Code that requires the author’s context to understand will require that same context from the next person who needs to change it.

The most valuable sentence a reviewer can write is not “this is wrong.” It is “I don’t understand what this is doing.” That sentence, when taken seriously, produces better code more reliably than any style guide.

Two engineers looking at code on a screen together, one pointing at a specific line
The most important moment in a review is when someone admits they do not understand

What Good Feedback Looks Like

Code review feedback tends to cluster into two failure modes. The first is nitpicking: comments about variable names, whitespace, formatting choices that a linter should handle automatically. This creates noise that trains authors to dismiss review comments. The second is ambiguity: comments like “this seems wrong” or “could be cleaner” that require the author to guess what the reviewer actually wants.

Good feedback is specific about the problem and neutral about the solution. A comment like “I think this could be a security issue because X can be called with Y, which…” is better than “don’t do it this way.” The author learns something. They can evaluate whether the concern is valid. And if the reviewer is wrong, the author can explain why — which also teaches the reviewer something.

// Unhelpful comment
// This is too complex, refactor it

// Helpful comment
// If `user` is null here, `user.permissions.includes()` will throw.
// I don't see a guard — is there something upstream that prevents null?
// If not, we might want to add a null check or use optional chaining.

The second comment identifies the specific problem, explains the reasoning, asks a question rather than issuing a mandate, and gives the author enough information to either fix it or explain why it is not actually a problem.

The Praise Problem

Engineers are often taught that a code review should contain only problems to fix. This is a mistake, and a psychologically costly one.

When every code review is a list of things that are wrong, authors begin to dread the process. They begin to interpret silence — the review that has no comments — as grudging approval rather than genuine recognition. The feedback loop becomes purely negative.

Pointing out what is genuinely good in a pull request is not flattery. It is information. “This approach to error handling is clean — I hadn’t thought of handling it at the service boundary like this” tells the author their decision was correct and tells the reviewer that they have learned something. Both things are valuable.

Size Is the Biggest Problem

Everything above is downstream of one root cause: pull requests that are too large to review well.

A pull request with four hundred changed lines cannot be reviewed in five minutes. But many engineers spend five minutes on it anyway, because there is another one waiting and another after that. The result is a review that checks for obvious problems and approves. The subtle issues — the structural decision that creates coupling, the assumption baked into a data model — pass through unexamined.

A graph showing review quality dropping sharply as pull request size increases beyond 200 lines
Review quality degrades faster than linearly with pull request size

The practical fix is a cultural agreement that pull requests over a certain size — 200 lines is a common threshold — need to be broken down before review. This is not always possible for large refactors, but it is possible more often than engineers assume. A large change can almost always be decomposed into a sequence of smaller changes that each leave the system in a working state.

A team that ships many small, well-reviewed pull requests builds shared understanding of the system incrementally. A team that ships large pull requests builds a codebase where the history is legible but the reasoning is lost.


The code review is not about the code. It is about the team. Optimize accordingly.

Kebanyakan saran code review berfokus pada apa yang harus dicari: kerentanan keamanan, masalah performa, cakupan tes. Saran ini tidak salah. Ia hanya ditujukan pada tujuan yang salah.

Code review yang menemukan bug itu berguna. Code review yang mengajarkan sesuatu pada penulis lebih berguna. Code review yang mengajarkan sesuatu pada reviewer adalah yang paling berguna. Artefaknya — pull request yang digabungkan — adalah produk sampingan. Produk nyatanya adalah pemahaman bersama yang dibangun oleh tim dengan membaca pekerjaan satu sama lain.

Ketika tim mengoptimalkan code review untuk throughput, memperlakukannya sebagai gerbang yang harus dilewati secepat mungkin, mereka menghasilkan kode yang benar. Mereka juga menghasilkan tim di mana tidak ada yang tahu cara sistem sebenarnya bekerja kecuali orang yang menulis modul tertentu. Ini adalah mode kegagalan yang umum, dan ia membunuh pengetahuan institusional secara diam-diam.

Asimetri Penulis dan Reviewer

Penulis adalah reviewer yang buruk untuk kode mereka sendiri. Bukan karena mereka tidak hati-hati, tapi karena mereka membawa konteks yang tidak terlihat oleh reviewer. Penulis tahu mengapa struktur tertentu dipilih, alternatif mana yang ditolak, kasus tepi mana yang sudah dipertimbangkan. Reviewer tidak tahu semua itu.

Asimetri ini bukan masalah yang harus diselesaikan. Inilah seluruh intinya. Reviewer yang benar-benar bingung dengan sepotong kode bukan gagal memahami — mereka sedang memperlihatkan masalah pemeliharaan di masa depan. Kode yang membutuhkan konteks penulis untuk dipahami akan membutuhkan konteks yang sama dari orang berikutnya yang perlu mengubahnya.

Kalimat paling berharga yang bisa ditulis reviewer bukan “ini salah.” Melainkan “saya tidak mengerti apa yang ini lakukan.” Kalimat itu, ketika ditanggapi serius, menghasilkan kode yang lebih baik lebih andal daripada panduan gaya apapun.

Dua engineer melihat kode di layar bersama, satu menunjuk ke baris tertentu
Momen terpenting dalam review adalah ketika seseorang mengakui mereka tidak mengerti

Seperti Apa Feedback yang Baik

Umpan balik code review cenderung berkelompok dalam dua mode kegagalan. Yang pertama adalah nitpicking: komentar tentang nama variabel, whitespace, pilihan pemformatan yang seharusnya ditangani secara otomatis oleh linter. Ini menciptakan noise yang melatih penulis untuk mengabaikan komentar review. Yang kedua adalah ambiguitas: komentar seperti “ini tampaknya salah” atau “bisa lebih bersih” yang mengharuskan penulis menebak apa yang sebenarnya diinginkan reviewer.

Umpan balik yang baik spesifik tentang masalah dan netral tentang solusinya. Komentar seperti “Saya pikir ini bisa menjadi masalah keamanan karena X bisa dipanggil dengan Y, yang…” lebih baik dari “jangan lakukan dengan cara ini.” Penulis belajar sesuatu. Mereka bisa mengevaluasi apakah kekhawatiran itu valid. Dan jika reviewer salah, penulis bisa menjelaskan mengapa — yang juga mengajarkan reviewer sesuatu.

// Komentar yang tidak membantu
// Ini terlalu kompleks, refactor saja

// Komentar yang membantu
// Jika `user` adalah null di sini, `user.permissions.includes()` akan throw.
// Saya tidak melihat guard — apakah ada sesuatu di upstream yang mencegah null?
// Jika tidak, kita mungkin ingin menambahkan null check atau menggunakan optional chaining.

Komentar kedua mengidentifikasi masalah spesifik, menjelaskan alasannya, mengajukan pertanyaan daripada mengeluarkan mandat, dan memberi penulis informasi yang cukup untuk memperbaikinya atau menjelaskan mengapa itu sebenarnya bukan masalah.

Masalah Pujian

Engineer sering diajarkan bahwa code review hanya boleh berisi masalah yang harus diperbaiki. Ini adalah kesalahan, dan secara psikologis memakan biaya.

Ketika setiap code review adalah daftar hal-hal yang salah, penulis mulai takut pada proses tersebut. Mereka mulai menafsirkan keheningan — review yang tidak memiliki komentar — sebagai persetujuan yang enggan daripada pengakuan yang tulus. Loop umpan balik menjadi murni negatif.

Menunjukkan apa yang benar-benar bagus dalam pull request bukan pujian semata. Ini adalah informasi. “Pendekatan ini untuk penanganan error sangat bersih — saya belum terpikirkan untuk menanganinya di batas layanan seperti ini” memberi tahu penulis bahwa keputusan mereka benar dan memberi tahu reviewer bahwa mereka telah belajar sesuatu. Keduanya sama-sama berharga.

Ukuran adalah Masalah Terbesar

Semua yang di atas adalah turunan dari satu akar penyebab: pull request yang terlalu besar untuk di-review dengan baik.

Pull request dengan empat ratus baris yang diubah tidak bisa di-review dalam lima menit. Tapi banyak engineer menghabiskan lima menit untuk itu pula, karena ada yang lain menunggu dan satu lagi setelahnya. Hasilnya adalah review yang memeriksa masalah yang jelas dan menyetujui. Masalah-masalah halus — keputusan struktural yang menciptakan coupling, asumsi yang dipanggang ke dalam model data — berlalu tanpa diperiksa.

Grafik yang menunjukkan kualitas review turun tajam saat ukuran pull request melebihi 200 baris
Kualitas review menurun lebih cepat dari linear seiring bertambahnya ukuran pull request

Solusi praktisnya adalah kesepakatan budaya bahwa pull request di atas ukuran tertentu — 200 baris adalah ambang yang umum — perlu dipecah sebelum di-review. Ini tidak selalu mungkin untuk refactor besar, tapi ini lebih mungkin daripada yang diasumsikan oleh engineer. Perubahan besar hampir selalu bisa diurai menjadi rangkaian perubahan yang lebih kecil yang masing-masing meninggalkan sistem dalam keadaan bekerja.

Tim yang mengirimkan banyak pull request kecil yang di-review dengan baik membangun pemahaman bersama tentang sistem secara bertahap. Tim yang mengirimkan pull request besar membangun codebase di mana sejarahnya dapat dibaca tapi alasannya hilang.


Code review bukan tentang kodenya. Ini tentang timnya. Optimalkan sesuai dengan itu.