Topik ini memandu pembangunan alat command line kecil bernama pemeriksa-suhu melalui empat tahap yang saling bertambah. Alat tersebut membaca deret suhu harian dari argumen terminal, memvalidasi setiap angka, lalu melaporkan rata-rata, nilai minimum dan maksimum, serta posisi hari terdingin dan terpanas. Setiap tahap diakhiri satu titik pemeriksaan berupa odin check . yang harus lulus hening sebelum tahap berikutnya dimulai. Hasil akhirnya berupa berkas main.odin utuh yang sudah menangani kasus tepi berupa pemanggilan tanpa argumen dan argumen yang bukan angka.
Titik pemeriksaan dan tahap kecil#
Perintah odin check mengurai dan memeriksa tipe seluruh berkas dalam satu package tanpa menghasilkan binari, sehingga biaya waktunya nyaris nol pada proyek kecil. Karakteristik itu menjadikannya alat titik pemeriksaan yang ideal, yaitu dijalankan setiap kali satu tahap kecil selesai ditulis dan bukan sekali di akhir pekerjaan. Kegagalan pemeriksaan pada tahap kecil menunjuk sebagian kecil kode yang baru saja berubah, sedangkan kegagalan pada program yang ditulis sekaligus hanya memberi titik awal penelusuran yang samar.
Kebalikan rutinitas tersebut adalah menulis seluruh program lebih dahulu dan memeriksa semuanya di akhir. Satu kesalahan kecil di awal berkas menular ke banyak baris lain yang sebenarnya benar, sehingga daftar error harus diurai satu per satu untuk menemukan akarnya. Compiler juga tidak menampilkan daftar tanpa batas, karena pengujian pada build sandbox ini menunjukkan daftar berhenti pada 36 error dan sisanya terpotong. Flag -max-error-count:<n> mengatur batas tampilan tersebut secara eksplisit apabila daftar panjang memang perlu dibaca utuh.
Pola tahap kecil menjaga daftar itu tetap pendek secara alami. Setiap tahap pada topik ini hanya menambah satu kemampuan, sehingga apabila pemeriksaan gagal, entri yang muncul paling banyak berjumlah beberapa baris dan seluruhnya menunjuk kode yang baru ditambahkan. Rutinitas yang dipraktikkan di sisa topik selalu sama, yaitu tulis satu tahap, jalankan odin check ., lalu lanjutkan hanya setelah keluarannya hening.
Tahap 1: kerangka yang lulus hening#
Tahap pertama membuat folder proyek beserta berkas main.odin yang hanya berisi kerangka. Package bernama main bersama proc main merupakan gerbang masuk setiap program Odin, sehingga kerangka berikut sudah sah sebagai program walaupun tubuhnya masih kosong. Untuk proyek berupa satu folder, nama berkas di dalamnya bebas ditentukan, dan kebiasaan yang lazim adalah menamai berkas utamanya main.odin. Kerangka sekecil ini memberi pemeriksa sesuatu yang sah untuk dianalisis sejak lima menit pertama proyek, tanpa menunda pekerjaan sampai rancangan selesai.
// tidak-dijalankan
package main
main :: proc() {
}Simpan kerangka itu sebagai main.odin di dalam folder proyek, lalu jalankan titik pemeriksaan pertama.
# sumberkan lingkungan sandbox jalur odin bila belum tersedia
[ -f /home/kal/my-project/tools/env.sh ] && source /home/kal/my-project/tools/env.sh
# titik pemeriksaan tahap 1
odin check .Keluaran yang kosong memang hasil yang diharapkan. Perintah odin check menjawab dengan hening, yaitu tanpa satu baris keluaran pun, ketika analisis lulus, dan kebiasaan membaca keheningan sebagai kabar baik perlu dibangun sejak sekarang. Titik pemeriksaan pertama sekaligus memvalidasi lingkungan kerja, yaitu perintah odin yang tersedia pada PATH dan folder proyek yang benar. Apabila tahap sesederhana ini sudah gagal, penyebabnya hampir pasti berada di lingkungan dan bukan di kode, sehingga penelusurannya tidak memakan waktu.
Tahap 2: parsing argumen suhu#
Tahap kedua mengubah argumen terminal menjadi deret angka yang siap dihitung. Variabel os.args bertipe []string berisi seluruh argumen pemanggilan, dengan entri pertama berupa jalur program itu sendiri, sehingga data suhu diperoleh dari os.args[1:]. Konversi setiap string dilakukan oleh strconv.parse_f64 dari package core:strconv, dan tanda tangannya pada sumber lokal core/strconv terbaca parse_f64(str: string, n: ^int = nil) -> (value: f64, ok: bool). Proc tersebut mengembalikan nilai f64 beserta flag keberhasilan, sedangkan strconv.parse_int menjadi pilihan apabila datanya memang bulat. Tipe desimal dipilih di sini karena suhu lazim bernilai pecahan, misalnya 24.5.
Setiap argumen diperiksa satu per satu dalam perulangan for. Apabila flag ok bernilai false, program mencetak pesan error lalu berhenti melalui os.exit(1), sehingga angka karangan tidak pernah sempat masuk ke perhitungan. Nilai yang sah dikumpulkan ke dynamic array suhu yang dibuat dengan make, ditumbuhkan dengan append, dan dibebaskan melalui defer delete yang ditulis di dekat pembuatannya.
// tidak-dijalankan
package main
import "core:fmt"
import "core:os"
import "core:strconv"
main :: proc() {
// args[0] adalah nama program, sisanya adalah data suhu harian
suhu_args := os.args[1:]
suhu := make([dynamic]f64, 0, len(suhu_args))
defer delete(suhu)
for a in suhu_args {
nilai, ok := strconv.parse_f64(a)
if !ok {
fmt.printf("error: %q bukan angka\n", a)
os.exit(1)
}
append(&suhu, nilai)
}
fmt.printf("terbaca %v suhu\n", len(suhu))
}Titik pemeriksaan kedua kembali wajib hening sebelum perhitungan statistik ditulis.
# sumberkan lingkungan sandbox jalur odin bila belum tersedia
[ -f /home/kal/my-project/tools/env.sh ] && source /home/kal/my-project/tools/env.sh
# titik pemeriksaan tahap 2
odin check .Tahap ini menambah tiga import, satu perulangan, dan satu cabang error, sehingga kegagalan yang mungkin muncul semuanya berada di area yang baru ditulis. Apabila pemeriksaan gagal, misalnya karena nama proc salah ketik, daftar errornya berisi beberapa entri yang menunjuk baris parsing tersebut. Lingkup yang sesempit itu membuat perbaikan biasanya selesai sebelum satu menit berlalu.
Tahap 3: statistik dan pelaporan#
Tahap ketiga menambahkan perhitungan statistik di atas deret yang sudah sah. Total diakumulasi dalam perulangan pertama, sedangkan minimum, maksimum, beserta posisi harinya dicari dalam perulangan kedua yang memperbarui posisi hari dengan i + 1 setiap kali rekor baru ditemukan. Penambahan satu itu diperlukan karena indeks slice dimulai dari nol, sedangkan nomor hari pada laporan dimulai dari satu.
// tidak-dijalankan
package main
import "core:fmt"
import "core:os"
import "core:strconv"
main :: proc() {
// args[0] adalah nama program, sisanya adalah data suhu harian
suhu_args := os.args[1:]
suhu := make([dynamic]f64, 0, len(suhu_args))
defer delete(suhu)
for a in suhu_args {
nilai, ok := strconv.parse_f64(a)
if !ok {
fmt.printf("error: %q bukan angka\n", a)
os.exit(1)
}
append(&suhu, nilai)
}
total := 0.0
for s in suhu {
total += s
}
minimum, maksimum := suhu[0], suhu[0]
hari_terdingin, hari_terpanas := 1, 1
for i in 1 ..< len(suhu) {
if suhu[i] < minimum {
minimum = suhu[i]
hari_terdingin = i + 1
}
if suhu[i] > maksimum {
maksimum = suhu[i]
hari_terpanas = i + 1
}
}
fmt.printf("jumlah suhu : %v\n", len(suhu))
fmt.printf("rata-rata : %.2f °C\n", total / f64(len(suhu)))
fmt.printf("minimum : %.2f °C\n", minimum)
fmt.printf("maksimum : %.2f °C\n", maksimum)
fmt.printf("hari terdingin : %v\n", hari_terdingin)
fmt.printf("hari terpanas : %v\n", hari_terpanas)
}Pada tahap ini rutinitas bertambah satu langkah, yaitu eksekusi sungguhan setelah pemeriksaan tipe lulus. Jalankan program dengan deret suhu sepekan melalui pemisah --.
# sumberkan lingkungan sandbox jalur odin bila belum tersedia
[ -f /home/kal/my-project/tools/env.sh ] && source /home/kal/my-project/tools/env.sh
# periksa tipe lebih dahulu, lalu jalankan dengan data sepekan
odin check .
odin run . -- 24.5 26.0 23.0 21.5 27.5 28.0 20.5jumlah suhu : 7
rata-rata : 24.43 °C
minimum : 20.50 °C
maksimum : 28.00 °C
hari terdingin : 7
hari terpanas : 6Keluaran tersebut dapat dihitung ulang dengan mudah. Tujuh suhu berjumlah 171.0, sehingga rata-ratanya 171.0 dibagi 7 dan dibulatkan menjadi dua desimal oleh verb %.2f hingga terbaca 24.43. Angka 20.5 pada hari ketujuh menjadi minimum, sedangkan 28.0 pada hari keenam menjadi maksimum. Verb %v dipakai untuk bilangan bulat seperti jumlah data dan nomor hari karena mencetak nilai apa pun dalam bentuk bakunya. Perlu dicatat pula bahwa pemisah -- berarti seluruh argumen setelahnya ditujukan kepada program dan bukan kepada odin.
Tahap 4: kasus tepi di gerbang input#
Tahap terakhir menutup dua celah pada gerbang input. Celah pertama adalah pemanggilan tanpa argumen. Pada versi tahap tiga, pemanggilan semacam itu membuat perulangan parsing tidak pernah berjalan sehingga statistik dihitung atas deret kosong, lengkap dengan akses suhu[0] yang tidak sah. Gerbang len(os.args) < 2 menghentikan program lebih awal dengan pesan penggunaan beserta contoh pemanggilan. Celah kedua adalah argumen yang bukan angka, dan pesannya kini menyebutkan bentuk angka yang sah agar pemanggil mengetahui perbaikannya. Perlu diingat bahwa odin check tidak mengeksekusi program, sehingga celah semacam ini lolos dari pemeriksaan tipe dan baru terlihat ketika program dijalankan.
Berkas main.odin berikut merupakan keadaan akhir yang menggabungkan keempat tahap.
package main
import "core:fmt"
import "core:os"
import "core:strconv"
main :: proc() {
// args[0] adalah nama program, sisanya adalah data suhu harian
if len(os.args) < 2 {
fmt.println("Penggunaan: pemeriksa-suhu <suhu-1> <suhu-2> ...")
fmt.println("Contoh : pemeriksa-suhu 24.5 26.0 23.0")
os.exit(1)
}
suhu_args := os.args[1:]
suhu := make([dynamic]f64, 0, len(suhu_args))
defer delete(suhu)
for a in suhu_args {
nilai, ok := strconv.parse_f64(a)
if !ok {
fmt.printf("error: argumen %q bukan angka suhu yang sah, contoh: 23.5\n", a)
os.exit(1)
}
append(&suhu, nilai)
}
total := 0.0
for s in suhu {
total += s
}
minimum, maksimum := suhu[0], suhu[0]
hari_terdingin, hari_terpanas := 1, 1
for i in 1 ..< len(suhu) {
if suhu[i] < minimum {
minimum = suhu[i]
hari_terdingin = i + 1
}
if suhu[i] > maksimum {
maksimum = suhu[i]
hari_terpanas = i + 1
}
}
fmt.printf("jumlah suhu : %v\n", len(suhu))
fmt.printf("rata-rata : %.2f °C\n", total / f64(len(suhu)))
fmt.printf("minimum : %.2f °C\n", minimum)
fmt.printf("maksimum : %.2f °C\n", maksimum)
fmt.printf("hari terdingin : %v\n", hari_terdingin)
fmt.printf("hari terpanas : %v\n", hari_terpanas)
}Dua pemanggilan berikut menguji kedua gerbang secara bergantian.
# sumberkan lingkungan sandbox jalur odin bila belum tersedia
[ -f /home/kal/my-project/tools/env.sh ] && source /home/kal/my-project/tools/env.sh
# pemanggilan tanpa argumen: gerbang penggunaan terpicu
odin run .Penggunaan: pemeriksa-suhu <suhu-1> <suhu-2> ...
Contoh : pemeriksa-suhu 24.5 26.0 23.0# sumberkan lingkungan sandbox jalur odin bila belum tersedia
[ -f /home/kal/my-project/tools/env.sh ] && source /home/kal/my-project/tools/env.sh
# argumen bukan angka: pesan error memuat bentuk yang sah
odin run . -- 24.5 26.0 abcerror: argumen "abc" bukan angka suhu yang sah, contoh: 23.5Kedua kasus tepi berhenti dengan kode keluar 1, yaitu konvensi umum penanda kegagalan pada terminal. Kode itu berguna bagi program lain yang memanggil pemeriksa-suhu, karena keberhasilannya dapat diperiksa melalui variabel status tanpa harus membaca teks keluaran. Pesan penggunaan yang memuat contoh pemanggilan juga meniadakan kebutuhan membuka dokumentasi hanya untuk mengetahui bentuk argumennya.
Kesalahan umum#
Kesalahan pertama adalah menumpuk banyak perubahan dan memeriksa semuanya sekali di akhir. Daftar error yang dihasilkan panjang, saling berkaitan, dan sebagian bisa terpotong oleh batas tampilan compiler, sehingga akar masalah sulit ditemukan. Perbaikannya adalah kembali ke disiplin tahap, yaitu menjalankan odin check . setiap kali satu tambahan kecil selesai ditulis.
Kesalahan kedua adalah melupakan pemisah -- sebelum argumen program. Odin menafsirkan angka seperti 24.5 sebagai opsi build, mencetak pesan Invalid flag, lalu tetap menjalankan program tanpa satu pun argumen, sehingga pesan penggunaan muncul padahal data sudah diketik.
# sumberkan lingkungan sandbox jalur odin bila belum tersedia
[ -f /home/kal/my-project/tools/env.sh ] && source /home/kal/my-project/tools/env.sh
# pemisah -- dilupakan: argumen ditelan sebagai opsi build
odin run . 24.5 26.0Invalid flag: 24.5
Invalid flag: 26.0
Penggunaan: pemeriksa-suhu <suhu-1> <suhu-2> ...
Contoh : pemeriksa-suhu 24.5 26.0 23.0Kesalahan ketiga adalah menulis gerbang kosong sebagai len(os.args) < 1. Entri pertama os.args selalu berisi jalur program, sehingga panjangnya tidak pernah kurang dari satu dan gerbang tidak pernah terpicu. Kondisi yang benar adalah len(os.args) < 2, yang baru bernilai true ketika tidak ada satu pun data suhu menyusul jalur program tersebut.
Ringkasan#
odin check .memeriksa tipe seluruh package tanpa menghasilkan binari, lulus dengan hening, dan dijalankan di akhir setiap tahap sebagai titik pemeriksaan yang murah.- Pemeriksaan per tahap kecil menghasilkan daftar error pendek yang seluruhnya menunjuk baris baru, sedangkan compiler berhenti menampilkan error pada batas tertentu, yakni 36 pada build sandbox ini, apabila perubahan ditumpuk.
- Pemeriksa-suhu dibangun dalam empat tahap yang bertambah, yaitu kerangka package main, parsing
os.args[1:]denganstrconv.parse_f64, statistik rata-rata, minimum, maksimum, hari terdingin dan terpanas, lalu gerbang kasus tepi. - Argumen program dikirim setelah pemisah
--, dan tanpa pemisah itu odin menelan argumen sebagai opsi build sehingga program berjalan tanpa data.
Referensi#
- Overview — Odin Documentation — Panduan resmi bahasa Odin yang mencakup proc main, perulangan, dynamic array, dan pengembalian berganda yang dipakai di setiap tahap.
- Paket core:strconv — Referensi pustaka Odin
— Dokumentasi resmi
parse_f64danparse_intyang menjadi dasar validasi argumen suhu. - Paket core:fmt — Referensi pustaka Odin
— Dokumentasi verb printf, termasuk
%.2fdan%v, yang dipakai pada pelaporan statistik.