Penanganan Error
Teknik defensive programming untuk menangani kondisi tak terduga dan mencegah program crash di NusaScript.
Strategi Penanganan Error
NusaScript menggunakan tiga pendekatan utama untuk penanganan error:
| Pendekatan | Kapan Digunakan |
|---|---|
coba/tangkap | Operasi yang bisa gagal (database, file, parsing) |
lempar | Melempar error dari fungsi Anda |
| Cek nilai nihil | Hasil query database, fungsi yang bisa gagal |
| Validasi input | Sebelum memproses data dari pengguna |
Blok coba / tangkap
Gunakan coba untuk menjalankan kode yang mungkin menghasilkan error, dan tangkap untuk menangani error tersebut.
Contoh — coba/tangkap Dasar
coba {
tampilkan("Mencoba operasi yang aman...")
buat x = 10 + 5
tampilkan("Hasil: " + x)
} tangkap(err) {
tampilkan("ERROR: " + err)
}
Output
Mencoba operasi yang aman... Hasil: 15
Melempar Error — lempar
Gunakan lempar untuk membuat error baru. Error akan ditangkap oleh blok tangkap terdekat.
Contoh — Lempar dan Tangkap
coba {
tampilkan("Mencoba koneksi DB...")
lempar "Koneksi database terputus!"
tampilkan("Baris ini TIDAK dijalankan")
} tangkap(err) {
tampilkan("Ditangkap: " + err)
}
Output
Mencoba koneksi DB... Ditangkap: Koneksi database terputus!
Blok akhirnya
Blok akhirnya akan selalu dijalankan, baik ada error maupun tidak. Berguna untuk cleanup.
Contoh — Dengan akhirnya
coba {
lempar "Terjadi kesalahan!"
} tangkap(e) {
tampilkan("Error: " + e)
} akhirnya {
tampilkan("Cleanup selesai") // Selalu dijalankan
}
Output
Error: Terjadi kesalahan! Cleanup selesai
Lempar Error dari Fungsi
Contoh — Validasi dalam Fungsi
fungsi bagi(a, b) {
jika b == 0 {
lempar "Tidak bisa membagi dengan nol!"
}
kembalikan a / b
}
coba {
tampilkan(bagi(10, 0))
} tangkap(e) {
tampilkan(e) // "Tidak bisa membagi dengan nol!"
}
Nested coba/tangkap
Contoh — Bersarang
coba {
coba {
lempar "Error di dalam"
} tangkap(e1) {
tampilkan("Tangkap dalam: " + e1)
lempar "Error diteruskan dari tangkap"
}
} tangkap(e2) {
tampilkan("Tangkap luar: " + e2)
}
Output
Tangkap dalam: Error di dalam Tangkap luar: Error diteruskan dari tangkap
| Keyword | Fungsi | Padanan |
|---|---|---|
coba | Blok kode yang mungkin error | try |
tangkap(err) | Menangkap dan handle error | catch |
akhirnya | Selalu dijalankan (opsional) | finally |
lempar | Melempar error baru | throw |
Cek Nilai Nihil
Banyak fungsi NusaScript mengembalikan nihil ketika operasi gagal atau tidak menemukan data.
Contoh — Cek Hasil Database
buat db = db_buka("sqlite", "app.db")
buat user = db_ambil_satu(db, "SELECT * FROM pengguna WHERE id=?", 999)
// Cek apakah data ditemukan
jika user == nihil {
tampilkan("Pengguna tidak ditemukan!")
keluar(1)
}
tampilkan("Nama:", ambil(user, "nama"))
tampilkan("Email:", ambil(user, "email"))
Validasi Input API
Contoh — Validasi Berlapis
fungsi validasi_email(email) {
jika email == nihil atau email == "" {
kembalikan "Email tidak boleh kosong"
}
jika !muat(email, "@") {
kembalikan "Format email tidak valid"
}
jika panjang(email) < 5 {
kembalikan "Email terlalu pendek"
}
kembalikan nihil // tidak ada error
}
fungsi validasi_sandi(sandi) {
jika sandi == nihil atau sandi == "" {
kembalikan "Sandi tidak boleh kosong"
}
jika panjang(sandi) < 8 {
kembalikan "Sandi minimal 8 karakter"
}
kembalikan nihil
}
// Gunakan di handler
tambah_rute(app, "POST", "/daftar", fungsi(req) {
buat b = body_json(req)
buat email = ambil(b, "email")
buat sandi = ambil(b, "sandi")
buat nama = ambil(b, "nama")
// Validasi satu per satu
buat err_email = validasi_email(email)
jika err_email != nihil {
kembalikan ke_json({"error": err_email})
}
buat err_sandi = validasi_sandi(sandi)
jika err_sandi != nihil {
kembalikan ke_json({"error": err_sandi})
}
jika nama == nihil atau panjang(nama) < 2 {
kembalikan ke_json({"error": "Nama minimal 2 karakter"})
}
// Semua valid, proses pendaftaran
buat hash = hash_sandi(sandi)
buat db = db_buka("sqlite", "app.db")
db_query(db, "INSERT INTO pengguna (nama, email, sandi_hash) VALUES (?, ?, ?)",
nama, email, hash)
kembalikan ke_json({"sukses": benar, "pesan": "Pendaftaran berhasil"})
})
Guard Clause Pattern
Kembalikan lebih awal (early return) untuk mengurangi nesting dan membuat kode lebih mudah dibaca.
Contoh — Early Return
// ❌ Buruk — banyak nesting
fungsi proses_buruk(req) {
buat token = header_req(req, "Authorization")
jika token != "" {
buat klaim = jwt_verifikasi(token, "rahasia")
jika klaim != nihil {
buat id = ambil(klaim, "id")
buat db = db_buka("sqlite", "app.db")
buat user = db_ambil_satu(db, "SELECT * FROM pengguna WHERE id=?", id)
jika user != nihil {
kembalikan ke_json(user)
}
}
}
kembalikan ke_json({"error": "Gagal"})
}
// ✅ Bagus — guard clause (early return)
fungsi proses_bagus(req) {
buat token = header_req(req, "Authorization")
jika token == "" {
kembalikan ke_json({"error": "Token diperlukan"})
}
buat klaim = jwt_verifikasi(token, "rahasia")
jika klaim == nihil {
kembalikan ke_json({"error": "Token tidak valid"})
}
buat id = ambil(klaim, "id")
buat db = db_buka("sqlite", "app.db")
buat user = db_ambil_satu(db, "SELECT * FROM pengguna WHERE id=?", id)
jika user == nihil {
kembalikan ke_json({"error": "Pengguna tidak ditemukan"})
}
kembalikan ke_json(user)
}
Defensive Programming untuk Array
Contoh — Cek Panjang Array
buat db = db_buka("sqlite", "app.db")
buat rows = db_ambil_semua(db, "SELECT * FROM produk WHERE kategori_id=?", 5)
// Selalu cek panjang sebelum akses indeks
jika panjang(rows) == 0 {
tampilkan("Tidak ada produk dalam kategori ini")
keluar(0)
}
buat pertama = rows[0]
tampilkan("Produk pertama:", ambil(pertama, "nama"))
// Loop dengan aman
buat i = 0
selama i < panjang(rows) {
buat r = rows[i]
tampilkan(i + 1, ".", ambil(r, "nama"), "-", format_rupiah(ambil(r, "harga")))
i += 1
}
Error Response Standar API
Contoh — Response Error Konsisten
// Definisikan helper response sekali, gunakan di mana-mana
fungsi sukses(data) {
kembalikan ke_json({
"sukses" : benar,
"data" : data,
"timestamp" : format_waktu(waktu_sekarang())
})
}
fungsi gagal(pesan, kode) {
kembalikan ke_json({
"sukses" : salah,
"error" : pesan,
"kode" : kode,
"timestamp" : format_waktu(waktu_sekarang())
})
}
// Penggunaan
tambah_rute(app, "GET", "/api/pengguna", fungsi(req) {
buat token = header_req(req, "Authorization")
jika token == "" {
kembalikan gagal("Token autentikasi diperlukan", 401)
}
buat klaim = jwt_verifikasi(token, "rahasia")
jika klaim == nihil {
kembalikan gagal("Token tidak valid atau kedaluwarsa", 403)
}
buat db = db_buka("sqlite", "app.db")
buat data = db_ambil_semua(db, "SELECT id, nama, email FROM pengguna")
kembalikan sukses(data)
})
📌 Prinsip Utama: Selalu anggap input dari luar (request body, query param, header) sebagai data yang tidak bisa dipercaya. Validasi semua input sebelum memprosesnya.