Prinsip Joel Spolsky tetap relevan meski AI menulis kode cepat. Pelajari cara menjaga pengujian, perekrutan, dan kesederhanaan fokus pada ketepatan.

AI bisa menghasilkan kode yang tampak berfungsi dalam hitungan menit. Itu mengubah kecepatan proyek, tapi bukan hal yang membuat perangkat lunak berhasil. Pelajaran dari “software truths” Joel Spolsky bukan soal kecepatan mengetik. Mereka tentang penilaian, loop umpan balik, dan menghindari kompleksitas yang dibuat sendiri.
Yang berubah adalah biaya membuat kode. Anda bisa meminta tiga pendekatan, lima variasi, atau penulisan ulang penuh dan mendapatkan sesuatu secara instan. Yang tidak berubah adalah biaya memilih pendekatan yang tepat, memeriksanya, dan hidup dengan keputusan itu selama berbulan-bulan. Waktu yang dihemat untuk menulis sering bergeser ke memutuskan apa yang Anda maksud, memvalidasi kasus tepi, dan memastikan kemenangan cepat hari ini tidak menjadi pajak pemeliharaan besok.
Ketepatan, keamanan, dan keterpeliharaan masih memakan waktu nyata karena mereka bergantung pada bukti, bukan keyakinan. Alur login tidak selesai saat kode dikompilasi. Selesai berarti ketika ia menolak input buruk secara andal, menangani status aneh, dan tidak membocorkan data. AI bisa terdengar pasti namun melewatkan satu detail krusial, seperti pemeriksaan izin pada sebuah endpoint atau kondisi race pada pembaruan pembayaran.
AI paling kuat ketika Anda memperlakukannya seperti mesin draf cepat. Ia bersinar pada boilerplate, pola berulang, refaktor cepat, dan mengeksplorasi opsi yang bisa Anda bandingkan berdampingan. Jika digunakan dengan baik, ia memendekkan fase “halaman kosong”.
AI paling berbahaya saat Anda memberinya tujuan samar dan menerima keluarannya begitu saja. Pola kegagalan yang sama muncul berulang: asumsi tersembunyi (aturan bisnis yang tidak disebutkan), jalur yang tidak diuji (penanganan error, retry, kondisi kosong), kesalahan percaya diri (kode yang masuk akal tapi salah secara halus), dan solusi “cerdas” yang susah dijelaskan nanti.
Jika kode murah, sumber daya langka yang baru adalah kepercayaan. Prinsip-prinsip ini penting karena mereka melindungi kepercayaan itu: pada pengguna, rekan setim, dan diri Anda di masa depan.
Saat AI bisa menghasilkan fitur dalam hitungan menit, tergoda untuk menganggap pengujian sebagai bagian lambat yang harus dieliminasi. Poin Spolsky tetap berlaku: bagian yang lambat adalah tempat kebenaran berada. Kode mudah dihasilkan. Perilaku yang benar tidak.
Perubahan yang berguna adalah memperlakukan tes sebagai persyaratan yang bisa Anda jalankan. Jika Anda tidak bisa mendeskripsikan perilaku yang diharapkan secara dapat diperiksa, berarti Anda belum selesai berpikir. Dalam pekerjaan dibantu AI, ini menjadi lebih penting, bukan kurang, karena model bisa dengan percaya diri menghasilkan sesuatu yang hanya sedikit salah.
Mulailah pengujian dengan hal yang akan paling menyakitkan jika rusak. Untuk kebanyakan produk, itu adalah alur inti (daftar, checkout, simpan, ekspor), izin (siapa yang bisa melihat, mengedit, menghapus), dan integritas data (tidak ada duplikat, total yang benar, migrasi aman). Kemudian tutupi tepi yang cenderung menyebabkan insiden larut malam: input kosong, teks panjang, zona waktu, retry, dan batas eksternal yang fluktuatif seperti pembayaran, email, dan unggahan berkas.
AI hebat dalam mengusulkan kasus uji, tetapi ia tidak tahu apa yang sebenarnya Anda janjikan kepada pengguna. Gunakan seperti rekan brainstorming: minta kasus tepi yang terlewat, skenario penyalahgunaan, dan kombinasi izin. Lalu lakukan pekerjaan manusia: cocokkan cakupan ke aturan nyata Anda dan hapus tes yang hanya “menguji implementasi” alih-alih perilaku.
Buat kegagalan bisa ditindaklanjuti. Tes yang gagal harus memberi tahu apa yang rusak, bukan mengirim Anda berburu. Jaga tes kecil, beri nama seperti kalimat, dan buat pesan error spesifik.
Bayangkan Anda membangun aplikasi “catatan tim” sederhana dengan bantuan AI. Layar CRUD muncul cepat. Risiko ketepatan bukan pada UI. Itu pada kontrol akses dan aturan data: seorang pengguna tidak boleh melihat catatan tim lain, edit tidak boleh menimpa perubahan yang lebih baru, dan menghapus catatan tidak boleh meninggalkan lampiran yatim. Tes yang mengunci aturan ini akan terasa seperti hambatan, tetapi mereka juga jaring pengaman Anda.
Ketika pengujian menjadi hambatan, itu memaksa kejelasan. Kejelasan itulah yang menjaga agar kode cepat tidak menjadi bug cepat.
Salah satu kebenaran paling tahan lama adalah kode sederhana menang atas kode cerdas. AI membuat tergoda menerima abstraksi mewah karena mereka datang tampak rapi dan cepat. Biaya muncul nanti: lebih banyak tempat untuk menyembunyikan bug, lebih banyak berkas untuk dipindai, dan lebih banyak momen “apa ini sebenarnya melakukan apa?”.
Saat kode murah, kompleksitaslah yang Anda bayar. Desain kecil dan membosankan lebih mudah diuji, lebih mudah diubah, dan lebih mudah dijelaskan. Itu semakin penting ketika draf pertama berasal dari model yang bisa terdengar pasti padahal salah secara halus.
Aturan praktis: jaga fungsi, komponen, dan modul cukup kecil sehingga seorang rekan tim bisa meninjaunya dalam hitungan menit, bukan jam. Jika sebuah komponen React membutuhkan banyak custom hook, mesin status lokal, dan lapisan “smart renderer” generik, berhenti dan tanyakan apakah Anda sedang memecahkan masalah nyata atau hanya menerima arsitektur karena AI menawarkannya.
Beberapa “tes kesederhanaan” membantu Anda menolak:
Prompt penting di sini. Jika Anda meminta “arsitektur terbaik,” Anda sering mendapat yang berlebih. Minta batasan yang mendorong ke arah lebih sedikit bagian bergerak. Contoh: gunakan pendekatan paling sederhana dengan jumlah berkas paling sedikit; hindari abstraksi baru kecuali menghilangkan duplikasi di tiga atau lebih tempat; utamakan kode eksplisit daripada helper generik.
Contoh konkret: Anda meminta AI menambahkan akses berbasis peran ke halaman admin. Versi cerdas memperkenalkan kerangka izin, decorator, dan DSL konfigurasi. Versi sederhana memeriksa peran pengguna di satu tempat, mengatur rute di satu tempat, dan mencatat akses yang ditolak. Versi sederhana lebih mudah ditinjau, lebih mudah diuji, dan lebih sulit disalahartikan.
Jika Anda membangun di alat berbasis chat seperti Koder.ai, kesederhanaan juga membuat snapshot dan rollback lebih bernilai. Perubahan kecil dan jelas lebih mudah dibandingkan, disimpan, atau dikembalikan.
Ketika kode mudah dihasilkan, keterampilan langka adalah memilih apa yang seharusnya ada dan memastikan itu benar. Nasihat lama “pekerjakan programmer hebat” masih berlaku, tapi peran bergeser. Anda tidak merekrut seseorang untuk mengetik lebih cepat. Anda merekrut seseorang untuk menilai, menyempurnakan, dan membela produk.
Orang yang paling berharga dalam pengembangan dibantu AI cenderung berbagi empat sifat: penilaian (apa yang penting), selera (apa yang baik), keterampilan debugging (menemukan penyebab sejati), dan komunikasi (menjelaskan tradeoff dengan jelas). Mereka bisa mengambil fitur yang ditulis AI yang “hampir bekerja” dan mengubahnya menjadi sesuatu yang dapat Anda percaya.
Alih-alih meminta solusi sempurna dari awal, berikan kandidat pull request yang dihasilkan AI (atau diff yang ditempel) dengan beberapa masalah realistis: penamaan tidak jelas, kasus tepi tersembunyi, tes yang hilang, dan kesalahan keamanan kecil.
Minta mereka menjelaskan apa yang coba dilakukan kode dengan bahasa sederhana, menemukan bagian risiko tertinggi, mengusulkan perbaikan, dan menambahkan (atau menguraikan) tes yang akan menangkap regresi. Jika Anda ingin sinyal kuat, tanyakan juga bagaimana mereka akan mengubah instruksi agar upaya AI berikutnya lebih baik.
Ini memperlihatkan bagaimana mereka berpikir dalam kondisi nyata: kode tidak sempurna, waktu terbatas, dan kebutuhan memilih prioritas.
AI sering terdengar yakin. Kandidat yang baik nyaman menolak. Mereka bisa berkata tidak pada fitur yang menambah kompleksitas, tidak pada perubahan yang melemahkan keamanan, dan tidak pada pengiriman tanpa bukti.
Sinyal konkret adalah bagaimana mereka merespons “Apakah Anda akan menggabungkan ini?” Kandidat kuat tidak menjawab berdasarkan perasaan. Mereka memberi keputusan dan daftar singkat perubahan yang diperlukan.
Contoh: Anda diminta pembaruan kontrol-akses “cepat” dan AI menyarankan menyebarkan pemeriksaan di banyak handler. Kandidat kuat menolak pendekatan itu dan mengusulkan satu lapisan otorisasi yang jelas, plus tes untuk jalur admin dan non-admin.
Terakhir, bangun standar bersama sehingga tim mengedit keluaran AI dengan cara yang sama. Jaga sederhana: satu definisi selesai, ekspektasi review konsisten, dan baseline pengujian.
Saat AI bisa menghasilkan banyak kode dalam hitungan menit, tergoda untuk melewatkan pemikiran dan hanya iterasi. Itu bekerja untuk demo. Itu runtuh ketika Anda butuh ketepatan, perilaku yang dapat diprediksi, dan lebih sedikit kejutan.
Prompt yang baik biasanya adalah spes singkat terselubung. Sebelum meminta kode, ubah tujuan samar menjadi beberapa kriteria penerimaan dan non-goal eksplisit. Ini mencegah AI (dan tim Anda) memperluas ruang lingkup diam-diam.
Jaga spes kecil tapi spesifik. Anda tidak menulis novel. Anda menetapkan batas di sekitar:
Tentukan “selesai” sebelum generasi, bukan setelah. “Selesai” harus lebih dari sekadar “kompilasi” atau “UI terlihat benar.” Sertakan ekspektasi tes, kompatibilitas mundur, dan apa yang dipantau setelah rilis.
Contoh: Anda ingin “menambah reset kata sandi.” Spes yang lebih jelas mungkin berkata: pengguna meminta reset lewat email; tautan kadaluarsa dalam 15 menit; pesan yang sama muncul apakah email ada atau tidak; rate limit per IP; catat percobaan reset tanpa menyimpan token dalam teks biasa. Non-goal: tidak ada redesain halaman login. Sekarang prompt Anda punya pagar pengaman dan review menjadi lebih sederhana.
Simpan log perubahan ringan dari keputusan. Satu paragraf per keputusan cukup. Catat mengapa Anda memilih pendekatan dan mengapa menolak alternatif. Ketika seseorang bertanya “kenapa seperti ini?” dua minggu kemudian, Anda akan punya jawabannya.
Perubahan terbesar dengan AI adalah menghasilkan kode menjadi mudah. Bagian sulit adalah memutuskan apa yang harus dilakukan kode dan membuktikan bahwa itu memang melakukannya.
Mulailah dengan menulis tujuan dan batasan dalam bahasa biasa. Sertakan apa yang tidak boleh pernah terjadi, apa yang boleh lambat, dan apa yang di luar ruang lingkup. Batasan yang baik bersifat dapat diuji: “Tidak ada pengguna yang boleh melihat data pengguna lain,” atau “Total harus sesuai dengan ekspor keuangan sampai sen.”
Sebelum meminta kode, minta desain sederhana dan tradeoff-nya. Anda ingin AI menunjukkan alur pikirnya dalam bentuk yang bisa Anda nilai: apa yang akan disimpan, apa yang akan divalidasi, dan apa yang akan dicatat. Jika ia mengusulkan sesuatu yang cerdas, tolak dan minta versi paling sederhana yang tetap memenuhi batasan.
Loop berulang yang bisa diikuti:
Contoh kecil: Anda menambahkan “status refund” ke layar order. AI bisa menghasilkan UI dengan cepat, tetapi ketepatan berada pada kasus tepi. Bagaimana jika refund bersifat parsial? Bagaimana jika provider pembayaran mengulang webhook? Tulis kasus-kasus itu dulu, lalu implementasikan satu bagian (kolom DB plus validasi) dan verifikasi dengan tes sebelum melanjutkan.
Jika Anda menggunakan Koder.ai, fitur seperti mode perencanaan, snapshot, dan rollback cocok dalam loop ini: rencanakan dulu, hasilkan potongan, dan tangkap titik pemulihan untuk setiap perubahan bermakna.
Ketika generasi kode cepat, mudah menganggap kode sebagai produk kerja. Bukan itu. Produk kerja adalah perilaku: aplikasi melakukan hal yang benar, bahkan ketika hal buruk terjadi.
AI sering terdengar pasti, meski ia menebak. Kesalahan adalah melewatkan bagian membosankan: menjalankan tes, memeriksa kasus tepi, dan memvalidasi input nyata.
Kebiasaan sederhana membantu: sebelum menerima perubahan, tanyakan “Bagaimana kita tahu ini benar?” Jika jawabnya “terlihat benar,” Anda sedang berjudi.
AI suka menambahkan ekstra: caching, retry, lebih banyak setting, lebih banyak endpoint, UI yang lebih bagus. Beberapa ide itu baik, tapi mereka menaikkan risiko. Banyak bug datang dari fitur “bagus untuk dimiliki” yang tidak diminta siapa pun.
Jaga batas keras: selesaikan masalah yang Anda tetapkan, lalu berhenti. Jika saran berharga, tangkap sebagai tugas terpisah dengan tesnya sendiri.
Commit besar yang dihasilkan AI bisa menyembunyikan selusin keputusan yang tidak terkait. Review menjadi sekadar menyetujui karena tak seorang pun bisa memegang semuanya di kepala.
Perlakukan output chat sebagai draf. Pecah menjadi perubahan kecil yang bisa dibaca, dijalankan, dan dibatalkan. Snapshot dan rollback hanya berguna jika Anda mengambilnya pada titik yang masuk akal.
Beberapa batas sederhana mencegah sebagian besar masalah: satu fitur per change set, satu migrasi per change set, satu area berisiko tinggi pada satu waktu (auth, pembayaran, penghapusan data), tes diperbarui dalam perubahan yang sama, dan catatan “cara verifikasi” yang jelas.
AI bisa mereproduksi pola dari data latihnya atau menyarankan dependency yang tidak Anda mengerti. Bahkan jika lisensi tidak masalah, risiko lebih besar adalah keamanan: secret ter-hardcode, penanganan token lemah, atau operasi file/query yang tidak aman.
Jika Anda tidak bisa menjelaskan apa yang dilakukan potongan kode, jangan kirimkan. Minta versi yang lebih sederhana, atau tulis ulang sendiri.
Banyak bug "berhasil di mesin saya" sebenarnya adalah bug data dan skala. AI bisa membuat perubahan skema tanpa memikirkan baris yang ada, tabel besar, atau downtime.
Contoh realistis: model menambahkan kolom NOT NULL baru ke tabel PostgreSQL dan melakukan backfill lewat loop lambat. Di produksi, itu bisa mengunci tabel dan merusak aplikasi. Selalu pertimbangkan apa yang terjadi pada satu juta baris, jaringan lambat, atau deploy gagal di tengah jalan.
Bayangkan tracker permintaan internal kecil: orang mengirim permintaan, manajer menyetujui atau menolak, dan bagian keuangan menandai item sebagai dibayar. Terlihat sederhana, dan dengan bantuan AI Anda bisa menghasilkan layar dan endpoint dengan cepat. Bagian yang memperlambat Anda tetap kebenaran: aturan, bukan pengetikan.
Mulailah dengan menulis minimum yang harus benar. Jika Anda tidak bisa menjelaskannya dengan kata-kata sederhana, Anda tidak bisa mengujinya.
Definisi versi-pertama yang ketat sering terlihat seperti ini: field (title, requester, department, amount, reason, status, timestamps); peran (requester, approver, finance, admin); status (draft, submitted, approved, rejected, paid). Lalu nyatakan transisi yang penting: hanya approver yang bisa memindahkan submitted ke approved atau rejected; hanya finance yang bisa memindahkan approved ke paid.
Gunakan AI dalam urutan terkontrol sehingga Anda bisa menangkap kesalahan lebih awal:
submit, approve, reject, pay), bukan rute update-generic.Tes bernilai tertinggi bukanlah “apakah halaman dimuat.” Mereka adalah pemeriksaan izin dan transisi status. Buktikan, misalnya, bahwa requester tidak bisa menyetujui permintaan mereka sendiri, approver tidak bisa menandai sesuatu sebagai dibayar, permintaan yang ditolak tidak bisa dibayar, dan (jika aturan Anda demikian) jumlah tidak bisa diubah setelah pengajuan.
Yang paling memakan waktu adalah memperjelas kasus tepi. Bisakah approver mengubah pikirannya setelah menolak? Bagaimana jika dua approver menekan approve pada saat bersamaan? Bagaimana jika finance perlu membayar parsial? AI bisa menghasilkan kode untuk jawaban apa pun yang Anda pilih, tetapi ia tidak bisa memilih jawaban untuk Anda. Ketepatan datang dari membuat keputusan itu, lalu memaksa kode mematuhinya.
AI bisa menghasilkan banyak kode cepat, tapi jarak akhir masih pekerjaan manusia: membuktikan ia melakukan apa yang Anda maksud, dan gagal dengan aman ketika tidak.
Sebelum Anda mulai mencentang kotak, pilih definisi “selesai” terkecil yang penting. Untuk fitur kecil, itu bisa satu happy path, dua failure path, dan pengecekan keterbacaan singkat. Untuk pembayaran atau auth, naikkan standar.
Misal AI menambahkan “undang massal pengguna” ke layar admin. Happy path bekerja, tapi risiko nyata adalah kasus tepi: email duplikat, kegagalan parsial, dan batas laju. Keputusan kirim yang solid mungkin satu tes otomatis untuk duplikat, satu pengecekan manual untuk pesan kegagalan parsial, dan rencana rollback.
Ketika kode murah, risiko bergeser ke kualitas keputusan: apa yang Anda minta, apa yang Anda terima, dan apa yang Anda kirimkan. Cara tercepat membuat prinsip-prinsip ini efektif dalam kerja dibantu AI adalah menambahkan guardrail yang mencegah perubahan “hampir benar” lolos.
Mulailah dengan spes satu halaman untuk fitur berikutnya. Buat sederhana: siapa penerima, apa yang dilakukan, apa yang tidak dilakukan, dan beberapa tes penerimaan ditulis dalam bahasa sehari-hari. Tes penerimaan itu menjadi jangkar ketika AI menyarankan jalan pintas menggoda.
Set guardrail yang bisa skala tanpa overhead proses besar:
Prompt kini bagian dari proses Anda. Sepakati gaya rumah: library yang diizinkan, bagaimana error ditangani, apa arti “selesai,” dan tes apa yang harus lulus. Jika sebuah prompt tidak bisa dipakai ulang oleh rekan lain, kemungkinan terlalu samar.
Jika Anda lebih suka cara pembangunan berbasis chat untuk web, backend, dan mobile, Koder.ai (koder.ai) adalah satu contoh platform vibe-coding di mana mode perencanaan, snapshot, dan ekspor kode sumber bisa mendukung guardrail ini. Alat itu dapat mempercepat draf, tetapi disiplinlah yang menjaga manusia tetap memegang kendali atas ketepatan.
Perlakukan keluaran AI seperti draf cepat, bukan fitur selesai. Mulailah dengan menulis 3–5 pemeriksaan penerimaan yang bisa lulus/gagal, lalu hasilkan satu potongan kecil (satu endpoint, satu layar, satu migrasi) dan verifikasi dengan tes serta pengujian kasus kegagalan sebelum melanjutkan.
Karena pengujian adalah tempat Anda menemukan apa yang sebenarnya dilakukan kode. AI bisa menghasilkan logika yang masuk akal tetapi melewatkan satu aturan penting (hak akses, pengulangan, kondisi tepi). Tes mengubah harapan Anda menjadi sesuatu yang bisa dijalankan, diulang, dan dipercaya.
Mulailah dengan hal yang paling merugikan jika rusak:
Tambahkan cakupan lebih setelah perilaku berisiko tinggi terkunci.
Minta pendekatan paling sederhana dengan batasan eksplisit, lalu hapus lapisan tambahan kecuali mereka benar-benar berfaedah. Aturan praktis: jangan perkenalkan abstraksi baru kecuali menghilangkan duplikasi di 3+ tempat atau membuat kebenaran lebih mudah dibuktikan.
Tulis spesifikasi singkat: masukan, keluaran, kesalahan, batasan, dan non-goal. Sertakan contoh konkret (request/response sampel, kasus tepi). Lalu definisikan “selesai” di muka: tes yang dibutuhkan, ekspektasi kompatibilitas mundur, dan catatan singkat “cara verifikasi.”
Pecah menjadi bagian-bagian kecil yang bisa direview dalam hitungan menit:
Ini membuat review menjadi nyata alih-alih sekadar menyetujui tanpa membaca.
Jangan percaya sekadar nada yakin—percaya bukti. Jalankan tes, coba input yang salah-bentuk, dan verifikasi batasan hak akses. Perhatikan juga jebakan umum AI: pemeriksaan auth yang hilang, pembuatan query yang tidak aman, penanganan token yang lemah, dan menelan error secara diam-diam.
Lebih baik gunakan endpoint transisi eksplisit daripada rute umum “update apapun”. Misalnya: submit, approve, reject, pay daripada rute update generik. Lalu tulis tes yang menegakkan siapa yang boleh melakukan setiap transisi dan transisi mana yang dilarang.
Berikan kandidat sebuah diff yang dihasilkan AI dengan masalah nyata: penamaan yang tidak jelas, tes yang hilang, kasus tepi, dan satu kesalahan keamanan kecil. Minta mereka menjelaskan maksud kode, menemukan bagian risiko tertinggi, mengusulkan perbaikan, dan merinci tes yang akan mereka tambahkan.
Gunakan fitur alat untuk mendukung loop disiplin: rencanakan dulu, hasilkan dalam potongan kecil, snapshot sebelum perubahan berisiko, dan rollback jika validasi gagal. Dalam alat berbasis chat seperti Koder.ai, ini cocok dengan mode perencanaan, snapshot, dan rollback—terutama untuk area yang menyentuh auth, pembayaran, atau migrasi.