Topik wawancara representatif

Bagaimana Cara Anda Melakukan Code Review?

UmumSedang
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Anda memiliki waktu 30 menit untuk meninjau pull request yang belum Anda kenal. Dalam urutan apa Anda memeriksanya, bagaimana Anda memisahkan blocker dari masukan non-blocking, bagaimana Anda menulis komentar, dan bagaimana Anda memutuskan untuk menyetujui (approve) atau meminta perubahan (request changes)?

Perintah dan Konteks yang Berlaku

Anda memiliki waktu 30 menit untuk meninjau pull request yang belum Anda kenal. Jelaskan bagaimana Anda merekonstruksi tujuannya, mengurutkan peninjauan, memisahkan blocker dari masukan non-blocking, menulis komentar yang dapat ditindaklanjuti oleh penulis, dan memilih antara approve, comment, dan request changes.

Ini adalah pertanyaan wawancara rekayasa perangkat lunak umum untuk peran backend, frontend, mobile, infrastruktur, dan engineering management. Pertanyaan ini dapat diajukan sebagai pertanyaan proses secara lisan atau sebagai peninjauan langsung (live review) terhadap diff yang disediakan. Kedua bentuk tersebut menguji apakah Anda dapat menemukan masalah yang paling penting bagi pengguna dan sistem dalam batas waktu, alih-alih memaksimalkan jumlah kesalahan pemformatan yang Anda laporkan.

Asumsikan Anda dapat melihat deskripsi pull request, kebutuhan (requirement) terkait, berkas yang diubah, dan hasil pengujian, tetapi Anda tidak mengetahui basis kode (codebase) tersebut dan tidak dapat terus-menerus bertanya kepada penulis. Jika pewawancara memberikan kondisi yang berbeda, sesuaikan kembali risiko dan cakupannya sebelum meninjau.

Apa yang Dievaluasi oleh Pewawancara

Sinyal pertama adalah apakah Anda merekonstruksi apa yang seharusnya dilakukan oleh perubahan tersebut. Tanpa requirement, kontrak API, atau batasan kegagalan (failure boundary), komentar hanya akan bermuara pada preferensi pribadi. Jawaban yang kuat membaca konteks pull request dan kode di sekitarnya, mengidentifikasi perubahan perilaku, dan baru setelah itu memeriksa baris demi baris.

Sinyal kedua adalah penentuan prioritas. Kebenaran (correctness), kerusakan data, keamanan, otorisasi, konkurensi, dan kompatibilitas umumnya layak mendapatkan perhatian sebelum penamaan atau tata letak. Pewawancara ingin melihat apakah Anda dapat menyatakan konsekuensinya dan meluangkan waktu pada jalur berisiko tertinggi.

Sinyal ketiga adalah bukti. "Ini mungkin sebuah bug" hanyalah sebuah petunjuk awal. Masukan berkualitas tinggi memberikan kondisi pemicu, konsekuensi yang dapat diamati, dan cara untuk memverifikasinya. Ketika konteks tidak ada, berikan pertanyaan yang tepat alih-alih menyamarkan tebakan sebagai kesimpulan yang bersifat blocking.

Terakhir, pewawancara mengevaluasi keputusan peninjauan dan komunikasi. Pisahkan perbaikan yang wajib, saran opsional, pertanyaan klarifikasi, dan nit. Dalam ringkasan, sebutkan apa yang telah Anda cakup, apa yang belum diverifikasi, dan mengapa Anda menyetujui atau meminta perubahan. Diskusikan kodenya dan dampaknya, bukan kemampuan penulisnya.

Pertanyaan yang Perlu Diklarifikasi Sebelum Menjawab

  • Apakah ini pertanyaan proses verbal atau live review terhadap diff? Untuk yang pertama, sajikan metode yang dapat digunakan kembali. Untuk yang kedua, luangkan beberapa detik untuk menyatakan metode tersebut lalu terapkan pada baris kode yang sebenarnya alih-alih membacakan daftar periksa (checklist).
  • Konteks apa yang tersedia? Adanya requirement, kontrak API, dan kode di sekitarnya memungkinkan Anda memverifikasi perilaku. Dengan fungsi yang terisolasi, nyatakan asumsi dan ubah kontrak yang tidak diketahui menjadi pertanyaan.
  • Apakah perubahan tersebut menyentuh domain berisiko tinggi? Pembayaran, otorisasi, privasi, migrasi, dan API publik meningkatkan standar pembuktian dan mungkin memerlukan pakar domain. Alat internal berisiko rendah dapat mendukung peningkatan bertahap yang lebih cepat.
  • Hasil kerja (deliverables) apa yang diharapkan pewawancara? Komentar inline, ringkasan, keputusan persetujuan, dan rekomendasi pengujian memerlukan alokasi waktu yang berbeda. Konfirmasikan output yang diharapkan sebelum menghabiskan waktu 30 menit.
  • Apakah ini pekerjaan normal atau perbaikan darurat (emergency fix)? Keadaan darurat dapat membenarkan patch yang lebih sempit dan pekerjaan tindak lanjut. Hal ini tidak membenarkan pengabaian risiko keamanan atau kerusakan data yang sudah diketahui.
  • Apakah Anda berkualifikasi untuk setiap domain yang terpengaruh? Jika perubahan melibatkan kriptografi, privasi, atau migrasi database di luar keahlian Anda, tinjau apa yang Anda bisa dan minta peninjau yang memenuhi syarat alih-alih menyetujuinya hanya berdasarkan rasa percaya diri.

Kerangka Jawaban 30 Detik

"Pertama, saya menetapkan tujuan pull request, perubahan perilaku, dan dampak kegagalannya, lalu meninjaunya dalam dua tahap (two-pass). Tahap pertama memetakan batasan perubahan, aliran data, dan jalur berisiko tinggi, dengan memprioritaskan kebenaran, keamanan, data, konkurensi, dan kompatibilitas. Tahap kedua memeriksa edge case, penanganan kesalahan, pengujian, observabilitas, performa, dan pemeliharaan (maintainability). Setiap komentar menyatakan tingkat keparahan, pemicu, konsekuensi, dan hasil yang diharapkan. Blocker yang dapat direproduksi berarti request changes; saran dan nit dapat menyertai persetujuan (approval). Saya mengakhiri dengan cakupan yang ditinjau, risiko yang belum diverifikasi, dan alasan keputusan saya."

Jawaban Mendalam Langkah demi Langkah

Tetapkan dasar pembanding (baseline) terlebih dahulu. Baca judul, deskripsi, requirement terkait, perubahan API atau model data, dan pengujian yang ada. Nyatakan kembali kontraknya dalam satu kalimat: "Perubahan ini memberi pengguna ini perilaku baru dalam kondisi ini dengan tetap mempertahankan jaminan yang sudah ada ini." Jika Anda tidak dapat menulis kalimat tersebut, dapatkan konteks sebelum memberikan komentar tingkat baris karena Anda belum memiliki standar kebenaran.

Selanjutnya, petakan batasan perubahan. Telusuri input, perubahan state, efek samping eksternal, dan jalur pengembalian (return paths), alih-alih hanya baris yang disorot. Pemanggil mana yang menerima parameter baru? Apakah penulisan database dan pengiriman pesan berada di dalam failure boundary yang sama? Apakah respons publik, format event, atau konfigurasi default berubah? Output dari tahap ini adalah model tentang tempat input masuk, batas kepercayaan (trust boundary) mana yang dilewatinya, state apa yang berubah, dan bagaimana kegagalan dapat terjadi.

Untuk contoh alokasi waktu 30 menit, gunakan 3 menit untuk tujuan, 7 menit untuk batasan dan jalur berisiko tinggi, 12 menit untuk pemeriksaan terperinci, 5 menit untuk pengujian dan pengamanan operasional, serta 3 menit untuk komentar dan keputusan. Ini adalah alokasi latihan yang disesuaikan dengan ukuran diff dan risiko. Tujuannya adalah untuk mencegah Anda menghabiskan 20 menit pertama hanya untuk masalah penamaan.

Gunakan urutan risiko ini pada tahap pertama:

  1. Perilaku dan kebenaran: Apakah jalur utama memenuhi kontrak? Apa yang terjadi dengan input kosong, permintaan duplikat, kegagalan parsial, dan percobaan ulang (retry)?
  2. Keamanan dan data: Apakah otorisasi dilakukan sebelum melewati trust boundary? Apakah data sensitif terekspos? Bisakah kegagalan menyebabkan kehilangan, duplikasi, atau state yang tidak dapat diubah kembali?
  3. Konkurensi dan kompatibilitas: Bisakah permintaan simultan merusak invarian? Apakah klien lama, data lama, dan versi campuran selama rolling deployment masih berfungsi?
  4. Batasan arsitektur: Apakah tanggung jawab berada pada komponen yang tepat, atau apakah perubahan tersebut melewati batasan yang ada dan menduplikasi state?

Tahap kedua memeriksa detail implementasi: alur kontrol dan propagasi kesalahan, pembersihan sumber daya (resource cleanup), skala kueri atau perulangan, log dan metrik, apakah pengujian benar-benar akan gagal ketika kodenya salah, serta apakah nama dan komentar membantu pembaca di masa mendatang. Tempatkan pemformatan dan gaya yang dapat diperbaiki secara otomatis di urutan terakhir agar nit yang dapat dideteksi oleh alat tidak menggeser penilaian manusia.

Untuk setiap temuan, verifikasi bahwa perubahan tersebut yang memperkenalkan atau mengeksposnya. Jika kode baru membaca items[0] ketika items kosong valid, itu adalah regresi konkret. Jika berkas yang sama berisi kompleksitas yang sudah ada sebelumnya dan tidak terkait, sebutkan sebagai technical debt atau buat pekerjaan tindak lanjut kecuali jika interaksinya dengan perubahan ini menciptakan risiko keamanan atau kebenaran. Peninjauan tidak boleh meluas tanpa batasan.

Gunakan empat intensi komentar:

  • Blocker: Bukti menunjukkan pelanggaran kontrak, hasil yang salah, masalah keamanan, kerusakan data, atau risiko kompatibilitas yang tidak dapat diterima. Hal ini harus diselesaikan sebelum penggabungan (merge).
  • Question: Konteks yang dapat mengubah kesimpulan tidak ada/hilang. Jawabannya dapat menyelesaikan kekhawatiran tersebut atau menaikkannya menjadi Blocker.
  • Suggestion: Peningkatan desain, kemudahan pemeliharaan, atau operasional yang bermanfaat, sementara implementasi saat ini masih memenuhi standar untuk merge.
  • Nit: Detail keterbacaan atau konsistensi non-blocking yang idealnya harus ditangani oleh pemformatan atau analisis statis.

Komentar yang dapat ditindaklanjuti berisi "label + kondisi + konsekuensi + hasil yang diharapkan", diikuti oleh satu kemungkinan arah solusi jika berguna. Contohnya:

Blocker: Ketika permintaan mengizinkan items=[], membaca items[0].id di sini akan melempar exception dan endpoint batch mengembalikan 500. Harap tangani array kosong sebelum perulangan dan tambahkan regression test; apakah akan mengembalikan hasil kosong atau 400 bergantung pada kontrak API.

Jika Anda tidak tahu apakah input kosong diperbolehkan, jadikan itu pertanyaan: "Apakah kontrak API mengizinkan array kosong? Jalur saat ini mengembalikan 500; jika diizinkan, ini memerlukan penanganan eksplisit dan pengujian." Ini melaporkan bukti tanpa mengada-ada requirement.

Akhiri dengan keputusan peninjauan. Pilih request changes ketika ada Blocker yang belum terselesaikan. Kirimkan komentar (comment) ketika konteks penting hilang alih-alih menyembunyikan ketidakpastian di balik persetujuan (approve). Lakukan approve ketika hanya saran non-blocking yang tersisa, dan nyatakan bahwa saran tersebut bukan syarat merge. Ringkasan harus menyebutkan cakupan yang ditinjau, temuan utama, bukti runtime atau pengujian, domain yang belum tercakup, dan status akhir.

CI yang hijau tidak membuktikan bahwa peninjauan telah selesai. Pengujian mungkin melewatkan branch penting, dan alat statis tidak mengetahui kontrak produk. Sebaliknya, peninjauan manusia tidak boleh menggantikan pengujian yang dapat dieksekusi. Hubungkan keduanya: identifikasi kondisi gagal dalam komentar dan minta pemeriksaan yang gagal sebelum perbaikan dan lolos setelahnya.

Contoh Jawaban Berkualitas Tinggi

"Saya tidak akan memulai dengan berburu kesalahan di tingkat baris. Saya akan membaca deskripsi pull request, requirement terkait, dan perubahan antarmuka, lalu menyatakan kembali tujuan dan perilaku lama yang harus tetap berlaku. Jika konteks tidak tersedia, saya akan mencantumkan asumsi alih-alih menyajikan tebakan sebagai blocker.

Dalam waktu 30 menit, saya akan menggunakan dua tahap. Tahap pertama mengikuti titik masuk, perubahan state, efek samping eksternal, dan jalur pengembalian, dengan memprioritaskan kebenaran, keamanan, kerusakan data, konkurensi, dan kompatibilitas. Tahap kedua mencakup edge case, penanganan kesalahan, performa, log, pengujian, dan pemeliharaan. Gaya kode berada di urutan terakhir, dan hanya ketika perkakas otomatis tidak mencakup masalah yang benar-benar memengaruhi pemahaman.

Setiap temuan harus menjawab tiga pertanyaan: apa yang memicunya, apa konsekuensinya, dan bagaimana cara memverifikasinya. Saya melabeli perbaikan yang wajib sebagai Blocker, konteks yang hilang sebagai Question, perbaikan non-blocking sebagai Suggestion, dan pemolesan kecil sebagai Nit. Misalnya, jika jalur array kosong membaca elemen pertama meskipun API menerima input kosong, saya akan menjelaskan bahwa itu mengembalikan 500 dan meminta penanganan eksplisit ditambah regression test, daripada hanya menulis 'kemungkinan masalah null'.

Sebelum mengirimkan, saya memeriksa bahwa setiap komentar berkaitan dengan diff ini, bahwa saya tidak mengangkat preferensi pribadi menjadi sebuah aturan, dan tidak ada peninjau domain wajib yang terlewatkan. Masalah keamanan, data, atau kebenaran yang dapat direproduksi akan menghasilkan request changes; saran saja dapat menyertai persetujuan. Ringkasan saya mencantumkan berkas yang dicakup, bukti pengujian, area yang belum diverifikasi, dan alasan keputusan sehingga penulis tahu tindakan selanjutnya dan peninjau berikutnya tahu apa yang sebenarnya saya tinjau."

Kesalahan Umum

  • Membuka diff dan berkomentar baris demi baris → Tanpa tujuan atau kontrak, kompromi (tradeoff) yang valid akan terlihat seperti kesalahan → Nyatakan kembali tujuan, perubahan perilaku, dan failure boundary terlebih dahulu.
  • Berkomentar sesuai urutan penemuan → Detail penamaan dapat mengubur risiko kerusakan data atau otorisasi → Jalankan tahap evaluasi risiko sebelum pemolesan implementasi.
  • Hanya menulis "ini mungkin bug" → Penulis tidak memiliki pemicu dan tidak dapat memverifikasi perbaikan → Nyatakan kondisi, konsekuensi, bukti, dan hasil yang diharapkan.
  • Membuat setiap komentar menjadi wajib → Penulis tidak dapat membedakan standar merge dari preferensi pribadi → Beri label Blocker, Question, Suggestion, dan Nit secara eksplisit.
  • Membacakan checklist panjang agar terlihat teliti → Daftar yang tidak diterapkan pada aliran data menunjukkan sedikit pertimbangan/penilaian → Telusuri satu jalur kritis dan jelaskan sisa cakupannya.
  • Menuntut agar semua masalah lama diperbaiki → Pull request meluas tanpa risiko atau validasi yang terikat batasan → Pisahkan regresi dari technical debt yang sudah ada kecuali jika keduanya bergabung menjadi masalah keselamatan atau kebenaran.
  • Memperlakukan CI yang hijau sebagai bukti persetujuan → Pengujian mungkin mengodekan kontrak yang salah atau melewatkan suatu branch → Periksa apakah pengujian gagal untuk contoh tandingan (counterexample) utama dan minta regression test yang hilang.
  • Mengomentari penulis alih-alih kodenya → Ini menciptakan sikap defensif dan tidak memberikan alasan teknis → Jelaskan kode, kondisi, dan dampaknya sambil mengasumsikan niat baik.
  • Menyetujui di luar keahlian Anda → Persetujuan tersebut menciptakan kepastian palsu → Nyatakan cakupan Anda dan minta peninjau domain terkait.

Pertanyaan Lanjutan dan Tanggapannya

Lanjutan 1: Bagaimana jika penulis membantah Blocker Anda?

Kembalilah ke kontrak dan konsekuensi yang dapat diverifikasi. Periksa apakah Anda tidak sepakat tentang input, risiko, atau kondisi rilis, dan gunakan reproduksi minimum bila memungkinkan. Jika bukti tidak menghasilkan konsensus, minta code owner atau domain owner untuk memutuskan dan catat kesimpulan verbal apa pun di pull request. Jangan biarkan ketidaksepakatan berlarut-larut tanpa batas.

Lanjutan 2: Bagaimana jika pull request terlalu besar untuk diselesaikan dalam 30 menit?

Jangan menyiratkan cakupan penuh. Pilih titik masuk, perubahan data, dan kontrak publik berdasarkan risiko; sebutkan berkas mana yang Anda tinjau baris demi baris, dipindai sekilas, atau tidak dicakup; lalu minta pemisahan (split) atau peninjau domain tambahan. Status persetujuan harus sesuai dengan cakupan yang benar-benar dilakukan.

Lanjutan 3: Bagaimana jika Anda menemukan masalah lama yang parah di luar diff?

Pertama-tama tentukan apakah perubahan ini memicu atau memperparahnya. Blokir jika interaksi tersebut menciptakan risiko keamanan, data, atau kebenaran untuk rilis saat ini. Jika masalah tersebut independen, catat buktinya, buat pekerjaan tindak lanjut berprioritas tinggi, dan beri tahu pemiliknya alih-alih memaksakan refaktor tanpa batas ke dalam pull request ini.

Lanjutan 4: Bisakah Anda menyetujui perbaikan darurat tanpa pengujian lengkap?

Tetapkan biaya langsung dari tidak dilakukannya perbaikan, apakah patch tersebut sempit, jalur rollback atau feature switch, dan validasi terarah terkecil yang tersedia. Proses darurat eksplisit dapat menerima cakupan pengujian tindak lanjut, tetapi risiko keamanan, kerusakan data, atau risiko yang tidak dapat diubah yang sudah diketahui tetap memerlukan standar persetujuan yang lebih tinggi. Batasan waktu tidak secara otomatis menyetujuinya.

Lanjutan 5: Bagaimana cara Anda meninjau domain yang tidak Anda ketahui?

Tetap periksa alur kontrol umum, penanganan kesalahan, pengujian, dan perubahan antarmuka sambil menandai hal-hal yang tidak Anda kuasai untuk dinilai. Minta pemilik yang sesuai untuk kriptografi, privasi, migrasi, atau konkurensi yang kompleks. Peninjauan parsial hanya berharga jika tidak disajikan sebagai persetujuan penuh.

Lanjutan 6: Apakah Anda masih perlu membaca setiap baris jika cakupan pengujian sudah luas?

Ya, dengan fokus yang berbeda. Pengujian memberikan bukti yang dapat dieksekusi untuk kasus-kasus yang dikodekan; peninjauan tetap bertugas menanyakan apakah requirement-nya benar, ada risiko yang terlewat, apakah desainnya menambah kompleksitas yang tidak perlu, dan apakah logging atau kompatibilitas sudah sesuai. Ubah contoh tandingan penting yang ditemukan dalam peninjauan menjadi pengujian agar kebenaran di masa mendatang tidak bergantung pada ingatan peninjau.

Sumber publik

Pertanyaan terkait