Pengecualian Java diperiksa telah mendapat beberapa pers yang buruk selama bertahun-tahun. Pertanda jitu adalah bahwa itu adalah satu-satunya bahasa di dunia yang memilikinya (bahkan bahasa JVM lainnya seperti Groovy dan Scala). Pustaka Java yang terkenal seperti Spring dan Hibernate juga tidak menggunakannya.
Saya pribadi telah menemukan satu kegunaan untuk mereka ( dalam logika bisnis antar lapisan), tetapi selain itu saya pengecualian cukup anti-diperiksa.
Apakah ada kegunaan lain yang tidak saya sadari?
java
exceptions
errors
Brad Cupit
sumber
sumber
Jawaban:
Pertama-tama, seperti paradigma pemrograman lainnya, Anda perlu melakukannya dengan benar agar bisa berfungsi dengan baik.
Bagi saya keuntungan dari pengecualian yang diperiksa adalah bahwa penulis perpustakaan Java runtime SUDAH telah memutuskan untuk saya masalah umum apa yang mungkin dapat saya tangani secara wajar pada titik panggilan (sebagai lawan dari print-catch tingkat atas). mati blok) dan pertimbangkan sedini mungkin bagaimana menangani masalah ini.
Saya suka mengecek pengecualian karena mereka membuat kode saya lebih kuat dengan memaksa saya untuk berpikir tentang pemulihan kesalahan sedini mungkin.
Lebih tepatnya, bagi saya ini membuat kode saya lebih kuat karena memaksa saya untuk mempertimbangkan kasus sudut aneh sangat awal dalam proses yang bertentangan dengan mengatakan "Ups, kode saya tidak menangani jika file belum ada" berdasarkan kesalahan dalam produksi, yang kemudian harus Anda ulang kode Anda untuk menangani. Menambahkan penanganan kesalahan ke kode yang ada bisa menjadi tugas yang tidak sepele - dan karenanya mahal - ketika mencapai pemeliharaan dan bukan hanya melakukannya sejak awal.
Mungkin file yang hilang adalah hal yang fatal dan harus menyebabkan program crash, tetapi kemudian Anda membuat keputusan dengan
Ini juga menunjukkan efek samping yang sangat penting. Jika Anda membungkus pengecualian, Anda dapat menambahkan penjelasan yang masuk dalam tumpukan jejak ! Ini sangat kuat karena Anda dapat menambahkan informasi tentang mis. Nama file yang hilang, atau parameter yang diteruskan ke metode ini atau informasi diagnostik lainnya, dan informasi itu ada tepat di jejak tumpukan yang sering merupakan satu-satunya hal yang Anda dapatkan ketika sebuah program macet.
Orang-orang mungkin mengatakan "kita bisa menjalankan ini di debugger untuk mereproduksi", tetapi saya telah menemukan bahwa kesalahan produksi yang sangat sering tidak dapat direproduksi nanti, dan kami tidak dapat menjalankan debugger dalam produksi kecuali untuk kasus-kasus yang sangat buruk di mana pada dasarnya pekerjaan Anda dipertaruhkan.
Semakin banyak informasi dalam jejak tumpukan Anda, semakin baik. Pengecualian diperiksa membantu saya mendapatkan informasi itu di sana, dan lebih awal.
EDIT: Ini berlaku untuk perancang perpustakaan juga. Satu perpustakaan yang saya gunakan setiap hari berisi banyak, banyak pengecualian yang diperiksa yang bisa dirancang jauh lebih baik sehingga tidak terlalu membosankan untuk digunakan.
sumber
Anda punya dua jawaban bagus yang menjelaskan apa yang sudah menjadi pengecualian dalam praktik. (+1 untuk keduanya.) Tetapi akan bermanfaat untuk memeriksa apa yang dimaksudkan dalam teori, karena niat sebenarnya bermanfaat.
Pengecualian yang diperiksa sebenarnya dimaksudkan untuk membuat bahasa lebih aman. Pertimbangkan metode sederhana seperti perkalian integer. Anda mungkin berpikir bahwa tipe hasil dari metode ini adalah bilangan bulat, tetapi, sebenarnya, hasilnya adalah bilangan bulat atau pengecualian melimpah. Mempertimbangkan hasil integer dengan sendirinya karena tipe kembalinya metode tidak mengekspresikan rentang fungsi yang lengkap.
Dilihat dari sudut ini, tidak sepenuhnya benar untuk mengatakan bahwa pengecualian yang diperiksa belum menemukan jalan mereka ke bahasa lain. Mereka tidak mengambil bentuk yang digunakan Java. Dalam aplikasi Haskell, adalah umum untuk menggunakan tipe data aljabar untuk membedakan antara penyelesaian fungsi yang berhasil dan yang tidak berhasil. Meskipun ini bukan pengecualian, namun, tujuannya sangat mirip dengan pengecualian yang diperiksa; itu adalah API yang dirancang untuk memaksa konsumen API untuk menangani keduanya yang berhasil dalam kasus yang tidak berhasil, misalnya:
Ini memberi tahu programmer bahwa fungsi tersebut memiliki dua kemungkinan hasil tambahan selain keberhasilan.
sumber
IMO, pengecualian yang diperiksa adalah implementasi yang cacat dari apa yang mungkin merupakan ide yang cukup baik (dalam keadaan yang sama sekali berbeda - tetapi sebenarnya bukan ide yang baik di bawah situasi saat ini).
Ide yang bagus adalah akan lebih baik jika kompiler memverifikasi bahwa semua pengecualian yang berpotensi dibuang oleh suatu program akan tertangkap. Implementasi yang cacat adalah untuk melakukan itu, Java memaksa Anda untuk menangani pengecualian secara langsung di kelas apa pun yang memanggil apa pun yang dinyatakan untuk melemparkan pengecualian yang diperiksa. Salah satu ide paling mendasar (dan keuntungan) dari penanganan pengecualian adalah bahwa jika terjadi kesalahan, ini memungkinkan lapisan kode menengah yang tidak ada hubungannya dengan kesalahan tertentu, untuk sepenuhnya mengabaikan keberadaannya. Pengecualian yang diperiksa (seperti yang diterapkan di Jawa) tidak memungkinkan, sehingga menghancurkan keuntungan utama (utama?) Dari penanganan pengecualian untuk memulai.
Secara teori, mereka bisa membuat pengecualian yang diperiksa bermanfaat dengan menegakkannya hanya berdasarkan program-lebar - yaitu, sambil "membangun" program, membangun pohon dari semua jalur kontrol dalam program. Berbagai simpul di pohon akan diberi penjelasan dengan 1) pengecualian yang dapat mereka hasilkan, dan 2) pengecualian yang dapat mereka tangkap. Untuk memastikan programnya benar, Anda kemudian akan berjalan di pohon, memverifikasi bahwa setiap pengecualian yang dilemparkan pada tingkat mana pun di pohon itu ditangkap pada tingkat yang lebih tinggi di pohon.
Alasan mereka tidak melakukan itu (saya kira, bagaimanapun juga) adalah melakukan hal itu akan sangat sulit - pada kenyataannya, saya ragu ada orang yang menulis sistem build yang dapat melakukan itu untuk apa pun kecuali sangat sederhana (berbatasan dengan "mainan" ") bahasa / sistem. Untuk Java, hal-hal seperti pemuatan kelas dinamis menjadikannya lebih sulit daripada dalam banyak kasus lainnya. Lebih buruk lagi, (tidak seperti sesuatu seperti C) Java tidak (setidaknya biasanya) secara statis dikompilasi / dihubungkan ke executable. Itu berarti tidak ada dalam sistem yang benar-benar memiliki kesadaran global untuk bahkan mencoba melakukan penegakan semacam ini sampai pengguna akhir benar-benar mulai memuat program untuk menjalankannya.
Melakukan penegakan hukum pada saat itu tidak praktis karena beberapa alasan. Pertama-tama, bahkan paling banter itu akan memperpanjang waktu startup, yang sudah menjadi salah satu keluhan terbesar dan paling umum tentang Java. Kedua, untuk melakukan banyak hal baik, Anda benar-benar perlu mendeteksi masalah cukup awal untuk diperbaiki oleh seorang programmer. Ketika pengguna memuat program, sudah terlambat untuk melakukan banyak hal baik - satu-satunya pilihan Anda pada saat itu adalah mengabaikan masalah, atau menolak memuat / menjalankan program sama sekali, jika ada kemungkinan ada pengecualian itu tidak tertangkap.
Karena itu, pengecualian yang diperiksa lebih buruk daripada tidak berguna, tetapi desain alternatif untuk pengecualian yang diperiksa bahkan lebih buruk. Sedangkan ide dasar untuk pengecualian diperiksa tampaknya seperti yang baik, itu benar-benar tidak sangat baik, dan terjadi menjadi sangat cocok miskin untuk Java. Untuk sesuatu seperti C ++, yang biasanya dikompilasi / ditautkan ke dalam executable yang lengkap dengan tidak banyak seperti pemuatan kelas refleksi / dinamis, Anda akan memiliki peluang lebih kecil (walaupun, terus terang, bahkan kemudian menegakkannya dengan benar tanpa jenis kekacauan yang sama seperti yang mereka lakukan). saat ini penyebab di Jawa mungkin masih berada di luar keadaan terkini).
sumber
UnexpectedException
jenis yang berasal dariRuntimeException
. Perhatikan bahwa "melempar" dan "tidak berharap" tidak bertentangan; jikafoo
melemparBozException
dan meneleponbar
, itu tidak berarti ia berharapbar
untuk melemparBozException
.Mereka benar-benar bagus untuk programmer yang mengganggu dan mendorong pengecualian menelan. Setengah poin dari pengecualian adalah agar Anda memiliki cara standar yang waras untuk menangani kesalahan dan tidak harus berpikir tentang menyebarkan kondisi kesalahan yang tidak dapat Anda tangani secara eksplisit. (Default waras adalah bahwa jika Anda tidak pernah menangani kesalahan di mana pun dalam kode Anda, Anda telah secara efektif menyatakan bahwa hal itu tidak dapat terjadi, dan dibiarkan dengan keluar yang waras dan jejak tumpukan jika Anda salah.) Pengecualian pengecualian dikalahkan ini. Mereka merasa seperti harus secara eksplisit menyebarkan kesalahan dalam C.
sumber
throws FileNotFoundException
. Hard fix:catch (FileNotFoundException e) { throw RuntimeException(e); }
Saya pikir adil untuk mengatakan bahwa pengecualian yang dicek adalah sedikit percobaan yang gagal. Di mana mereka salah adalah bahwa mereka melanggar layering:
Pemisahan yang baik dari yang bersangkutan rusak, karena sekarang pengetahuan tentang kesalahan yang bisa saja terbatas pada A dan C sekarang harus tersebar di atas B.
Ada diskusi yang bagus pengecualian yang diperiksa di Wikipedia.
Dan Bruce Eckel juga memiliki artikel yang bagus . Berikut ini kutipannya:
Saya percaya untuk kasus C ++, jika semua metode memiliki
throws
klausa spesifikasi, maka Anda dapat memiliki beberapa optimasi yang bagus. Saya tidak percaya Java bisa memiliki kelebihan itu, karenaRuntimeExceptions
tidak diperiksa. JIT modern harus dapat mengoptimalkan kode dengan baik.Salah satu fitur bagus dari AspectJ adalah pelunakan pengecualian: Anda dapat mengubah pengecualian yang dicentang menjadi pengecualian yang tidak dicentang, khususnya untuk meningkatkan pelapisan.
Mungkin ironis bahwa Jawa mengalami semua masalah ini, padahal seharusnya bisa diperiksa
null
, yang mungkin jauh lebih berharga .sumber
Saya suka pengecualian.
Saya, bagaimanapun, terus-menerus bingung oleh penyalahgunaan mereka.
Jangan menggunakannya untuk penanganan aliran. Anda tidak ingin kode yang mencoba melakukan sesuatu dan menggunakan pengecualian sebagai pemicu untuk melakukan sesuatu yang lain sebagai gantinya karena Pengecualian adalah objek yang perlu dibuat dan menggunakan memori dll. Hanya karena Anda tidak dapat diganggu untuk menulis beberapa jenis if () periksa sebelum Anda melakukan panggilan. Itu hanya malas dan memberi Exception yang mulia nama yang buruk.
Jangan menelan mereka. Pernah. Dalam keadaan apapun. Sebagai minimum absolut Anda menempelkan sesuatu di file log Anda untuk menunjukkan bahwa Pengecualian terjadi. Mencoba melacak jalan Anda melalui kode yang menelan pengecualian adalah mimpi buruk. Sekali lagi, kutuk kalian para penelepon-terkecuali karena telah membuat Pengecualian yang perkasa menjadi jelek!
Perlakukan Pengecualian dengan topi OO Anda aktif. Buat objek Pengecualian Anda sendiri dengan hierarki yang berarti. Laporkan logika bisnis Anda dan pengecualian Anda bersama-sama. Saya biasanya menemukan bahwa jika saya mulai pada area baru dari suatu sistem saya akan menemukan kebutuhan untuk subkelas Pengecualian dalam setengah jam pengkodean jadi hari ini saya mulai dengan menulis kelas Pengecualian.
Jika Anda menulis bit kode 'frameworky', pastikan semua antarmuka awal Anda ditulis untuk membuang Pengecualian baru Anda di tempat yang sesuai ... dan pastikan coders Anda memiliki beberapa kode sampel di sekitar tempat yang harus dilakukan ketika kode mereka melempar IOException tetapi antarmuka yang mereka tulis ingin melemparkan 'ReportingApplicationException'.
Setelah Anda memahami cara membuat Pengecualian bekerja untuk Anda, Anda tidak akan pernah melihat ke belakang.
sumber
initCause
atau inisialisasi pengecualian dengan pengecualian yang menyebabkannya. Contoh: Anda memiliki utilitas I / O yang hanya membutuhkan pengecualian jika penulisan gagal. Namun, ada beberapa alasan mengapa penulisan bisa gagal (tidak bisa mendapatkan akses, kesalahan tulis, dll.) Lempar pengecualian khusus Anda dengan penyebabnya sehingga masalah asli tidak tertelan.Pengecualian yang diperiksa juga dalam ADA.
(Peringatan, posting ini mengandung kepercayaan yang sangat kuat yang mungkin Anda temui).
Pemrogram tidak suka dan mengeluh, atau menulis kode menelan pengecualian.
Pengecualian yang dicentang ada karena hal-hal tidak hanya gagal berfungsi, Anda dapat melakukan analisis mode / efek kegagalan dan menentukan ini terlebih dahulu.
Membaca file bisa gagal. Panggilan RPC bisa gagal. Jaringan IO bisa gagal. Data bisa salah diformat saat diuraikan.
"Jalan bahagia" untuk kode itu mudah.
Saya kenal seseorang di Universitas yang bisa menulis kode "jalan bahagia". Tak satu pun dari kasus tepi yang pernah bekerja. Saat ini ia mengerjakan Python untuk perusahaan sumber terbuka. Kata Nuff.
Jika Anda tidak ingin menangani pengecualian yang dicentang, apa yang sebenarnya Anda katakan adalah
Jadi pengecualian yang dicentang tidak akan disukai oleh programmer, karena itu berarti lebih banyak pekerjaan.
Tentu saja, orang lain mungkin menginginkan pekerjaan itu selesai.
Mereka mungkin menginginkan jawaban yang tepat bahkan jika server file gagal / USB stick mati.
Ini adalah kepercayaan aneh dalam komunitas pemrograman bahwa Anda harus menggunakan bahasa pemrograman yang membuat hidup Anda lebih mudah, yang Anda nikmati, ketika pekerjaan Anda adalah menulis perangkat lunak. Pekerjaan Anda adalah memecahkan masalah seseorang, tidak membiarkan Anda terlibat dalam improvisasi Jazz terprogram.
Jika Anda seorang programmer amatir (bukan pemrograman untuk uang), jangan ragu untuk memprogram dalam C # atau bahasa lain tanpa pengecualian. Heck, hentikan perantara dan program di Logo. Anda bisa menggambar pola-pola cantik di lantai dengan kura-kura.
sumber
Pengecualian yang dicek seharusnya mendorong orang untuk menangani kesalahan dekat dengan sumber yang ada. Semakin jauh dari sumbernya, semakin banyak fungsi telah berakhir di tengah berjalan, dan semakin besar kemungkinan bahwa sistem telah memasuki kondisi yang tidak konsisten. Selain itu, lebih mungkin bahwa Anda menangkap pengecualian yang salah secara tidak sengaja.
Sayangnya, orang cenderung mengabaikan pengecualian atau menambah spesifikasi lemparan yang semakin meningkat. Kedua hal ini melewatkan inti dari apa yang seharusnya dikecualikan dari pengecualian yang diperiksa. Mereka seperti mengubah kode prosedural untuk menggunakan banyak fungsi Getter dan Setter yang seharusnya menjadikannya OO.
Pada dasarnya, pengecualian yang dicentang berusaha membuktikan tingkat kebenaran tertentu dalam kode Anda. Gagasannya hampir sama dengan pengetikan statis, dalam hal ini mencoba untuk membuktikan bahwa hal-hal tertentu benar sebelum kode dijalankan. Masalahnya adalah bahwa semua bukti ekstra itu membutuhkan upaya dan apakah upaya itu berharga?
sumber