java php laravel linux mysql sql bootstrap html css query java php laravel linux mysql sql bootstrap html css query

Sunday, May 3, 2026

dart exception handling

Dart From Zero to Zorro · Artikel 8 dari 16

Exception Handling —
Tangani Error Biar
Aplikasi Nggak Crash

Pelajari cara menangani error di Dart secara elegan — dari try-catch sampai custom exception — supaya aplikasimu tahan banting dan profesional.

#ErrorHandling #ExceptionHandling #TryCatch #Dart
⏱ 8 menit
Estimasi Baca
⚙️ Menengah
Level
2026
Tahun Terbit

Pernah nggak, kamu lagi asik pakai aplikasi — tiba-tiba BLAM! — layarnya putih, atau keluar pesan error yang nggak jelas? Menyebalkan, kan? Nah, itulah yang terjadi kalau developer lupa atau nggak tahu cara menerapkan exception handling Dart yang benar. Artikel ke-8 dari seri Dart From Zero to Zorro ini hadir khusus buat kamu yang mau belajar cara bikin aplikasi yang tahan banting — nggak gampang crash cuma gara-gara input pengguna yang aneh atau koneksi internet yang putus.

Di sini kita akan bongkar tuntas: apa itu exception, kenapa wajib ditangani, dan gimana cara Dart menyediakan mekanisme yang elegan untuk menghadapinya. Siap? Ayo kita mulai!

📌 Definisi Kunci

Exception adalah kondisi tak terduga yang terjadi saat program berjalan — seperti file yang tidak ditemukan, pembagian dengan nol, atau koneksi jaringan yang gagal. Exception handling adalah mekanisme untuk mendeteksi, menangkap, dan merespons kondisi tersebut agar program tetap berjalan dengan benar.

🧯 Kenapa Exception Handling Dart Itu Wajib Kamu Kuasai?

Bayangkan kamu adalah pilot pesawat. Mesin tiba-tiba bermasalah di udara — apakah kamu langsung panik dan biarkan pesawat jatuh? Tentu tidak! Ada prosedur darurat: nyalakan mesin cadangan, hubungi menara kontrol, lakukan pendaratan darurat. Itulah analogi exception handling dalam pemrograman Dart.

Tanpa exception handling, program Dart kamu akan:

📊 Analisis: Dampak Tanpa vs Dengan Exception Handling
Kondisi ❌ Tanpa Handling ✅ Dengan Handling
Input salah App crash 💥 Tampilkan pesan error
Jaringan putus App freeze/crash 💥 Retry atau notifikasi user
File tidak ada Unhandled Exception 💥 Buat file baru / fallback
Bagi dengan nol IntegerDivisionByZeroException 💥 Kembalikan nilai default
🔥 Fakta Menarik

Menurut laporan developer, sekitar 60% bug kritis dalam aplikasi mobile berasal dari error yang tidak ditangani — terutama yang berkaitan dengan I/O, parsing data, dan operasi jaringan. Jadi, exception handling bukan opsional — ini kebutuhan wajib!

🔬 Anatomi Exception Handling di Dart: try, catch, on, finally

Dart menyediakan blok try-catch-finally yang sangat fleksibel. Mari kita bedah satu per satu dengan analogi yang mudah dipahami.

1
Blok try — Zona Percobaan

Semua kode yang berpotensi error dimasukkan ke sini. Analoginya: kamu memasuki ruangan gelap sambil membawa senter — kamu siap jika terjadi sesuatu.

2
Blok on — Tangkap Tipe Spesifik

Gunakan on TipeException untuk menangani jenis error tertentu. Seperti dokter yang punya penanganan berbeda untuk flu vs patah tulang.

3
Blok catch — Tangkap Semua Error

Menangkap exception apapun beserta detail stack trace-nya. Ibarat jaring pengaman di sirkus — siap menangkap apapun yang jatuh.

4
Blok finally — Selalu Dijalankan

Kode di sini akan selalu dijalankan, baik ada error maupun tidak. Cocok untuk tutup koneksi database, tutup file, atau bersihkan resource.

main.dart
// Contoh lengkap: try-on-catch-finally

void ambilDataPengguna(int id) {
  try {
    // Zona berbahaya — kode yang mungkin error
    if (id <= 0) {
      throw ArgumentError('ID pengguna harus lebih dari 0!');
    }
    if (id == 999) {
      throw FormatException('Format ID tidak dikenali.');
    }
    print('Data pengguna ID $id berhasil diambil ✅');

  } on ArgumentError catch (e) {
    // Tangkap ArgumentError secara spesifik
    print('⚠️ Argumen salah: ${e.message}');

  } on FormatException catch (e) {
    // Tangkap FormatException secara spesifik
    print('🔴 Format error: ${e.message}');

  } catch (e, stackTrace) {
    // Tangkap semua error lainnya
    print('❌ Error tak terduga: $e');
    print('Stack trace: $stackTrace');

  } finally {
    // Selalu berjalan — bersihkan resource
    print('🔄 Proses selesai — resource dibersihkan.');
  }
}

void main() {
  ambilDataPengguna(5);    // ✅ Sukses
  ambilDataPengguna(-1);   // ⚠️ ArgumentError
  ambilDataPengguna(999);  // 🔴 FormatException
}
💡 Tips Pro

Urutan blok on sangat penting! Letakkan tipe exception yang paling spesifik di atas, dan yang paling umum di bawah. Kalau dibalik, exception spesifik tidak akan pernah tertangkap karena sudah "dimakan" oleh yang umum.

🛠️ Level Up: Membuat Custom Exception di Dart

Exception bawaan Dart sudah cukup untuk banyak kasus. Tapi bagaimana kalau kamu bikin aplikasi toko online, dan perlu error khusus seperti "stok barang habis" atau "user belum login"? Di sinilah custom exception berperan. Ini adalah tanda bahwa kamu sudah berpikir layaknya developer profesional!

Cara membuat custom exception di Dart sangat mudah — cukup implements class Exception.

custom_exception.dart
// Langkah 1: Buat custom exception class
class StokHabisException implements Exception {
  final String namaProduk;
  final int stokTersisa;

  StokHabisException(this.namaProduk, this.stokTersisa);

  // Override toString untuk pesan yang jelas
  @override
  String toString() {
    return 'StokHabisException: "$namaProduk" '
           'hanya tersisa $stokTersisa unit.';
  }
}

// Langkah 2: Gunakan custom exception
void beliProduk(String nama, int jumlah, int stok) {
  if (jumlah > stok) {
    throw StokHabisException(nama, stok);
  }
  print('🛒 Berhasil membeli $jumlah unit "$nama"!');
}

void main() {
  try {
    beliProduk('Laptop Gaming', 5, 2); // beli 5, stok 2
  } on StokHabisException catch (e) {
    print('❌ Gagal: $e');
    // Output: ❌ Gagal: StokHabisException: "Laptop Gaming"
    //         hanya tersisa 2 unit.
  }
}
⚡ Insight Penting

Di Dart, kamu bisa throw objek apa saja — tidak harus class yang implements Exception. Bahkan throw "Error string" valid! Tapi konvensi terbaik tetap menggunakan class yang implements Exception atau Error agar kode lebih terstruktur dan mudah di-debug.

🔍 Exception vs Error, dan Kapan Pakai rethrow

Banyak pemula yang bingung: apa bedanya Exception dan Error di Dart? Ini perbedaannya dalam dunia nyata.

🆚 Exception vs Error di Dart
✅ Exception
  • Kondisi yang bisa diantisipasi
  • Bisa & sebaiknya di-handle
  • Contoh: FormatException, IOException
  • Berasal dari input user atau sistem eksternal
❌ Error
  • Bug atau kesalahan logika program
  • Biasanya tidak di-catch — dibiarkan crash
  • Contoh: StackOverflowError, OutOfMemoryError
  • Menandakan ada yang salah di kode kamu!

Ada satu keyword keren lagi: rethrow. Gunakan ini ketika kamu ingin mencatat error (logging), lalu melempar kembali exception tersebut ke pemanggil di atasnya.

rethrow_example.dart
void prosesData(String data) {
  try {
    int nilai = int.parse(data); // Bisa throw FormatException
    print('Nilai: $nilai');
  } catch (e) {
    // Catat error ke sistem logging
    print('📋 Log: Error terjadi pada prosesData() — $e');
    rethrow; // Lempar kembali ke pemanggil
  }
}

void main() {
  try {
    prosesData('bukan_angka');
  } catch (e) {
    print('🔴 Ditangkap di main: $e');
  }
}
⚠️ Perhatian

Jangan gunakan catch (e) {} yang kosong (silent catch)! Ini adalah kebiasaan buruk yang menyembunyikan bug. Selalu minimal log atau tampilkan pesan ke user agar kamu tahu ada yang salah.

💡 Tips Best Practice
  • Tangkap exception sepesifik mungkin — hindari catch-all jika tidak perlu.
  • Gunakan finally untuk membersihkan resource (koneksi, file, dsb).
  • Buat custom exception untuk domain logic aplikasi kamu.
  • Jangan lupa uji kode error path kamu — bukan hanya happy path!
📚
Bagian dari Seri
Dart From Zero to Zorro

Artikel ini adalah bagian ke-8 dari 16 artikel seri Belajar Dart: Dart From Zero to Zorro. Lihat daftar lengkap semua artikel untuk belajar Dart dari nol hingga mahir secara terstruktur!

🗺️ Lihat Semua 16 Artikel →
📝 Kesimpulan

Kamu Sudah Satu Langkah Lebih Dekat Jadi Developer Profesional! 🚀

Di artikel ke-8 ini, kita sudah tuntas mempelajari exception handling Dart dari dasar hingga level yang lebih advanced. Berikut poin-poin utama yang wajib kamu ingat:

  • Blok try-on-catch-finally adalah tulang punggung exception handling di Dart.
  • Gunakan on TipeException untuk menangkap error spesifik — lebih aman dan presisi.
  • Custom exception memungkinkan kamu membuat pesan error yang bermakna sesuai domain aplikasimu.
  • Keyword rethrow berguna untuk logging sekaligus meneruskan error ke pemanggil di atasnya.
  • Exception (kondisi yang diantisipasi) berbeda dari Error (bug di kode) — pahami perbedaan ini!

Setelah ini, kita akan masuk ke topik yang tak kalah seru: Dart Asynchronous — di mana kamu akan belajar cara kerja Future, async, dan await. Stay tuned!

📚 Lihat Semua Artikel

💬 Ada pertanyaan? Bingung di bagian mana? Tulis di kolom komentar di bawah — kita diskusi bareng! Dan kalau artikel ini membantu, jangan lupa share ke teman-teman yang juga lagi belajar Dart. Setiap share kamu sangat berarti untuk seri ini terus berlanjut! 🙏

🏷️ Tags
#BelajarDart #DartFromZeroToZorro #ExceptionHandling #ErrorHandling #TryCatch #CustomException #ProgrammingDart #Flutter

dart oop inheritance encapsulation polymorphism

🎯 OOP Lanjutan   Artikel 7 dari 16

OOP Bagian 2
Inheritance, Encapsulation
& Polymorphism

Kuasai tiga pilar OOP yang bikin kode Dart kamu lebih rapi, reusable, dan profesional — dengan analogi dunia nyata yang mudah dipahami.

⏱️
Estimasi Baca
12 Menit
📶
Level
Menengah
📅
Tahun
2026
🎓
Seri
Dart From Zero to Zorro

Pernah nggak kamu nulis kode yang sama berulang kali, dan dalam hati bilang "ini pasti ada cara yang lebih elegan"? Nah, itu tandanya kamu udah siap belajar inheritance, encapsulation, dan polymorphism — tiga senjata rahasia OOP di Dart yang akan mengubah cara kamu menulis kode selamanya. Kalau di artikel sebelumnya kita udah kenalan sama Class dan Object, sekarang kita naik level: kita bahas inheritance polymorphism Dart yang jadi pondasi aplikasi Flutter skala besar. Artikel ini dibuat untuk kamu yang udah paham Class dasar dan siap melangkah lebih jauh. Siap? Kita mulai! 🚀

🧬 Inheritance di Dart — Mewarisi Supaya Tidak Mengulang

Inheritance (pewarisan) adalah mekanisme di mana sebuah class bisa "mewarisi" properti dan method dari class lain. Bayangkan kamu punya resep masakan keluarga turun-temurun — anak bisa memakai resep dasar orang tua, lalu menambah bumbu sendiri tanpa harus menulis ulang seluruh resep dari nol.

Dalam Dart, class yang mewarisi disebut subclass (child class), dan class yang diwarisi disebut superclass (parent class). Kata kunci yang digunakan adalah extends.

📐 Formula Inheritance
class SubClass extends SuperClass { ... }
SubClass mewarisi semua properti & method non-private dari SuperClass.
📋 Langkah-Langkah Membuat Inheritance di Dart
1
Buat Superclass (Parent)
Definisikan class dasar dengan properti dan method yang akan diwarisi. Ini adalah "template umum".
2
Buat Subclass dengan extends
Gunakan kata kunci extends untuk mewarisi. Subclass otomatis punya semua yang dimiliki superclass.
3
Gunakan super untuk akses Parent
Kata kunci super digunakan untuk memanggil constructor atau method milik superclass.
4
Override Method jika Perlu
Subclass bisa menimpa (override) method dari superclass menggunakan anotasi @override.
inheritance_dart.dart
class Hewan {
  String nama;
  int umur;

  Hewan(this.nama, this.umur);

  void bernapas() {
    print('$nama sedang bernapas...');
  }
}

// 🐕 Anjing mewarisi Hewan
class Anjing extends Hewan {
  String ras;

  Anjing(String nama, int umur, this.ras)
      : super(nama, umur); // panggil constructor parent

  void menggonggong() {
    print('$nama ($ras): Woof! Woof!');
  }
}

void main() {
  var doggo = Anjing('Max', 3, 'Golden Retriever');
  doggo.bernapas();     // ✅ diwarisi dari Hewan
  doggo.menggonggong(); // ✅ milik Anjing sendiri
}

// Output:
// Max sedang bernapas...
// Max (Golden Retriever): Woof! Woof!
💡 Tips — Kapan Pakai Inheritance?
Gunakan inheritance kalau hubungan antara dua class bisa diungkapkan dengan kalimat "A adalah B". Contoh: Anjing adalah Hewan ✅. Tapi kalau relasinya lebih seperti "A memiliki B", gunakan composition, bukan inheritance.

🔐 Encapsulation — Lindungi Data, Kontrol Akses

Encapsulation adalah konsep menyembunyikan detail internal class dari dunia luar, dan hanya mengekspos apa yang perlu diekspos. Analoginya seperti mesin ATM — kamu bisa tarik uang, cek saldo, transfer — tapi kamu nggak bisa (dan nggak perlu) tahu gimana mesin ATM memproses semua itu di dalamnya.

Di Dart, encapsulation diterapkan dengan menambahkan underscore (_) di depan nama properti atau method untuk membuatnya menjadi private — hanya bisa diakses dari dalam file yang sama. Akses dari luar dikontrol lewat getter dan setter.

🔥 Fakta Menarik
Di Dart, private itu per-file (library), bukan per-class! Berbeda dengan Java atau C# yang private-nya per-class. Jadi kalau dua class ada dalam satu file .dart yang sama, mereka bisa akses properti private satu sama lain.
encapsulation_dart.dart
class RekeningBank {
  String pemilik;
  double _saldo; // 🔒 private!

  RekeningBank(this.pemilik, this._saldo);

  // Getter — hanya baca
  double get saldo => _saldo;

  // Method terkontrol untuk ubah saldo
  void deposit(double jumlah) {
    if (jumlah > 0) {
      _saldo += jumlah;
      print('Deposit Rp${jumlah} berhasil. Saldo: Rp${_saldo}');
    } else {
      print('❌ Jumlah deposit harus positif!');
    }
  }

  void tarik(double jumlah) {
    if (jumlah <= _saldo) {
      _saldo -= jumlah;
      print('Tarik Rp${jumlah} berhasil. Sisa: Rp${_saldo}');
    } else {
      print('❌ Saldo tidak cukup!');
    }
  }
}

void main() {
  var rekening = RekeningBank('Budi', 500000);
  print(rekening.saldo);         // ✅ OK via getter
  // rekening._saldo = 999999; // ❌ Error! Private
  rekening.deposit(200000);
  rekening.tarik(800000);       // ❌ Saldo tidak cukup
}
⚠️ Perhatian
Jangan langsung buat semua properti private hanya karena terdengar "lebih aman". Terlalu banyak getter/setter justru membuat kode verbose. Pertimbangkan mana data yang benar-benar perlu dilindungi dari modifikasi langsung.

🎭 Polymorphism — Satu Interface, Banyak Bentuk

Polymorphism berasal dari bahasa Yunani: poly (banyak) + morphe (bentuk). Dalam dunia inheritance polymorphism Dart, konsep ini berarti satu method yang sama bisa berperilaku berbeda tergantung object yang menggunakannya.

Analogi: tombol "play" di YouTube dan Spotify melakukan hal yang berbeda, tapi keduanya tetap dinamakan tombol "play". Inilah inti dari polymorphism — antarmuka yang sama, implementasi yang berbeda.

Di Dart, polymorphism dicapai melalui method overriding (menimpa method dari superclass) dan interface/abstract class.

polymorphism_dart.dart
// Abstract class = kontrak yang harus dipenuhi
abstract class Bentuk {
  double hitungLuas(); // wajib diimplementasi
  void info() {
    print('Luas: ${hitungLuas()}');
  }
}

class Lingkaran extends Bentuk {
  double radius;
  Lingkaran(this.radius);

  @override
  double hitungLuas() => 3.14 * radius * radius;
}

class Persegi extends Bentuk {
  double sisi;
  Persegi(this.sisi);

  @override
  double hitungLuas() => sisi * sisi;
}

void main() {
  // 🎭 Polymorphism: satu tipe, banyak bentuk
  List<Bentuk> daftarBentuk = [
    Lingkaran(7),
    Persegi(5),
    Lingkaran(3),
  ];

  for (var b in daftarBentuk) {
    b.info(); // method yang SAMA, hasil BEDA!
  }
}
// Output:
// Luas: 153.86
// Luas: 25.0
// Luas: 28.26
⚡ Insight Penting
Polymorphism membuat kode kamu sangat extensible. Mau tambah bentuk baru seperti Segitiga atau Trapesium? Cukup buat class baru yang extends Bentuk, dan loop di main() nggak perlu diubah sama sekali. Ini yang disebut Open/Closed Principle — terbuka untuk ekstensi, tertutup untuk modifikasi.

📊 Perbandingan: Inheritance vs Encapsulation vs Polymorphism

🔍 Analisis Mendalam — Kapan Menggunakan Masing-masing?
Konsep Tujuan Utama Kata Kunci Dart Analogi
Inheritance Reuse kode dari parent class extends, super 📜 Resep turun-temurun
Encapsulation Lindungi data internal _nama, get, set 🏧 Mesin ATM
Polymorphism Satu interface, banyak perilaku @override, abstract ▶️ Tombol Play
Gabungan ketiganya Arsitektur kode yang scalable semua di atas 🏢 Sistem perbankan

🚀 Studi Kasus — Gabungkan Ketiganya dalam Proyek Nyata

Sekarang saatnya kita gabungkan inheritance polymorphism Dart bersama encapsulation dalam satu contoh yang realistis: sistem pembayaran sederhana. Ini persis pola yang akan kamu temui saat membangun aplikasi Flutter sungguhan.

payment_system.dart
// 🎭 Abstract Class — Polymorphism
abstract class MetodePembayaran {
  String _namaPenyedia; // 🔒 Encapsulation
  double _saldo;

  MetodePembayaran(this._namaPenyedia, this._saldo);

  String get namaPenyedia => _namaPenyedia;
  double get saldo => _saldo;

  void bayar(double jumlah); // wajib diimplementasi

  bool cukupSaldo(double jumlah) => _saldo >= jumlah;
}

// 🧬 Inheritance + Polymorphism
class GoPay extends MetodePembayaran {
  GoPay(double saldo) : super('GoPay', saldo);

  @override
  void bayar(double jumlah) {
    if (cukupSaldo(jumlah)) {
      _saldo -= jumlah;
      print('✅ [GoPay] Bayar Rp$jumlah. Sisa: Rp$_saldo');
    } else {
      print('❌ [GoPay] Saldo tidak cukup!');
    }
  }
}

class OVO extends MetodePembayaran {
  int _poinOvo; // fitur tambahan OVO

  OVO(double saldo) : _poinOvo = 0, super('OVO', saldo);

  @override
  void bayar(double jumlah) {
    if (cukupSaldo(jumlah)) {
      _saldo -= jumlah;
      _poinOvo += (jumlah * 0.01).toInt();
      print('✅ [OVO] Bayar Rp$jumlah. Poin: $_poinOvo');
    } else {
      print('❌ [OVO] Saldo tidak cukup!');
    }
  }
}

void main() {
  List<MetodePembayaran> dompet = [
    GoPay(150000),
    OVO(200000),
  ];

  for (var m in dompet) {
    print('Dompet: ${m.namaPenyedia}');
    m.bayar(50000); // Polymorphism!
  }
}
⚡ Insight — Pola ini Ada di Flutter!
Di Flutter, kamu akan sering melihat pola ini. Widget adalah abstract class, dan semua widget seperti Text, Container, Row adalah subclass-nya. Method build() adalah contoh polymorphism yang kamu override setiap hari!

🎯 Kesimpulan

Di artikel ke-7 seri Dart From Zero to Zorro ini, kita sudah menyelami tiga pilar OOP yang krusial:

  • Inheritance — mewarisi properti & method dengan extends, menghemat kode duplikat
  • Encapsulation — melindungi data internal dengan underscore (_), getter, dan setter
  • Polymorphism — satu interface, banyak implementasi via @override dan abstract class

Menguasai inheritance polymorphism Dart bukan sekadar hafalan teori — ini adalah pola pikir yang akan mengubah cara kamu merancang solusi. Setiap kali kamu membuka proyek Flutter, kamu akan melihat ketiga konsep ini bekerja bersama-sama di balik layar.

💬 Punya pertanyaan atau bingung di bagian mana? Tulis di kolom komentar! Dan kalau artikel ini bermanfaat, share ke teman-teman yang lagi belajar Dart — siapa tahu jadi pahala ilmu! 🙏
#BelajarDart #DartFromZeroToZorro #OOPDart #Inheritance #Polymorphism #Encapsulation #Flutter #ProgrammingIndonesia
📚
Bagian dari Seri 16 Artikel
Dart From Zero to Zorro

Artikel ini adalah bagian ke-7 dari seri lengkap belajar Dart dari nol hingga mahir. Mulai dari sintaks dasar sampai membangun aplikasi Flutter, semua ada di sini!

🗺️ Lihat Daftar Isi Lengkap →
🧭 Navigasi Artikel
← Artikel Sebelumnya
Artikel 6
OOP Bagian 1 — Class, Object, dan Constructor di Dart
← Baca Artikel Ini
Artikel Selanjutnya →
Artikel 8
Exception Handling — Tangani Error Biar Aplikasi Nggak Crash
Baca Artikel Ini →

saifiahmada.com adalah blog belajar programming Indonesia, membahas lengkap materi bahasa pemrograman: code HTML, CSS, Bootstrap, Desain, PHP, MySQL, coding Java, Query, SQL, dan dunia linux