Ada satu momen dalam hidup sebuah script kecil yang selalu berulang: hari pertama dia menerima file yang bukan kamu bikin sendiri. Selama yang menyusun .csv-nya kamu, semuanya mulus. Begitu file datang dari tim lain, telepon mulai berdering.
Script-nya sederhana, kok. Dia membaca file .csv berisi daftar pendaftar dengan tiga kolom — nama, email, umur — lalu menyimpan baris yang valid. Satu file masuk, satu laporan keluar, selesai. Kecuali saat ada satu baris yang isinya jelek.
Di situ yang muncul bukan penjelasan, melainkan laporan setinggi setengah layar. Judulnya Traceback (most recent call last):, disusul daftar path file, nomor baris di impor.py, nama fungsi, dan di baris paling bawah satu kalimat seperti ValueError: invalid literal for int() with base 10: 'dua puluh'. Semuanya benar. Nggak ada satu pun yang berguna buat orang yang mengirim file itu.
Poin Penting
- Satu pesan error yang berguna menjawab tiga hal: di mana, apa yang salah, dan harusnya bagaimana.
- Script yang berhenti di masalah pertama cuma menjawab sepertiganya. Empat masalah di satu file, nol yang dilaporkan.
- File yang salah kadang malah diam.
kosong.csvmelaporkan3 baris diimpordengan kode keluar0, padahal ada baris tanpa nama. - Targetnya
make check: tujuh pemeriksaan, kondisi awal cuma 1 yang hijau.
Yang orang keluhkan
Di lab ini, make demo memerankan lima file contoh yang semuanya masuk ke script yang sama. Yang keluar dari tiap file belum seragam, dan justru itu masalah pertamanya. Tiga keluhan yang paling sering terdengar:
- Sebagian file bikin script mati mendadak. Yang dilaporkan cuma baris yang kebetulan tersandung lebih dulu. Baris bermasalah setelahnya nggak pernah disebut, seolah nggak ada.
- File lain malah diam total. Nggak ada keluhan apa pun, padahal di dalamnya jelas ada baris yang rusak. Script-nya malah mengucapkan terima kasih.
- Yang minta tolong mengeluh dengan kalimat yang sama: "aku nggak tahu baris berapa yang salah, kolom apa, dan harus ngapain." Stack trace-nya menyebut nama variabel Python —
baris,umur— bukan baris di dalam file mereka.
Kalau kamu pernah menulis validator atau importer kecil, tiga keluhan itu terasa akrab. Yang bikin capek bukan menulis validasinya, tapi menjelaskan hasilnya ke orang lain. Dan itu, ternyata, bagian dari pekerjaannya juga.
Angka yang sudah diukur
Nggak ada tebakan di sini. Semua baris di bawah keluar dari make demo dan make check, dijalankan pada kondisi awal lab, apa adanya:
| perintah | yang muncul sekarang |
|---|---|
make impor FILE=data/contoh/beberapa.csv |
ValueError: invalid literal for int() ... 'dua puluh' — 0 dari 4 masalah dilaporkan |
make impor FILE=data/contoh/kosong.csv |
nggak ada keluhan, dan bilang 3 baris diimpor, kode keluar 0 |
make impor FILE=data/contoh/kolom.csv |
IndexError: list index out of range — 0 dari 2 masalah dilaporkan |
make impor FILE=data/contoh/tidak-ada.csv |
FileNotFoundError, kode keluar 1 |
make check |
1 dari 7 pemeriksaan hijau (cuma A) |
Baris pertama itu yang paling menyakitkan. Di beberapa.csv ada empat masalah yang menunggu dilaporkan, tapi program berhenti di yang pertama dan melupakan sisanya. Baris ketiga sama polanya: kolom.csv punya dua baris dengan jumlah kolom yang meleset, dan dua-duanya nggak pernah kelihatan.
Baris kedua punya bentuk kegagalan yang berbeda, dan menurutku yang paling licin. kosong.csv berisi baris tanpa nama, tapi script-nya santai saja melaporkan 3 baris diimpor dengan kode keluar 0. Nggak ada yang merah, nggak ada yang kuning; dan kalau kamu nggak memeriksa file sumbernya baris demi baris, kamu nggak akan pernah tahu.
Bandingkan dengan baris terakhir. Di situ make check cuma menyalakan satu lampu hijau dari tujuh. Tujuh pemeriksaan itu tersimpan di scripts/check.py, dan alat itulah yang jadi juri lab ini.
Batas lab ini
Ada dua hal yang sengaja nggak dibahas di sini, dan keduanya penting biar kamu nggak salah ambil pelajaran.
Pertama, semua error yang diurus lab ini adalah data yang salah, bukan program yang salah. Kamu sedang memvalidasi masukan yang datang dari luar. Kalau yang salah adalah logika di kodemu sendiri (bug), itu cerita yang lain lagi. Kedua, ini program satu kali jalan, bukan layanan yang terus hidup. Di sini "di mana" artinya nomor baris di file; di sebuah layanan web, "di mana" bisa berarti field di body request. Konsepnya sama, tempatnya beda. Ini juga yang bikin kode keluar (exit code) penting: script seperti ini sering dipanggil dari cron, make, atau pipa shell, bukan ditemani orang yang menatap layarnya.
Ada juga satu batas yang praktis. Format laporan baris N: kolom — pesan cukup untuk file seukuran ini. Begitu filenya ratusan megabyte, melaporkan semua masalah sekaligus itu sendiri punya ongkos. Untuk sekarang, ukurannya masih sopan.
Misi kamu
Lab ini sengaja dibuat level pemula. Buat menjalankannya kamu nggak perlu Docker, nggak perlu database — cukup python3 yang sudah terpasang. Yang dilatih di sini bukan kecepatan atau concurrency, tapi satu hal yang kepakai di semua bahasa: membuat program yang salahnya bisa dibaca manusia.
Targetmu satu: bikin make check hijau, tujuh dari tujuh. Kamu bebas mengubah isi app/ sesukamu. Yang jangan diubah: scripts/check.py (itu penilainya), data/ (fixture-nya), dan Makefile.
Kalau nyangkut, ada HINTS.md dengan tiga tingkat petunjuk. Pakai urut, jangan langsung lompat ke yang ketiga. Dan jangan buka branch solusi sebelum kamu benar-benar mentok.
Satu pertanyaan sebelum kamu mulai
Sebelum menyentuh satu baris kode, ada satu hal yang perlu kamu putuskan dulu. Laporan itu sebenarnya untuk siapa, sih — mesin yang membaca kode, atau orang yang sedang panik karena pendaftarannya nggak masuk?
Pertanyaan itulah yang menentukan semua keputusan teknis setelahnya. Program yang cuma melaporkan masalah pertama yang dia temui sebenarnya baru menjawab sebagian kecil dari yang ditanyakan penggunanya. Sisa pertanyaannya, dan kenapa jawabannya sesederhana mengubah satu kebiasaan, ada di artikel jawabannya.
Kalau script-mu berhenti di baris jelek pertama, apa yang nggak akan pernah kamu lihat?