Hijrah Frontend (3): Type Chaos, Angka, String Kosong, dan Halaman yang Berbeda Pendapat



Ada satu field yang sama, dikirim oleh tiga halaman berbeda, dengan tiga keyakinan berbeda tentang apa dia itu. Halaman pertama mengirim angka. Halaman kedua, kalau kosong, mengirim string kosong. Halaman ketiga mengirim angka tapi dibungkus string. Ketiganya hidup damai bertahun-tahun, sampai satu hari penerimanya berganti menjadi sistem yang menolak menebak hehe~

Episode ini tentang type chaos: bagaimana ia lahir tanpa niat siapa pun, kenapa ia bertahan bertahun-tahun, dan bekas lukanya yang sampai hari ini masih terukur di repo kami.

Dunia yang Memafkan #

Dulu, penerima cerita ini adalah PHP. Dan PHP, bagi tipe data, adalah teman paling pemaaf yang pernah ada. Kirim "123", dia baca 123. Kirim "", dia baca kosong. Kirim null, dia pura-pura tidak melihat. Selama bertahun-tahun, tidak ada satu halaman pun yang merasa perlu memikirkan tipe, karena bahasanya tidak pernah mempermasalahkannya.

Dunia ini berjalan damai. Semua halaman mengirim dengan gayanya masing-masing, backend menerima dengan senyum, dan hidup terasa sederhana. Yang tidak kami sadari: damai itu bukan karena sistemnya sehat, tapi karena saksi utamanya tidak pernah bersaksi hehe~

Tetangga Baru yang Perfeksionis #

Lalu backend-nya pindah ke Go, dan Go punya pandangan yang sangat berbeda tentang tipe: tipe adalah kontrak. Kalau kontraknya bilang angka, yang datang harus angka; string kosong yang mengaku angka akan ditolak di pintu, dengan error decoding yang panjang dan sama sekali tidak lucu.

Di sinilah chaos itu baru tampak bentuknya. Bukan karena Go menciptakan chaos; Go cuma berhenti memafkannya. Tiga keyakinan yang selama ini hidup damai tiba-tiba jadi tiga pelanggaran:

  1. Ada nilainya? Kirim angka. Tidak ada nilainya? Kirim string kosong.1
  2. Halaman lain untuk fungsi serupa mengirim string, dari sananya.
  3. Dan tidak ada dua halaman yang pernah duduk bareng menyepakati hal itu.

Tidak ada penjahat di cerita ini. Setiap halaman konsisten dengan dirinya sendiri, sepanjang umurnya. Chaosnya itu emergent: ia lahir dari bertahun-tahun kebebasan, bukan dari kejahatan siapa pun hahaha.

Bekas Luka yang Terukur #

Bagian favorit saya dari episode ini: chaosnya tidak cuma bisa diceritakan, dia bisa dihitung.

Saat saya menyapu repo baru, satu pola terlihat jelas: hampir dua ratus pemanggilan String() tersebar di halaman-halaman, plus dua puluh lebih Number().2 Sebagian memang tugas resminya; sebagian lagi adalah bekas luka dari era chaos: jaring pengaman kecil yang dipasang supaya nilai yang tak tentu tipenya tetap bisa diproses.

Dua ratus jaring pengaman itu tidak salah; malah mereka pahlawan sunyi yang membuat transisi tetap jalan. Tapi kehadiran mereka adalah pengukuran paling jujur tentang masalahnya: kalau tipe data sudah dipercaya, tidak akan ada dua ratus titik yang merasa perlu menebak-nebak hehe~

Kontrak, Bukan Tebak-Tebakan #

Solusi jangka panjangnya bukan menambah jaring pengaman ke-400. Solusinya adalah mengubah pertanyaannya: dari “nilai ini bentuknya apa hari ini?” menjadi “kontraknya bilang apa?”

Satu field, satu tipe yang dijanjikan, dipatuhi semua halaman yang mengirimnya. String kosong yang mengaku angka tidak lagi ditolak di ujung dengan error; dia ditolak lebih awal, di tempat yang bisa menjelaskan dengan sopan. Dan daftar kontrak itu menjadi dokumen paling berguna yang pernah diabaikan frontend bertahun-tahun: sederhana, tertulis, dan menghabiskan semua perdebatan hahaha.

Pelajaran #

  1. Bahasa yang memafkan menyembunyikan hutang tipe. Ia bukan menyelesaikan masalah; ia menundukkannya sampai penerima berganti.
  2. Chaos itu emergent, bukan disengaja. Setiap halaman benar secara lokal; hanya sistem keseluruhan yang salah.
  3. Penerima yang strict itu berkah, meski terasa seperti pengganggu. Dia memaksa kontrak yang seharusnya sudah ada sejak awal.
  4. Normalisasi di satu pintu, jangan disebarkan. Dua ratus jaring pengaman tersebar itu bukan arsitektur; itu angsuran.

Episode berikutnya kita naik ke lapisan yang lebih terlihat: dua library UI yang hidup berdampingan di satu aplikasi, dan penamaan yang berganti setiap pergantian tukang. Sampai ketemu di sana.

Sekian. Salam.


  1. Detail endpoint, nama field, dan bentuk error disederhanakan; yang dipertahankan hanya bentuk masalahnya. ↩︎

  2. Pola dan angka dihitung langsung dari repo saat episode ini ditulis; tidak semua pemanggilan konversi adalah bekas luka, dan tidak semua bekas luka tercatat. ↩︎