Perintah dan skenario
Sebuah basis kode C++ yang besar menggunakan beberapa kompiler, versi pustaka standar, dan mode build. Tim ingin menggunakan C++26 Contracts untuk prakondisi dan pascakondisi API, tetapi khawatir tentang dukungan kompiler yang tidak merata, perilaku proses online setelah pelanggaran, dan armada build lama yang tidak dapat ditingkatkan versinya. Rancang peluncuran bertahap dan jelaskan validasi serta rollback.
Hal yang diuji oleh pewawancara
- Apakah Anda membedakan ekspresi kontrak dari asersi pengujian, penanganan pengecualian, dan perilaku yang tidak terdefinisi (undefined behavior).
- Apakah Anda mengidentifikasi batasan kompatibilitas di seluruh standar, kompiler, linker, mode runtime, dan ABI.
- Apakah Anda menyertakan penanganan pelanggaran, biaya performa, dan keselamatan produksi dalam desain rilis.
- Apakah Anda dapat memajukan fitur bahasa dengan migrasi kecil dan bukti yang dapat diobservasi daripada penulisan ulang sekaligus.
Pertanyaan klarifikasi untuk diajukan terlebih dahulu
- Matriks kompiler, pustaka standar, sistem build, dan platform target apa yang ada, dan target mana yang harus mempertahankan versi lama?
- Apakah kontrak ditujukan untuk API publik, batasan modul internal, atau invarian data? Apakah pelanggaran harus menghentikan proses, mencatat log, menjeda debugging, atau melanjutkan?
- Berapa anggaran performa online, tingkat insiden, metode rollback, dan kemampuan simbolikasi untuk layanan inti?
- Apakah asersi, pengujian, analisis statis, dan release gate sudah menyediakan dasar pengukuran (baseline) migrasi?
Jawaban 30 detik
Saya akan memperlakukan Contracts sebagai semantik antarmuka dan diagnostik, bukan sebagai pengganti semua pengujian atau penanganan pengecualian. Pertama, saya akan memetakan dukungan kompiler, lalu melakukan uji coba pada satu pustaka internal dan membandingkan mode diaktifkan, dinonaktifkan, dan penanganan pelanggaran. Header publik harus tetap dapat digunakan oleh kompiler lama melalui jalur kondisional atau kontrak yang dinonaktifkan. Saya akan memigrasikan dari API internal ke layanan kritis, mengukur keberhasilan build, pelanggaran, latensi, dan kompatibilitas biner. Setiap pelanggaran online memerlukan jeda eksplisit dan jalur rollback.
Pembahasan mendalam
1. Tentukan masalah yang diselesaikan oleh kontrak
Prakondisi menggambarkan kewajiban input, pascakondisi menggambarkan apa yang harus berlaku saat kembali (return), dan invarian membatasi status objek. Keduanya menempatkan asumsi pada batas antarmuka, tetapi tidak menggantikan penanganan kesalahan bisnis, perilaku anggun (graceful) untuk input yang ambigu, atau pengujian lengkap. Mulailah dengan batasan lintas modul yang tidak dapat disimpulkan dengan mudah oleh pemanggil daripada mengekspos setiap detail implementasi.
2. Petakan batasan toolchain dan ABI
Buat daftar versi kompiler, pustaka standar, mode bahasa, linker, platform, dan konfigurasi build. Verifikasi penguraian (parsing), pembuatan kode, dukungan penanganan pelanggaran, dan informasi debug untuk masing-masing. Sintaksis baru dalam header publik dapat membuat kompiler lama langsung gagal; bahkan build yang berhasil pun dapat mendiagnosis secara berbeda dalam mode runtime yang berbeda. Gunakan deteksi kemampuan dan sampel minimal sebelum memilih batas build kondisional.
3. Pilih strategi penanganan pelanggaran
Penanganan pelanggaran harus sesuai dengan risiko layanan. Build pengembangan dapat berhenti dengan stack trace; build pengujian harus menggagalkan pengujian; build produksi dapat dihentikan secara aman, mengisolasi permintaan, atau mencatat dan melanjutkan tergantung pada tingkat keparahan kontrak. Melanjutkan proses tidak boleh menyembunyikan fakta bahwa status mungkin tidak tepercaya. Catatan harus berisi lokasi kontrak, ringkasan input, dan versi tanpa mengekspos data sensitif.
4. Evaluasi semantik dan efek samping
Ekspresi kontrak harus bebas efek samping, dapat diulang, dan independen dari urutan evaluasi yang tidak terdefinisi. Tim harus mengetahui apakah ekspresi dievaluasi dalam mode pemeriksaan yang diaktifkan, dinonaktifkan, atau alternatif dan apakah penanganan mengubah alur kontrol. Jangan menempatkan mutasi status, panggilan jaringan, atau ketergantungan waktu dalam kontrak; simpan perilaku tersebut dalam implementasi dan pengujian.
5. Rancang migrasi bertahap dan lapisan kompatibilitas
Mulailah dengan pustaka non-publik, fungsi murni, dan invarian bernilai tinggi pada satu kompiler dan target CI. API publik dapat menggunakan header berversi, build kondisional, atau makro agar armada lama tetap dapat mengompilasi, tetapi makro harus menangani perbedaan kemampuan alih-alih menyembunyikan semantik bisnis yang berbeda. Catat fungsi yang dicakup, matriks dukungan, dan pemanggil yang belum dimigrasikan untuk setiap ekspansi.
6. Gunakan bukti untuk memperluas atau melakukan rollback
Tetapkan baseline pra-migrasi untuk waktu build, ukuran biner, latensi jalur kritis, pelanggaran kontrak, crash, dan cacat pengujian. Selama canary, bandingkan lalu lintas dan distribusi input yang sama sebelum dan sesudah, memisahkan masalah input nyata, cacat kode, dan positif palsu dari toolchain. Jika pelanggaran terkonsentrasi pada jalur kritis, performa melebihi anggaran, atau target lama tidak dapat melakukan build secara andal, jeda migrasi, nonaktifkan jalur sintaksis baru, dan pulihkan artefak build sebelumnya.
Jawaban lengkap yang kuat
Saya akan menginventarisasi kompiler, pustaka standar, mode bahasa, platform, dan mode runtime serta memverifikasi penguraian C++26 Contracts dan penanganan pelanggaran untuk setiap target. Mulai dengan fungsi murni internal dan invarian eksplisit; gunakan kontrak sebagai dokumentasi antarmuka dan diagnostik, bukan sebagai pengganti pengecualian, degradasi anggun, atau pengujian. Biarkan build pengembangan dan pengujian gagal dengan cepat (fail fast), sementara produksi memilih penghentian aman, isolasi, atau pencatatan log berdasarkan risiko dan menjaga rahasia tetap berada di luar catatan. Pertahankan kompilasi armada lama dengan deteksi kemampuan dan build kondisional. Kendalikan canary berdasarkan keberhasilan build, latensi, perubahan biner, tingkat pelanggaran, dan crash, menjeda dan melakukan rollback pada setiap pelanggaran berisiko tinggi.
Pola kegagalan umum
- Memperlakukan Contracts sebagai pengganti lengkap untuk asersi, pengecualian, atau pengujian.
- Hanya mengatakan “tingkatkan ke C++26” tanpa matriks kompiler, pustaka standar, linker, dan ABI.
- Mengabaikan bagaimana mode pemeriksaan dan penanganan pelanggaran memengaruhi alur kontrol, performa, dan keselamatan online.
- Menempatkan operasi berefek samping dalam kontrak sehingga diagnostik mengubah perilaku program.
- Memperluas jangkauan setelah kompilasi berhasil tanpa baseline, canary, atau rollback.
Tindak lanjut dan ekstensi
Tindak lanjut 1: Haruskah pelanggaran kontrak melempar pengecualian?
Tidak ada jawaban universal. Pelanggaran berarti status program atau konvensi pemanggilan telah rusak. Pilih berdasarkan keterpulihan yang aman, apakah pengecualian melintasi batas ABI, dan kebijakan kesalahan tim. Untuk status yang tidak dapat dipulihkan, melanjutkan proses atau menggunakan pengecualian biasa dapat menyembunyikan kegagalan yang lebih besar.
Tindak lanjut 2: Bagaimana Anda mendukung kompiler lama?
Pertama, konfirmasikan apakah header publik harus diurai oleh kompiler tersebut. Deteksi kemampuan, build kondisional, atau makro kompatibilitas dapat mengarahkan target lama melalui jalur kontrak yang dinonaktifkan, tetapi pertahankan pengujian dan dokumentasi yang setara sehingga semantik bisnis tidak menyimpang.
Tindak lanjut 3: Akankah kontrak memperlambat produksi?
Ukur daripada menebak. Bandingkan CPU, latensi, dan perubahan biner di seluruh mode pemeriksaan, tingkat pengoptimalan, dan distribusi input. Batasi pemeriksaan yang mahal pada pengembangan, pengujian, atau canary kecil sambil mempertahankan pemantauan berbiaya rendah untuk invarian kritis.
Tindak lanjut 4: Bagaimana Anda mencegah penyalahgunaan kontrak?
Tetapkan aturan: nyatakan hanya invarian yang dapat diverifikasi dan asumsi batas, larang efek samping, dokumentasikan penanganan pelanggaran dan data sensitif, serta tinjau dalam code review. Setiap kontrak memerlukan pengujian, pemilik (owner), dan kondisi untuk penghapusan atau revisi.