Kapan menggunakan pernyataan dan kapan menggunakan pengecualian

121

Sebagian besar waktu saya akan menggunakan pengecualian untuk memeriksa kondisi dalam kode saya, saya bertanya-tanya kapan waktu yang tepat untuk menggunakan pernyataan?

Misalnya,

Group group=null;
try{
    group = service().getGroup("abc");
}catch(Exception e){
    //I dont log error because I know whenever error occur mean group not found
}

if(group !=null)
{
    //do something
}

Bisakah Anda menunjukkan bagaimana pernyataan cocok di sini? Haruskah saya menggunakan pernyataan?

Sepertinya saya tidak pernah menggunakan pernyataan dalam kode produksi dan hanya melihat pernyataan dalam pengujian unit. Saya tahu bahwa dalam banyak kasus, saya hanya dapat menggunakan pengecualian untuk melakukan pemeriksaan seperti di atas, tetapi saya ingin tahu cara yang tepat untuk melakukannya "secara profesional".

cometta
sumber

Jawaban:

81

Pernyataan harus digunakan untuk memeriksa sesuatu yang seharusnya tidak pernah terjadi, sementara pengecualian harus digunakan untuk memeriksa sesuatu yang mungkin terjadi.

Misalnya, suatu fungsi mungkin membagi dengan 0, jadi pengecualian harus digunakan, tetapi pernyataan dapat digunakan untuk memeriksa bahwa hard drive tiba-tiba menghilang.

Sebuah pernyataan akan menghentikan program dari berjalan, tapi pengecualian akan membiarkan program terus berjalan.

Perhatikan bahwa if(group != null)itu bukan pernyataan, itu hanya bersyarat.

Marius
sumber
3
"sebuah pernyataan dapat digunakan untuk memeriksa bahwa hard drive tiba-tiba menghilang" - menurut saya ini tidak benar: mengapa Anda ingin ini ditangani selama pengembangan, tetapi tidak dalam produksi (ketika pernyataan biasanya dinonaktifkan)?
herman
71
Komentar tentang hard drive salah. Pernyataan adalah untuk memeriksa kesalahan dalam logika kode Anda. Jangan pernah, gunakan mereka untuk memeriksa sesuatu yang tidak Anda kendalikan. Ingat, jika pernyataan gagal, itu berarti kode Anda salah .
Ian Goldby
1
@Marius Kondisional Anda dapat diganti dengan pernyataan seperti ini: grup pernyataan! = Null
IgorGanapolsky
1
Tidak disukai karena contoh hard drive bertentangan dengan filosofi Anda. Hard drive "menghilang" (dari perspektif kode) sebenarnya bisa terjadi dalam kenyataan - tidak peduli betapa mustahilnya. Seperti yang dikatakan @IanGoldby, pernyataan harus sepenuhnya bergantung pada hal-hal yang dikontrol oleh kode Anda.
Vicky Chijwani
Jawaban yang jauh lebih baik jika diposting oleh Gregory Pakosz, silakan baca posting itu.
ormurin
169

Keluar dari pikiran saya (daftar mungkin tidak lengkap, dan terlalu panjang untuk memuat komentar), saya akan mengatakan:

  • gunakan pengecualian saat memeriksa parameter yang diteruskan ke metode dan konstruktor publik atau dilindungi
  • gunakan pengecualian saat berinteraksi dengan pengguna atau saat Anda mengharapkan kode klien pulih dari situasi luar biasa
  • gunakan pengecualian untuk mengatasi masalah yang mungkin terjadi
  • gunakan pernyataan saat memeriksa prakondisi, pascakondisi, dan invarian kode pribadi / internal
  • gunakan pernyataan untuk memberikan umpan balik kepada diri Anda sendiri atau tim pengembang Anda
  • gunakan pernyataan saat memeriksa hal-hal yang sangat tidak mungkin terjadi, sebaliknya itu berarti ada kesalahan serius dalam aplikasi Anda
  • gunakan pernyataan untuk menyatakan hal-hal yang Anda (seharusnya) ketahui benar

Dengan kata lain, pengecualian menangani ketahanan aplikasi Anda sementara pernyataan membahas kebenarannya.

Assertion dirancang agar murah untuk ditulis, Anda dapat menggunakannya hampir di mana saja dan saya menggunakan aturan praktis ini: semakin pernyataan pernyataan terlihat bodoh, semakin berharga dan semakin banyak informasi yang disematkan. Saat men-debug program yang berperilaku tidak benar, Anda pasti akan memeriksa kemungkinan kegagalan yang lebih jelas berdasarkan pengalaman Anda. Kemudian Anda akan memeriksa masalah yang tidak dapat terjadi: ini tepatnya ketika pernyataan sangat membantu dan menghemat waktu.

Gregory Pakosz
sumber
53
Saya suka cara Anda mengutarakan ini: Pengecualian menangani ketahanan aplikasi Anda sementara pernyataan membahas kebenarannya .
M. Dudley
Saya mengirim silang ini ke situs saya: pempek.net/articles/2013/11/16/assertions-or-exceptions
Gregory Pakosz
Dan jika Anda kebetulan mencari pustaka pernyataan
Gregory Pakosz
26

Ingat pernyataan dapat dinonaktifkan saat runtime menggunakan parameter, dan dinonaktifkan secara default , jadi jangan mengandalkannya kecuali untuk tujuan debugging.

Anda juga harus membaca artikel Oracle tentang assert untuk melihat lebih banyak kasus di mana menggunakan - atau tidak menggunakan - assert.

chburd
sumber
Hue hue hue Saya bertanya-tanya mengapa kode saya gagal di Eclipse tetapi berjalan dengan baik pada baris perintah.
Steve
15

Sebagai aturan umum:

  • Gunakan pernyataan untuk pemeriksaan konsistensi internal di mana tidak masalah sama sekali jika seseorang mematikannya. (Perhatikan bahwa javaperintah mematikan semua pernyataan secara default.)
  • Gunakan tes reguler untuk semua jenis pemeriksaan yang tidak boleh dimatikan. Ini termasuk pemeriksaan defensif yang melindungi dari potensi kerusakan yang disebabkan oleh bug, dan setiap data / permintaan validasi / apa pun yang disediakan oleh pengguna atau layanan eksternal.

Kode berikut dari pertanyaan Anda adalah gaya yang buruk dan berpotensi bermasalah

try {
    group = service().getGroup("abc");
} catch (Exception e) {
    //i dont log error because i know whenever error occur mean group not found
}

Masalahnya adalah Anda TIDAK tahu bahwa pengecualian berarti grup tidak ditemukan. Mungkin juga service()panggilan tersebut melontarkan pengecualian, atau muncul kembali nullyang kemudian menyebabkan a NullPointerException.

Saat Anda menemukan pengecualian "yang diharapkan", Anda harus menangkap hanya pengecualian yang Anda harapkan. Dengan menangkap java.lang.Exception(dan terutama dengan tidak mencatatnya), Anda mempersulit untuk mendiagnosis / men-debug masalah, dan berpotensi memungkinkan aplikasi melakukan lebih banyak kerusakan.

Stephen C
sumber
4

Nah, kembali ke Microsoft, rekomendasinya adalah untuk membuang Pengecualian di semua API yang Anda sediakan untuk umum dan menggunakan Asserts dalam segala macam asumsi yang Anda buat tentang kode yang bersifat internal. Ini sedikit definisi yang longgar tetapi saya kira itu tergantung pada masing-masing pengembang untuk menarik garis.

Mengenai penggunaan Pengecualian, seperti namanya, penggunaannya harus luar biasa sehingga untuk kode yang Anda tunjukkan di atas, getGrouppanggilan akan ditampilkan nulljika tidak ada layanan. Pengecualian seharusnya hanya terjadi jika tautan jaringan mati atau semacamnya.

Saya kira kesimpulannya adalah bahwa itu sedikit diserahkan kepada tim pengembangan untuk setiap aplikasi untuk menentukan batas-batas pernyataan vs pengecualian.

rui
sumber
IMHO, masalah dengan rekomendasi semacam itu adalah tidak masalah selama batas antara bagian publik dan pribadi dari API cukup diperbaiki. Jika Anda mengembangkan kode baru maka batasan itu sering kali berubah
ubah
Ya kau benar. Ini adalah pedoman tetapi pada akhirnya hal itu diserahkan kepada kepekaan pemrogram. Saya tidak berpikir ada garis yang menentukan untuk ini jadi saya rasa Anda hanya pergi dengan apa yang menurut Anda benar dari membaca banyak kode yang berbeda.
rui
3

Menurut dokumen ini http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#design-faq-general , "Pernyataan tegas sesuai untuk prasyarat nonpublik, kondisi pascakondisi, dan invarian kelas pemeriksaan. Pemeriksaan prakondisi publik harus tetap dilakukan dengan pemeriksaan di dalam metode yang menghasilkan pengecualian terdokumentasi tertentu, seperti IllegalArgumentException dan IllegalStateException. "

Jika Anda ingin mengetahui lebih banyak tentang prekondisi, kondisi pos dan invarian kelas, periksa dokumen ini: http://docs.oracle.com/javase/6/docs/technotes/guides/language/assert.html#usage-conditions . Ini juga berisi contoh penggunaan pernyataan.

cesarsalgado
sumber
1

Menguji null hanya akan menangkap null yang menyebabkan masalah, sedangkan coba / tangkap seperti yang Anda lakukan akan mendeteksi error apa pun .

Secara umum, coba / tangkap lebih aman, tetapi sedikit lebih lambat, dan Anda harus berhati-hati agar menangkap semua jenis kesalahan yang mungkin terjadi. Jadi saya akan mengatakan gunakan try / catch - suatu hari kode getGroup dapat berubah, dan Anda mungkin membutuhkan jaring yang lebih besar itu.

Phil H.
sumber
1

Anda dapat menggunakan perbedaan sederhana ini dalam pikiran saat menggunakannya. Pengecualian akan digunakan untuk memeriksa kesalahan yang diharapkan dan tidak terduga yang disebut kesalahan diperiksa dan tidak dicentang sementara pernyataan digunakan terutama untuk tujuan debugging pada waktu proses untuk melihat apakah asumsi divalidasi atau tidak.

SBTec
sumber
1

Saya akui saya agak bingung dengan pertanyaan Anda. Jika kondisi pernyataan tidak terpenuhi, pengecualian akan dilemparkan. Yang membingungkan, ini disebut AssertionError . Perhatikan bahwa ini tidak dicentang, seperti (misalnya) IllegalArgumentException yang muncul dalam keadaan yang sangat mirip.

Jadi menggunakan pernyataan di Java

  1. adalah cara yang lebih ringkas untuk menulis kondisi / blok lemparan
  2. memungkinkan Anda untuk mengaktifkan / menonaktifkan pemeriksaan ini melalui parameter JVM. Biasanya saya akan membiarkan pemeriksaan ini terus menerus, kecuali hal itu berdampak pada kinerja runtime atau memiliki penalti serupa.
Brian Agnew
sumber
AssertionError adalah subclass dari Error bukan RuntimeException.
Stephen C
Ah. Tentu saja. Saya berpikir untuk dicentang / tidak dicentang. Sekarang dikoreksi
Brian Agnew
Ini menjelaskan apa pernyataan itu (dari sudut pandang kontroversial), tetapi tidak kapan harus menggunakannya dengan tepat.
Karl Richter
1

Lihat bagian 6.1.2 (Pernyataan vs. kode kesalahan lainnya) dari dokumentasi Sun di tautan berikut.

http://www.oracle.com/technetwork/articles/javase/javapch06.pdf

Dokumen ini memberikan saran terbaik yang pernah saya lihat tentang kapan harus menggunakan pernyataan. Mengutip dari dokumen:

"Aturan praktis yang baik adalah Anda harus menggunakan pernyataan untuk kasus luar biasa yang ingin Anda lupakan. Penegasan adalah cara tercepat untuk menangani, dan melupakan, suatu kondisi atau keadaan yang tidak Anda harapkan akan terjadi. berurusan dengan."

Phil
sumber
0

Sayangnya menegaskan dapat dinonaktifkan. Saat dalam produksi, Anda membutuhkan semua bantuan yang bisa Anda peroleh saat melacak sesuatu yang tidak terduga, jadi tegas mendiskualifikasi diri.

Thorbjørn Ravn Andersen
sumber