Ada banyak persyaratan yang dibutuhkan suatu sistem untuk menyampaikan dan menangani pengecualian dengan benar. Ada juga banyak pilihan untuk dipilih suatu bahasa untuk mengimplementasikan konsep tersebut.
Persyaratan untuk pengecualian (tanpa urutan tertentu):
Dokumentasi : Suatu bahasa harus memiliki maksud untuk mendokumentasikan pengecualian yang dapat dilemparkan API. Idealnya media dokumentasi ini dapat digunakan mesin untuk memungkinkan kompiler dan IDE untuk memberikan dukungan kepada programmer.
Mentransmisikan Situasi Luar Biasa : Yang ini jelas, untuk memungkinkan suatu fungsi menyampaikan situasi yang mencegah fungsi yang disebut melakukan tindakan yang diharapkan. Menurut pendapat saya ada tiga kategori besar dari situasi seperti ini:
2.1 Bug dalam kode yang menyebabkan beberapa data menjadi tidak valid.
2.2 Masalah dalam konfigurasi atau sumber daya eksternal lainnya.
2.3 Sumber daya yang secara inheren tidak dapat diandalkan (jaringan, sistem file, database, pengguna akhir dll). Ini adalah sedikit kasus sudut karena sifat tidak dapat diandalkan kita harus mengharapkan kegagalan sporadis mereka. Dalam hal ini apakah situasi ini dianggap luar biasa?
Berikan informasi yang cukup untuk kode untuk menanganinya : Pengecualian harus memberikan informasi yang cukup kepada callee sehingga dapat bereaksi dan mungkin menangani situasi. informasi juga harus memadai sehingga ketika dicatat pengecualian ini akan memberikan konteks yang cukup bagi seorang programmer untuk mengidentifikasi dan mengisolasi pernyataan yang menyinggung dan memberikan solusi.
Berikan kepercayaan kepada programmer tentang status saat ini dari status eksekusi kode-nya : Pengecualian kemampuan penanganan sistem perangkat lunak harus ada cukup untuk memberikan perlindungan yang diperlukan sambil tetap berada di luar jalan programmer sehingga ia bisa tetap fokus pada tugas di tangan.
Untuk mengatasinya, metode berikut diimplementasikan dalam berbagai bahasa:
Pengecualian yang Diperiksa Menyediakan cara yang bagus untuk mendokumentasikan pengecualian, dan secara teoritis bila diterapkan dengan benar harus memberikan jaminan yang cukup bahwa semuanya baik. Namun biayanya sedemikian rupa sehingga banyak yang merasa lebih produktif untuk mem-bypass baik dengan menelan pengecualian atau melemparkannya kembali sebagai pengecualian yang tidak diperiksa. Ketika digunakan pengecualian diperiksa tidak tepat cukup banyak kehilangan semua manfaatnya. Selain itu, pengecualian yang diperiksa membuat sulit untuk membuat API yang stabil dalam waktu. Implementasi sistem generik dalam domain tertentu akan membawa beban situasi luar biasa yang akan sulit dipertahankan dengan menggunakan pengecualian yang hanya diperiksa.
Pengecualian yang Tidak Dicentang - jauh lebih fleksibel daripada pengecualian yang diperiksa, mereka gagal mendokumentasikan situasi luar biasa yang mungkin terjadi dari implementasi yang diberikan. Mereka mengandalkan dokumentasi ad-hoc jika sama sekali. Ini menciptakan situasi di mana sifat media yang tidak dapat diandalkan ditutupi oleh API yang memberikan tampilan keandalan. Juga ketika dilontarkan pengecualian ini kehilangan artinya ketika bergerak kembali melalui lapisan abstraksi. Karena mereka didokumentasikan dengan buruk, seorang programmer tidak dapat menargetkan mereka secara khusus dan seringkali perlu menggunakan jaringan yang lebih luas daripada yang diperlukan untuk memastikan bahwa sistem sekunder, jika mereka gagal, jangan menjatuhkan seluruh sistem. Yang membawa kita kembali ke masalah menelan pengecualian yang disediakan.
Multistate return types Ini dia bergantung pada set disjoint, tuple, atau konsep serupa lainnya untuk mengembalikan hasil yang diharapkan atau objek yang mewakili pengecualian. Di sini tidak ada tumpukan yang dibuka, tidak ada pemotongan kode, semuanya dijalankan secara normal tetapi nilai kembali harus divalidasi untuk kesalahan sebelum melanjutkan. Saya belum benar-benar bekerja dengan ini, jadi saya tidak bisa berkomentar dari pengalaman. Saya mengakuinya menyelesaikan beberapa masalah pengecualian dengan melewati aliran normal tapi tetap saja akan menderita banyak masalah yang sama seperti pengecualian diperiksa sebagai melelahkan dan terus-menerus "di wajah Anda".
Jadi pertanyaannya adalah:
Apa pengalaman Anda dalam hal ini dan apa, menurut Anda adalah kandidat terbaik untuk membuat sistem penanganan perkecualian yang baik untuk sebuah bahasa?
EDIT: Beberapa menit setelah menulis pertanyaan ini saya menemukan posting ini , seram!
sumber
noexcept
cerita di C ++ dapat menghasilkan wawasan yang sangat baik untuk EH di C # dan Java juga.)Jawaban:
Pada hari-hari awal C ++ kami menemukan bahwa tanpa semacam pemrograman generik, bahasa yang diketik sangat sulit. Kami juga menemukan bahwa pengecualian yang diperiksa dan pemrograman generik tidak bekerja bersama dengan baik, dan pengecualian yang diperiksa pada dasarnya ditinggalkan.
Jenis pengembalian multiset bagus, tetapi tidak ada pengganti untuk pengecualian. Tanpa pengecualian, kode ini penuh dengan noise pengecekan error.
Masalah lain dengan pengecualian yang diperiksa adalah bahwa perubahan dalam pengecualian yang dilemparkan oleh fungsi tingkat rendah memaksa sejumlah perubahan di semua penelepon, dan penelepon mereka, dan seterusnya. Satu-satunya cara untuk mencegah hal ini adalah agar setiap level kode menangkap setiap pengecualian yang dilemparkan oleh level yang lebih rendah dan membungkusnya dengan pengecualian baru. Sekali lagi, Anda berakhir dengan kode yang sangat bising.
sumber
Untuk bahasa OO yang lama, penggunaan pengecualian telah menjadi standar de-facto untuk mengkomunikasikan kesalahan. Tetapi bahasa pemrograman fungsional memberikan kemungkinan pendekatan yang berbeda, misalnya menggunakan monad (yang belum pernah saya gunakan), atau "Pemrograman Berorientasi Kereta Api" yang lebih ringan, seperti dijelaskan oleh Scott Wlaschin.
Di posting blog ini
Dalam presentasi ini di NDC 2014
Ini benar-benar varian dari tipe hasil multistate.
Jenis hasil dapat dinyatakan seperti ini
Jadi hasil dari fungsi yang mengembalikan tipe ini akan berupa a
Success
atauFail
tipe. Tidak mungkin keduanya.Dalam bahasa pemrograman yang lebih berorientasi imperatif, gaya semacam ini bisa memerlukan sejumlah besar kode di situs pemanggil. Tetapi pemrograman fungsional memungkinkan Anda untuk membangun fungsi yang mengikat atau operator untuk menyatukan beberapa fungsi sehingga pengecekan kesalahan tidak memakan setengah kode. Sebagai contoh:
The
updateUser
fungsi panggilan masing-masing fungsi berturut-turut, dan masing-masing dari mereka bisa gagal. Jika mereka semua berhasil, hasil dari fungsi terakhir yang dipanggil dikembalikan. Jika salah satu fungsi gagal, maka hasil dari fungsi itu akan menjadi hasil dari keseluruhanupdateUser
fungsi. Ini semua ditangani oleh operator kustom >> =.Dalam contoh di atas, tipe kesalahan bisa jadi
Jika penelepon
updateUser
tidak secara eksplisit menangani semua kemungkinan kesalahan dari fungsi, kompiler akan mengeluarkan peringatan. Jadi, Anda telah mendokumentasikan semuanya.Di Haskell, ada
do
notasi yang dapat membuat kode lebih bersih.sumber
do
notasi Haskell , yang membuat kode yang dihasilkan lebih bersih.Railway Oriented Programming
adalah perilaku persis monadik.Saya menemukan jawaban Pete sangat bagus dan saya ingin menambahkan beberapa pertimbangan dan satu contoh. Diskusi yang sangat menarik tentang penggunaan pengecualian versus mengembalikan nilai kesalahan khusus dapat ditemukan di Pemrograman dalam ML Standar, oleh Robert Harper , di akhir Bagian 29.3, halaman 243, 244.
Masalahnya adalah untuk mengimplementasikan fungsi parsial
f
mengembalikan nilai dari beberapa tipet
. Salah satu solusinya adalah memiliki fungsi berjenisdan melemparkan pengecualian ketika tidak ada hasil yang mungkin. Solusi kedua adalah mengimplementasikan fungsi dengan tipe
dan kembali
SOME v
pada kesuksesan, danNONE
pada kegagalan.Ini adalah teks dari buku, dengan adaptasi kecil yang dibuat oleh saya sendiri untuk menjadikan teks lebih umum (buku merujuk pada contoh tertentu). Teks yang dimodifikasi ditulis dalam huruf miring .
Sejauh menyangkut pilihan antara pengecualian dan jenis pengembalian opsi.
Mengenai gagasan bahwa merepresentasikan kesalahan dalam tipe pengembalian menyebabkan pemeriksaan kesalahan tersebar di seluruh kode: ini tidak perlu menjadi masalah. Berikut adalah contoh kecil dalam Haskell yang menggambarkan ini.
Misalkan kita ingin menguraikan dua angka dan kemudian membagi yang pertama dengan yang kedua. Jadi mungkin ada kesalahan saat menguraikan setiap angka, atau saat membagi (pembagian dengan nol). Jadi kita harus memeriksa kesalahan setelah setiap langkah.
Penguraian dan pembagian dilakukan di
let ...
blok. Perhatikan bahwa dengan menggunakanMaybe
monad dando
notasi, hanya jalur keberhasilan yang ditentukan: semantikMaybe
monad secara implisit menyebarkan nilai kesalahan (Nothing
). Tidak ada overhead untuk programmer.sumber
Either
jenisnya akan lebih cocok. Apa yang kamu lakukan jika sampai diNothing
sini? Anda baru saja mendapatkan pesan "kesalahan". Tidak sangat membantu untuk debugging.Saya telah menjadi penggemar berat Pengecualian Tercatat dan saya ingin membagikan aturan umum saya tentang kapan harus menggunakannya.
Saya sampai pada kesimpulan bahwa pada dasarnya ada 2 jenis kesalahan yang harus ditangani kode saya. Ada kesalahan yang dapat diuji sebelum kode dijalankan dan ada kesalahan yang tidak dapat diuji sebelum kode dijalankan. Contoh sederhana untuk kesalahan yang dapat diuji sebelum kode dieksekusi di NullPointerException.
Tes sederhana bisa menghindari kesalahan seperti ...
Ada saat-saat dalam komputasi di mana Anda dapat menjalankan 1 tes atau lebih sebelum mengeksekusi kode untuk memastikan Anda aman DAN ANDA AKAN MENDAPATKAN PENGECUALIAN. Misalnya, Anda dapat menguji sistem file untuk memastikan ada cukup ruang disk pada hard drive sebelum Anda menulis data ke drive. Dalam sistem operasi multiprosesing, seperti yang digunakan saat ini, proses Anda dapat menguji ruang disk dan sistem file akan mengembalikan nilai dengan mengatakan ada ruang yang cukup, maka pergantian konteks ke proses lain dapat menulis byte tersisa yang tersedia untuk operasi tersebut sistem. Ketika konteks sistem operasi beralih kembali ke proses Anda berjalan di mana Anda menulis konten Anda ke disk, Pengecualian akan terjadi hanya karena tidak ada cukup ruang disk pada sistem file.
Saya menganggap skenario di atas sebagai kasus yang sempurna untuk Pengecualian yang Diperiksa. Ini merupakan pengecualian dalam kode yang memaksa Anda untuk berurusan dengan sesuatu yang buruk meskipun kode Anda dapat ditulis dengan sempurna. Jika Anda memilih untuk melakukan hal-hal buruk seperti 'menelan pengecualian', Anda adalah programmer yang buruk. Ngomong-ngomong, saya telah menemukan kasus-kasus di mana masuk akal untuk menelan pengecualian, tetapi tolong tinggalkan komentar dalam kode mengapa pengecualian itu tertelan. Mekanisme penanganan pengecualian tidak bisa disalahkan. Saya biasanya bercanda bahwa saya lebih suka alat pacu jantung saya ditulis dengan bahasa yang memiliki Pengecualian.
Ada kalanya menjadi sulit untuk memutuskan apakah kode tersebut dapat diuji atau tidak. Misalnya, jika Anda menulis penerjemah dan SyntaxException dilemparkan ketika kode gagal dieksekusi karena beberapa alasan sintaksis, haruskah SyntaxException menjadi Pengecualian yang Diperiksa atau (dalam Java) RuntimeException? Saya akan menjawab jika penerjemah memeriksa sintaks kode sebelum kode dieksekusi maka Pengecualian haruslah RuntimeException. Jika penerjemah hanya menjalankan kode 'panas' dan hanya menemukan kesalahan Sintaks, saya akan mengatakan pengecualian harus menjadi Pengecualian yang Diperiksa.
Saya akan mengakui bahwa saya tidak selalu senang harus menangkap atau melempar Pengecualian Tercatat karena ada waktu di mana saya tidak yakin apa yang harus dilakukan. Pengecualian yang Diperiksa adalah cara untuk memaksa programmer untuk memperhatikan potensi masalah yang dapat terjadi. Salah satu alasan mengapa saya memprogram di Jawa adalah karena ia telah Memeriksa Pengecualian.
sumber
Saya saat ini di tengah-tengah proyek / API berbasis OOP yang agak besar dan saya telah menggunakan tata letak pengecualian ini. Tapi itu semua benar-benar tergantung dari seberapa dalam Anda ingin pergi dengan penanganan pengecualian dan sejenisnya.
ExpectedException
- AuthorisedException
- EmptySetException
- NoRemainingException
- NoRowsException
- NotFoundException
- ValidationException
UnexpectedException
- ConnectivityException
- EnvironmentException
- ProgrammerException
- SQLException
CONTOH
sumber
NAN
atauNULL
.