Tiga halaman mengirim field yang sama dengan cara berbeda. Ada yang mengirim angka, ada yang mengirim string kosong kalau nilainya tidak ada, ada juga yang membungkus angka jadi string. Kebiasaan ini bertahan bertahun-tahun, sampai penerimanya berubah jadi sistem yang tidak mau menebak.
Begitulah type chaos muncul. Tidak ada yang sengaja bikin, tapi bekasnya masih bisa dihitung di repo kami.
Dulu, PHP Memaklumi #
Dulu penerimanya adalah PHP, bahasa yang sangat pemaaf soal tipe data. Kirim "123", dibaca sebagai 123. Kirim "", dianggap kosong. Kirim null, seolah tidak terlihat. Selama bertahun-tahun, halaman-halaman itu tidak perlu memikirkan tipe karena bahasanya tidak mempermasalahkannya.
Tiap halaman mengirim dengan gayanya sendiri, backend menerima saja, dan hidup terasa sederhana. Baru belakangan saya sadar, tenang-tenang saja bukan berarti sistemnya sehat. Penerimanya saja yang tidak pernah protes.
Lalu Go Datang #
Lalu backend-nya pindah ke Go. Pandangannya soal tipe berbeda: tipe adalah kontrak. Kalau kontraknya meminta angka, yang dikirim harus angka. String kosong yang mengaku angka ditolak di pintu, lengkap dengan error decoding yang panjang dan sama sekali tidak lucu.
Go tidak menciptakan chaos; ia hanya berhenti memaafkannya. Tiga kebiasaan yang sebelumnya tidak bermasalah berubah menjadi pelanggaran:
- Ada nilainya? Kirim angka. Tidak ada nilainya? Kirim string kosong.1
- Halaman lain untuk fungsi serupa mengirim string, dari sananya.
- Dan tidak ada dua halaman yang pernah duduk bareng menyepakati hal itu.
Tidak ada penjahatnya. Setiap halaman konsisten dengan caranya sendiri. Chaos ini muncul pelan-pelan selama bertahun-tahun, bukan karena ada yang sengaja membuatnya.
Bekasnya Ternyata Bisa Dihitung #
Yang paling menarik, chaos ini bukan cuma bisa diceritakan. Jumlahnya juga bisa dihitung.
Saat menyisir repo baru, saya menemukan hampir dua ratus pemanggilan String() di berbagai halaman, ditambah lebih dari dua puluh Number().2 Sebagian memang punya kegunaan sendiri. Sebagian lain adalah bekas luka dari era chaos: jaring pengaman agar nilai dengan tipe yang tidak pasti tetap bisa diproses.
Jaring pengaman itu bukan kesalahan. Mereka membantu transisi tetap berjalan. Tapi jumlahnya juga jadi petunjuk: kalau tipe data bisa dipercaya, mestinya tidak ada begitu banyak tempat yang harus menebak.
Biar Kontraknya Jelas #
Solusi jangka panjangnya bukan menambah jaring pengaman ke-400. Pertanyaannya perlu diubah: bukan lagi “nilai ini bentuknya apa hari ini?”, melainkan “kontraknya bilang apa?”
Satu field punya satu tipe yang dijanjikan, lalu semua halaman yang mengirimnya mengikuti kontrak itu. String kosong yang mengaku angka bisa ditolak lebih awal, di tempat yang dapat menjelaskan masalahnya. Daftar kontrak yang sederhana dan tertulis itu mungkin bisa mengakhiri perdebatan yang selama ini dibiarkan frontend.
Yang Saya Catat #
Saya jadi ingat: bahasa yang memaklumi tipe bisa menyembunyikan utang sampai penerimanya berubah. Tiap halaman mungkin terasa benar sendiri, tapi sistem keseluruhannya belum tentu rapi. Menurut saya, kontraknya perlu ditulis jelas dan normalisasi dilakukan di satu pintu. Jaring pengaman yang tersebar itu membantu, tapi bukan tujuan akhir.
Hampir dua ratus pemanggilan konversi tadi tidak semuanya masalah. Tapi cukup banyak yang memberi petunjuk bahwa tipe datanya belum bisa dipercaya. Di episode berikutnya, saya bahas warisan yang lebih kelihatan: dua library UI dan dua era penamaan dalam satu aplikasi.