Exception bukan satu-satunya cara melaporkan kegagalan. Alternatifnya disebut result pattern: method mengembalikan nilai yang menggambarkan hasil — bool, tuple, atau tipe data khusus — dan pemanggil memeriksa nilainya sebelum lanjut. Kedua pendekatan sah di dunia nyata; tugas kita adalah memahami perbedaannya dan memilih dengan sadar.
Pendekatan Result: Kegagalan sebagai Nilai #
csharp
Dictionary<string, int> stok = new Dictionary<string, int>
{
{ "Kopi", 24 },
{ "Teh", 0 }
};
(bool sukses, string pesan, int jumlahStok) = CekStokResult("Kopi", stok);
Console.WriteLine($"Result (tuple) - sukses: {sukses}, pesan: {pesan}, stok: {jumlahStok}");
(bool suksesTeh, string pesanTeh, int stokTeh) = CekStokResult("Teh", stok);
Console.WriteLine($"Result (tuple) - sukses: {suksesTeh}, pesan: {pesanTeh}, stok: {stokTeh}");
HasilCekStok hasilPenghapus = CekStokRecord("Penghapus", stok);
Console.WriteLine($"Result (record) - sukses: {hasilPenghapus.Sukses}, pesan: {hasilPenghapus.Pesan}");
static (bool Sukses, string Pesan, int Stok) CekStokResult(string nama, Dictionary<string, int> stok)
{
if (!stok.TryGetValue(nama, out int jumlah))
{
return (false, $"Produk '{nama}' tidak terdaftar", 0);
}
if (jumlah == 0)
{
return (false, $"Produk '{nama}' sedang kosong", 0);
}
return (true, "Tersedia", jumlah);
}
static HasilCekStok CekStokRecord(string nama, Dictionary<string, int> stok)
{
if (!stok.TryGetValue(nama, out int jumlah) || jumlah == 0)
{
return new HasilCekStok(false, $"Produk '{nama}' tidak tersedia");
}
return new HasilCekStok(true, "Tersedia");
}
public sealed record HasilCekStok(bool Sukses, string Pesan);Output yang Dihasilkan:
text
Result (tuple) - sukses: True, pesan: Tersedia, stok: 24
Result (tuple) - sukses: False, pesan: Produk 'Teh' sedang kosong, stok: 0
Result (record) - sukses: False, pesan: Produk 'Penghapus' tidak tersediaMari kita telaah bagian pentingnya:
- Baris 7-8 (dekonstruksi tuple): Method
CekStokResultmengembalikan tiga informasi sekaligus —bool, pesan, dan stok — dan dekonstruksi tuple memecahnya ke variabel terpisah; kegagalan “Teh kosong” diterima sebagai nilai biasa, tanpa lompatan alur. - Baris 13-14 (record):
recordadalah tipe referensi ringkas untuk membungkus data; satu baris deklarasi menghasilkan tipeHasilCekStokdengan propertiSuksesdanPesan— bahasannya menyeluruh di section Pemrograman Berorientasi Objek. - Baris 16-29 (method
CekStokResult): Setiap kemungkinan gagal dikembalikan sebagai nilai denganfalseplus pesan; method tidak pernah melempar exception.
Pendekatan Exception: Kegagalan yang Melompat #
Versi yang sama dengan exception memindahkan alur kegagalan ke blok catch:
csharp
try
{
int jumlah = AmbilStokDenganException("Gula", stok);
Console.WriteLine($"Exception - stok terbaca: {jumlah}");
}
catch (KeyNotFoundException ex)
{
Console.WriteLine($"Exception - ditangkap: {ex.Message}");
}
static int AmbilStokDenganException(string nama, Dictionary<string, int> stok)
{
if (!stok.TryGetValue(nama, out int jumlah))
{
throw new KeyNotFoundException($"Produk '{nama}' tidak terdaftar");
}
return jumlah;
}Output yang Dihasilkan:
text
Exception - ditangkap: Produk 'Gula' tidak terdaftarKapan Memilih yang Mana #
| Situasi | Pendekatan yang tepat |
|---|---|
| Kegagalan yang diharapkan dan sering terjadi (validasi input, data tidak ada) | Result pattern |
| Kondisi yang menandakan bug atau kondisi tak terduga | Exception |
| Alur harus berhenti dan kegagalan perlu mencapai lapisan atas dengan cepat | Exception |
| Pemanggil harus ditegaskan untuk memeriksa hasil | Result pattern |