Apakah ini bukan praktik yang baik untuk menangani pengecualian runtime dalam kode?

11

Saya sedang mengerjakan aplikasi Java, dan saya melihat bahwa Run time exception ditangani di banyak tempat. Sebagai contoh,

try {
    // do something
} catch(NullPointerException e) {
    return null;
}

Pertanyaan saya adalah, kapan itu praktik yang baik untuk menangani pengecualian Runtime? Kapan pengecualian harus dibiarkan tidak tertangani?

Vinoth Kumar CM
sumber
7
-1: Tidak ada jawaban tunggal untuk pertanyaan seluas dan kabur ini. Tidak mungkin memberikan jawaban tunggal untuk pertanyaan yang tidak fokus seperti ini. Pertanyaan ini mengerikan. Harap berikan contoh spesifik tempat Anda ragu.
S.Lott
@ S.Lott Saya agak tidak setuju dalam kasus ini karena tampaknya ada sebagian programmer yang memilikinya di kepala mereka bahwa ini adalah kasus tanpa Rasionalitas "Bagus".
SoylentGray
2
@Chad: "ini adalah kasus tanpa" Bagus "Rasionalitas". Itu mungkin benar. Tetapi satu-satunya jawaban yang mungkin adalah "itu tergantung". Karena itu, pertanyaannya kelihatannya salah.
S.Lott

Jawaban:

18

Tergantung.

Misalnya, Integer#parseIntmelempar NumberFormatException(yang merupakan RTE) jika string yang disediakan tidak dapat diuraikan. Tetapi tentunya Anda tidak ingin aplikasi Anda mogok hanya karena pengguna menulis "x" ke bidang teks yang untuk bilangan bulat? Dan bagaimana Anda tahu apakah string dapat diuraikan, kecuali jika Anda mencoba menguraikannya terlebih dahulu? Jadi dalam hal ini, RTE hanyalah sinyal kesalahan yang seharusnya menyebabkan beberapa jenis pesan kesalahan. Orang bisa berargumen bahwa itu harus menjadi pengecualian yang diperiksa, tetapi apa yang bisa Anda lakukan - tidak.

Joonas Pulakka
sumber
2
Saya setuju dengan "Itu tergantung", tetapi contoh parsing Anda tampaknya merupakan kasus desain API yang buruk. Integer#parseIntharus benar-benar mengembalikan Maybe<Integer>gantinya dan tidak membuang pengecualian sama sekali.
Jörg W Mittag
3
@ Jörg W Mittag: Saya setuju bahwa ini adalah desain API yang buruk, tapi ini adalah dunia nyata yang harus kita tangani. Cara menangani nilai throwables / return dengan benar tergantung pada bagaimana dunia sebenarnya bekerja, bukan pada bagaimana seharusnya bekerja secara optimal :-)
Joonas Pulakka
Intinya di sini adalah, Anda dapat melakukan sesuatu yang bermakna untuk kondisi yang diantisipasi (input pengguna tidak integer). Menelan NPE adalah gaya yang buruk dan hanya akan menutupi kesalahan pemrograman yang ada.
Jürgen Strobel
7

NullPointerExceptions biasanya merupakan tanda dari cek nol yang hilang. Jadi, alih-alih menangkapnya seperti ini, Anda harus menambahkan tanda centang nol yang sesuai untuk memastikan tidak membuang pengecualian.

Tetapi kadang-kadang, sangat tepat untuk menangani RunTimeExceptions. Misalnya, ketika Anda tidak dapat mengubah kode untuk menambahkan cek nol di tempat yang sesuai, atau ketika pengecualian adalah sesuatu selain NullPointerException.

Contoh Anda dalam menangani pengecualian sangat buruk. Dengan melakukannya, Anda kehilangan jejak tumpukan dan informasi yang tepat tentang masalah tersebut. Dan Anda sebenarnya tidak menyelesaikannya karena Anda mungkin akan memicu NullPointerException lain di tempat yang berbeda, dan mendapatkan informasi yang menyesatkan tentang apa yang terjadi dan bagaimana menyelesaikannya.

deadalnix
sumber
1
Saya ingin menambahkan bahwa cek nol adalah keputusan yang lebih baik berdasarkan kinerja.
Mahmoud Hossam
... tetap saja, jika Anda membuat lusinan alokasi yang "seharusnya tidak pernah gagal" di satu tempat, menambahkan cek nol untuk masing-masingnya mungkin sangat mengaburkan kode. Pengecualian untuk semua (yang AKAN menangani situasi dengan anggun, bukan hanya return null;) akan menjadi solusi yang lebih baik.
SF.
Anda mungkin membingungkan java dengan sesuatu yang lain (C ++ untuk contoh). Ketika alokasi gagal, Anda mendapatkan OutOfMemoryError atau yang serupa, tidak pernah menjadi null pointer. Menekan pengembalian nol alih-alih pengecualian menyembunyikan kesalahan menunggu kode meledak di tempat lain.
deadalnix
newmelempar std::bad_allocdalam C ++.
R. Martinho Fernandes
Dengan asumsi bahwa operator baru tidak kelebihan beban, yang merupakan praktik umum. Dalam C ++, apa pun bisa terjadi;) Tapi OK, katakanlah C malloc. Poin penting adalah bahwa Anda tidak pernah mendapatkannya di java.
deadalnix
4

Saya menangani pengecualian yang diharapkan di mana saya mengharapkannya. (Seperti kesalahan baca / tulis DB). Pengecualian yang tidak terduga saya muncul. Di tempat lain mungkin mengharapkan pengecualian dan memiliki logika untuk itu.

SoylentGray
sumber
2

Pengecualian harus hanya itu .. pengecualian. Praktik terbaik ketika menggunakan pengecualian adalah menggunakannya untuk mencakup situasi di mana sesuatu yang bertentangan dengan apa yang Anda harapkan terjadi terjadi. Contoh klasik adalah FileNotFoundException yang dilemparkan ketika file tidak ada di sana. Jika Anda menguji keberadaan file, maka Anda menggunakan File.exists () karena Anda hanya mendorong dengan tongkat 10 kaki untuk melihat apakah Anda menabrak sesuatu.

Anda dapat secara teknis mencapai hasil yang sama dengan mengelilinginya dalam mencoba menangkap dan menggunakan file seolah-olah ada, tetapi A) pengecualian umumnya mahal sumber daya dan B) programmer akan menganggap Anda berarti file itu ada jika itu ada dalam try catch, yang menambah kebingungan keseluruhan suatu program.

Ada banyak situasi di mana saya akan menulis metode yang mengambil beberapa nilai dari database. Seribu hal bisa salah, dan melihat betapa saya hanya membutuhkan satu informasi kecil, tidak nyaman untuk mengelilingi panggilan dengan daftar coba coba yang berisi 5 pengecualian berbeda. Jadi, saya akan menangkap pengecualian dalam metode pengambilan. Jika terjadi kesalahan, saya mengambil tindakan apa pun yang sesuai untuk menutup koneksi database atau yang lainnya di klausa akhirnya dan mengembalikan nol. Ini adalah praktik yang baik tidak hanya karena menyederhanakan kode Anda tetapi juga karena "null" mengirim pesan yang sama dengan yang Anda dapatkan dari pengecualian .. bahwa ada sesuatu yang tidak berjalan sesuai rencana. Kelola spesifik pengecualian dalam metode pengambilan, tetapi kelola apa yang harus dilakukan ketika hal-hal tidak terjadi

Sebagai contoh:

Integer getUserCount() {
   Integer result = null;
   try {
      // Attempt to open database and retrieve data
   } catch (TimeoutException e) {
      logger.error("Got a watch?");
   } catch (MissingDatabaseException e) {
      logger.error("What are you smoking?");
   } catch (PermissionsToReadException e) {
      logger.error("Did you *really* think you were getting away with that?");
   } catch (PressedSendButtonToHardException e) {
      logger.error("Seriously.. just back away from the computer... slowly..");
   } catch (WTFException e) {
      logger.error("You're on your own with this one.. I don't even know what happened..");
   } finally {
      // Close connections and whatnot
   }
   return result;
}

void doStuff() {
   Integer result = getUserCount();
   if(result != null) {
       // Went as planned..
   }
}
Neil
sumber
6
Jika Anda menggunakan File.exists () dan mengandalkan hasilnya, kondisi balapan dapat terjadi jika file dihapus tepat antara File.exists () dan File.open (). Jika ini memicu bug keamanan-kritis, penyerang dapat menyebabkan kondisi ini dengan sengaja. Karena itu, kadang-kadang lebih baik menjaga operasi atom, yaitu mencobanya dan menangkap pengecualian.
user281377
1
Juga, ada file yang harus ada untuk menjalankan aplikasi. Itu akan menjadi kondisi yang luar biasa. Jika ada file yang harus Anda miliki agar aplikasi berfungsi, maka tidak ada alasan untuk tidak membacanya dan kemudian menangani pengecualian untuk case luar biasa. Saya percaya itu membuat niat lebih jelas.
Thomas Owens
Ini keputusan yang buruk untuk mengembalikan nol. Ini akan menghasilkan NullPointerException di beberapa titik dan akan sangat sulit untuk men-debug apa yang salah. Karena seseorang AKAN pada suatu titik melupakan cek nol.
deadalnix
@deadalnix: Saya bisa berpendapat bahwa Anda bisa dengan mudah lupa untuk mengelilingi dengan mencoba-menangkap sebaliknya. Perbedaan adalah masalah gaya, bukan fungsionalitas.
Neil
@ammoQ: Saya tidak setuju. Saya pikir Anda harus menggunakan File.exists () dan dalam keadaan langka itu akan dihapus sebelum Anda menggunakannya, pengecualian lebih dari tepat. Perbedaannya adalah di mana Anda menyimpan tangkapan Anda. Cukup minta selimut penangkap untuk kesalahan yang tidak terduga untuk mencatat dan melaporkannya.
Neil
-5

ya Anda benar menangani pengecualian run time bukan praktik yang baik. Alasannya adalah bahwa itu dianggap mahal / memori intensif.

prasoncala
sumber
5
Hai prassee, dapatkah Anda menjelaskan jawaban Anda? Satu kalimat yang tidak didukung dengan fakta, referensi, atau pengalaman tidak terlalu membantu.