Membaca artikel Eric Lippert tentang pengecualian jelas merupakan pembuka mata tentang bagaimana saya harus mendekati pengecualian, baik sebagai produsen maupun sebagai konsumen. Namun, saya masih berjuang untuk mendefinisikan pedoman tentang bagaimana menghindari melemparkan pengecualian yang menjengkelkan.
Secara khusus:
- Misalkan Anda memiliki metode Simpan yang dapat gagal karena a) Orang lain memodifikasi catatan sebelum Anda , atau b) Nilai yang Anda coba buat sudah ada . Kondisi ini diharapkan dan tidak luar biasa, jadi alih-alih melemparkan pengecualian Anda memutuskan untuk membuat versi Coba dari metode Anda, TrySave, yang mengembalikan boolean yang menunjukkan jika penyelamatan berhasil. Tetapi jika gagal, bagaimana konsumen tahu apa masalahnya? Atau akan lebih baik untuk mengembalikan enum yang menunjukkan hasil, seperti Ok / RecordAlreadyModified / ValueAlreadyExists? Dengan integer.TryParse masalah ini tidak ada, karena hanya ada satu alasan metode ini dapat gagal.
- Apakah contoh sebelumnya benar-benar situasi yang menjengkelkan? Atau akankah melemparkan pengecualian dalam kasus ini menjadi cara yang disukai? Saya tahu itulah yang dilakukan di sebagian besar perpustakaan dan kerangka kerja, termasuk kerangka kerja Entity.
- Bagaimana Anda memutuskan kapan akan membuat versi Coba dari metode Anda vs. menyediakan beberapa cara untuk menguji sebelumnya apakah metode itu akan berfungsi atau tidak? Saat ini saya mengikuti pedoman ini:
- Jika ada kemungkinan kondisi balapan, maka buat versi Coba. Ini mencegah kebutuhan konsumen untuk menangkap pengecualian eksogen. Misalnya, dalam metode Simpan yang dijelaskan sebelumnya.
- Jika metode untuk menguji kondisi cukup banyak akan melakukan semua yang metode asli lakukan, maka buat versi Coba. Misalnya, integer.TryParse ().
- Dalam kasus lain, buat metode untuk menguji kondisi.
exceptions
Mike
sumber
sumber
Jawaban:
Pertanyaan bagus.
Pertanyaan pertama yang muncul di benak saya adalah: jika data sudah ada di sana dalam arti apa penyelamatan gagal ? Pasti kedengarannya berhasil bagi saya. Tetapi mari kita asumsikan demi argumen bahwa Anda benar-benar memiliki banyak alasan berbeda mengapa operasi bisa gagal.
Pertanyaan kedua yang muncul di benak saya adalah: apakah informasi yang ingin Anda kembalikan kepada pengguna dapat ditindaklanjuti ? Yaitu, apakah mereka akan mengambil keputusan berdasarkan informasi itu?
Ketika lampu "mesin periksa" menyala, saya membuka kap mobil, memverifikasi bahwa ada mesin di mobil saya yang tidak terbakar, dan membawanya ke garasi. Tentu saja di garasi mereka memiliki semua jenis peralatan diagnostik tujuan khusus yang memberi tahu mereka mengapa lampu engine menyala, tetapi dari sudut pandang saya , sistem peringatan dirancang dengan baik. Saya tidak peduli apakah masalahnya karena sensor oksigen merekam tingkat oksigen abnormal di ruang bakar, atau karena detektor kecepatan idle dicabut, atau apa pun. Saya akan mengambil tindakan yang sama, yaitu, biarkan orang lain memikirkan hal ini .
Apakah penelepon peduli mengapa penyelamatan gagal? Apakah mereka akan melakukan sesuatu tentang hal itu, selain menyerah atau mencoba lagi?
Mari kita asumsikan demi argumen bahwa penelepon benar-benar akan mengambil tindakan yang berbeda tergantung pada alasan mengapa operasi gagal.
Pertanyaan ketiga yang terlintas dalam pikiran adalah: apakah mode kegagalan luar biasa ? Saya pikir Anda mungkin bingung dengan tidak mungkin . Saya akan memikirkan dua pengguna yang berusaha mengubah catatan yang sama pada saat yang sama sebagai situasi yang luar biasa tetapi mungkin, bukan situasi yang umum.
Mari kita asumsikan demi argumen bahwa itu tidak biasa.
Pertanyaan keempat yang muncul di benak saya adalah: adakah cara untuk mendeteksi situasi buruk sebelumnya dengan andal?
Jika situasi buruk ada dalam ember "eksogen" saya, maka, tidak. Tidak ada cara untuk mengatakan "apakah pengguna lain mengubah catatan ini?" karena mereka mungkin memodifikasinya setelah Anda mengajukan pertanyaan . Jawabannya basi segera setelah dihasilkan.
Pertanyaan kelima yang terlintas dalam pikiran adalah: apakah ada cara untuk merancang API sehingga situasi buruk dapat dicegah?
Misalnya, Anda dapat membuat operasi "simpan" memerlukan dua langkah. Langkah satu: dapatkan kunci pada catatan yang sedang dimodifikasi. Operasi itu berhasil atau gagal sehingga dapat mengembalikan Boolean. Penelepon kemudian dapat memiliki kebijakan tentang bagaimana menghadapi kegagalan: tunggu sebentar dan coba lagi, menyerah, apa pun. Langkah dua: setelah kunci diperoleh, lakukan simpan dan lepaskan kunci. Sekarang save selalu berhasil sehingga tidak perlu khawatir tentang segala jenis penanganan kesalahan. Jika penyelamatan gagal, itu benar-benar luar biasa.
sumber
Dalam contoh Anda, jika situasi ValueAlreadyExists dapat dengan mudah diperiksa, itu harus diperiksa dan pengecualian dapat dimunculkan sebelum mencoba Simpan, saya tidak berpikir Coba harus diperlukan dalam situasi ini. Kondisi balapan lebih sulit untuk diperiksa sebelumnya, jadi membungkus Simpan dalam Coba dalam hal ini mungkin ide yang sangat bagus.
Secara umum, jika ada kondisi yang saya pikir sangat mungkin (seperti NoDataReturned, DivideByZero, dll ...) ATAU sangat mudah untuk memeriksa (seperti koleksi kosong atau nilai NULL), saya mencoba memeriksa sebelumnya dan menghadapinya sebelum saya sampai ke titik di mana saya harus menangkap pengecualian. Saya akui itu tidak selalu mudah untuk mengetahui kondisi ini sebelumnya, kadang-kadang mereka hanya muncul ketika kode sedang dalam pengujian ketat.
sumber
The
save()
Metode harus melempar pengecualian.Lapisan paling atas harus menangkap dan memberi tahu pengguna , tanpa menghentikan program, kecuali jika itu adalah program baris perintah Unix, dalam hal ini OK untuk mengakhiri.
Nilai pengembalian bukan cara yang baik untuk mengelola pengecualian.
sumber