Tampaknya ada sejumlah kesepakatan bahwa pesan pengecualian harus berisi perincian yang bermanfaat .
Mengapa banyak pengecualian umum dari komponen sistem tidak mengandung detail yang berguna?
Beberapa contoh:
- NET
List
akses indeksArgumentOutOfRangeException
tidak tidak memberitahu saya nilai indeks yang diadili dan tidak sah, juga tidak memberitahu saya rentang diperbolehkan. - Pada dasarnya semua pesan pengecualian dari pustaka standar MSVC C ++ sama sekali tidak berguna (dengan nada yang sama seperti di atas).
- Pengecualian Oracle dalam .NET, memberi tahu Anda (diparafrasekan) "TABEL ATAU LIHAT tidak ditemukan", tetapi tidak yang mana .
Jadi, bagi saya tampaknya sebagian besar pesan pengecualian tidak berisi rincian yang cukup untuk berguna. Apakah harapan saya di luar batas? Apakah saya menggunakan pengecualian yang salah sehingga saya perhatikan ini? Atau mungkin kesan saya salah: mayoritas pengecualian benar - benar memberikan detail yang berguna?
c#
c++
exceptions
Martin Ba
sumber
sumber
Jawaban:
Pengecualian tidak mengandung perincian yang berguna karena konsep pengecualian belum cukup matang dalam disiplin rekayasa perangkat lunak, sehingga banyak programmer tidak memahaminya sepenuhnya, dan oleh karena itu mereka tidak memperlakukannya dengan baik.
Ya,
IndexOutOfRangeException
harus berisi indeks tepat yang berada di luar jangkauan, serta kisaran yang valid pada saat dilempar, dan itu hina atas nama pencipta runtime .NET yang tidak. Ya,table or view not found
pengecualian Oracle harus berisi nama tabel atau tampilan yang tidak ditemukan, dan lagi, fakta bahwa itu tidak dapat dihina atas nama siapa pun yang bertanggung jawab untuk ini.Sebagian besar, kebingungan berasal dari ide asli yang salah arah bahwa pengecualian harus mengandung pesan yang dapat dibaca manusia, yang pada gilirannya berasal dari kurangnya pemahaman tentang apa yang dimaksud dengan pengecualian, sehingga merupakan lingkaran setan.
Karena orang berpikir bahwa pengecualian harus mengandung pesan yang dapat dibaca manusia, mereka percaya bahwa informasi apa pun yang dibawa oleh pengecualian juga harus diformat ke dalam pesan yang dapat dibaca manusia, dan kemudian mereka bosan untuk menulis semua pesan yang dapat dibaca manusia- membuat kode, atau mereka takut melakukan hal itu akan membocorkan informasi yang tidak disarankan kepada mata yang memandangi pesan itu. (Masalah keamanan disebutkan oleh jawaban lain.)
Tetapi kebenaran dari masalah ini adalah bahwa mereka tidak perlu khawatir tentang itu karena pengecualian tidak boleh mengandung pesan yang bisa dibaca manusia. Pengecualian adalah hal-hal yang hanya harus dilihat dan / atau ditangani oleh programmer. Jika ada kebutuhan untuk menyajikan informasi kegagalan kepada pengguna, itu harus dilakukan pada tingkat yang sangat tinggi, dengan cara yang canggih, dan dalam bahasa pengguna, yang, secara statistik, tidak mungkin berbahasa Inggris.
Jadi, bagi kita programmer, "pesan" pengecualian adalah nama kelas pengecualian , dan apa pun informasi lain yang berkaitan dengan pengecualian harus disalin ke variabel anggota (terakhir / hanya baca) dari objek pengecualian. Lebih disukai, setiap hal dapat dibayangkan. Dengan cara ini, tidak ada pesan yang perlu (atau harus) dihasilkan, dan karenanya tidak ada mata yang mengintip yang bisa melihatnya.
Untuk mengatasi kekhawatiran yang diungkapkan oleh Thomas Owens dalam komentar di bawah:
Ya, tentu saja, pada tingkat tertentu, Anda akan membuat pesan log tentang pengecualian. Tapi Anda sudah melihat masalah dengan apa yang Anda katakan: di satu sisi, pesan log pengecualian tanpa jejak tumpukan tidak berguna, tetapi di sisi lain, Anda tidak ingin membiarkan pengguna melihat seluruh jejak jejak pengecualian. Sekali lagi, masalah kita di sini adalah bahwa perspektif kita condong oleh praktik tradisional. File log secara tradisional dibuat dalam teks biasa, yang mungkin baik-baik saja ketika disiplin kita masih dalam masa pertumbuhan, tetapi mungkin tidak lagi: jika ada masalah keamanan, maka file log harus berupa biner dan / atau dienkripsi.
Apakah biner atau teks biasa, file log harus dianggap sebagai aliran ke mana aplikasi membuat serial informasi debug. Aliran seperti itu hanya untuk mata programmer, dan tugas menghasilkan informasi debug untuk pengecualian harus sesederhana serialisasi pengecualian ke dalam stream log debug. Dengan cara ini, dengan melihat log Anda bisa melihat nama kelas pengecualian, (yang, seperti telah saya sebutkan, adalah untuk semua tujuan praktis "pesan",) masing-masing variabel anggota pengecualian yang menggambarkan segala sesuatu yang berkaitan - dan-praktis-untuk-memasukkan-dalam-log, dan seluruh jejak tumpukan. Perhatikan bagaimana pemformatan pesan pengecualian yang dapat dibaca manusia jelas hilang dari proses ini.
PS
Beberapa pemikiran saya mengenai hal ini dapat ditemukan dalam jawaban ini: Cara menulis pesan pengecualian yang baik
PPS
Tampaknya banyak orang dicentang oleh saran saya tentang file log biner, jadi saya mengubah jawaban sekali lagi untuk membuatnya lebih jelas bahwa apa yang saya sarankan di sini bukanlah bahwa file log harus biner, tetapi itu file log mungkin biner, jika perlu.
sumber
Dalam pengalaman saya, ada sejumlah alasan bahwa pengecualian tidak mengandung informasi yang berguna. Saya berharap bahwa alasan semacam ini juga berlaku untuk komponen sistem - tetapi saya tidak tahu pasti.
Agak? Maksud saya, pengecualian harus memiliki pesan yang bagus, tetapi mereka juga pengecualian . Anda harus menghabiskan waktu merancang kode untuk menghindari kondisi luar biasa, atau menulis kode untuk menangani kondisi luar biasa (mengabaikan pesan), tidak menggunakannya sebagai semacam mekanisme umpan balik interaktif saat pengkodean. Tidak dapat dihindari untuk menggunakannya untuk tujuan debugging, tetapi dalam sebagian besar situasi yang harus dijaga agar tetap minimum. Bahwa Anda memperhatikan masalah ini membuat saya khawatir bahwa Anda tidak melakukan pekerjaan yang cukup baik untuk mencegah mereka.
sumber
Saya tidak memiliki kelebihan pengalaman C #, atau C ++ secara khusus, tetapi saya dapat memberitahu Anda ini - pengecualian yang ditulis pengembang 9 dari 10 kali lebih berguna daripada pengecualian umum yang pernah Anda temukan, titik.
Idealnya ya, pengecualian umum akan mengarahkan Anda ke persis mengapa kesalahan terjadi dan Anda akan dapat memperbaikinya dengan mudah - tetapi secara realistis, dalam aplikasi besar dengan beberapa kelas yang dapat melempar berbagai macam pengecualian, atau sama jenis pengecualian, itu selalu lebih berharga untuk menulis output Anda sendiri untuk kesalahan kembali daripada mengandalkan pesan default.
Begitulah seharusnya, karena sebagaimana banyak orang tunjukkan, beberapa aplikasi tidak ingin melemparkan pesan kesalahan yang mereka tidak ingin dilihat oleh pengguna, karena alasan keamanan atau untuk menghindari membingungkan mereka.
Sebagai gantinya, Anda harus mengantisipasi dalam desain Anda apa jenis kesalahan yang mungkin dilemparkan ke dalam aplikasi Anda (dan akan selalu ada kesalahan) dan menulis pesan-pesan yang menangkap kesalahan yang membantu Anda mengidentifikasi masalah.
Ini tidak akan selalu membantu Anda - karena Anda tidak dapat selalu mengantisipasi pesan kesalahan apa yang akan berguna - tetapi ini adalah langkah pertama untuk memahami aplikasi Anda sendiri dengan lebih baik dalam jangka panjang.
sumber
Pertanyaannya adalah secara khusus menanyakan mengapa begitu banyak pengecualian yang dilemparkan oleh "komponen sistem" (alias kelas pustaka standar) tidak mengandung detail yang berguna.
Sayangnya, sebagian besar pengembang tidak menulis komponen inti di perpustakaan standar, juga tidak ada dokumen desain terperinci atau alasan desain lainnya yang harus dipublikasikan. Dengan kata lain, kita mungkin tidak pernah tahu pasti.
Namun, ada dua poin utama yang perlu diingat mengapa informasi pengecualian terperinci mungkin tidak diinginkan atau penting:
Pengecualian dapat digunakan dengan memanggil kode dengan cara apa pun: perpustakaan standar tidak dapat menempatkan batasan tentang bagaimana pengecualian digunakan. Secara khusus, ini dapat ditampilkan kepada pengguna. Pertimbangkan indeks array di luar batas: ini dapat memberikan informasi yang berguna bagi penyerang. Perancang bahasa tidak tahu bagaimana aplikasi akan menggunakan pengecualian yang dilemparkan atau bahkan apa jenis aplikasi itu (misalnya aplikasi web atau desktop), sehingga meninggalkan informasi mungkin lebih aman dari perspektif keamanan.
Pengecualian tidak boleh ditampilkan kepada pengguna. Sebagai gantinya, tampilkan pesan kesalahan yang ramah dan catat pengecualian ke lokasi yang tidak dapat diakses oleh penyerang (jika ada). Setelah kesalahan diidentifikasi, pengembang harus melakukan debug melalui kode, memeriksa frame stack dan jalur logika. Pada titik ini, pengembang memiliki lebih banyak informasi daripada yang bisa diharapkan oleh pengecualian.
sumber
Pertama, izinkan saya memecahkan gelembung dengan mengatakan bahkan jika pesan diag dimuat dengan informasi yang membawa Anda ke baris kode dan perintah sub yang tepat dalam 4 detik, kemungkinan para pengguna tidak akan pernah menuliskannya atau menyampaikannya kepada orang-orang yang mendukung dan Anda akan diberitahu "Yah itu mengatakan sesuatu tentang pelanggaran ... Saya tidak tahu itu terlihat rumit!"
Saya telah menulis perangkat lunak dan mendukung hasil perangkat lunak orang lain selama lebih dari 30 tahun sekarang, dan secara pribadi, kualitas pesan pengecualian saat ini hampir tidak ada hubungannya dengan keamanan, terlepas dari bagaimana hasil akhirnya terjadi sesuai dengan model mereka. alam semesta, yang lebih berkaitan dengan fakta bahwa begitu banyak di industri kami yang awalnya belajar sendiri, dan mereka tidak pernah memasukkan pelajaran dalam komunikasi. Mungkin jika kita MEMINDAHKAN semua coders baru ke posisi pemeliharaan selama beberapa tahun di mana mereka harus berurusan dengan mencari tahu apa yang salah, mereka akan memahami pentingnya setidaknya beberapa bentuk presisi.
Baru-baru ini dalam aplikasi yang sedang dibangun kembali, keputusan dibuat bahwa kode kembali akan jatuh ke dalam salah satu dari tiga kelompok:
(100 karena beberapa alasan ditinggalkan)
Dalam alur kerja tertentu, pemikiran kami digunakan kembali atau kode generik akan menggunakan pengembalian generik (> 199) untuk kesalahan fatal, membuat kami memiliki 100 kesalahan fatal yang mungkin untuk alur kerja. Dengan sedikit membedakan data dalam pesan, kesalahan seperti file tidak ditemukan semua bisa menggunakan kode yang sama dan membedakan dengan pesan.
Ketika kode kembali dari kontraktor, Anda tidak akan percaya kejutan kami ketika hampir SETIAP KESALAHAN FATAL TUNGGAL adalah kode pengembalian 101.
Semua yang dianggap saya pikir jawaban untuk pertanyaan Anda adalah pesan-pesan itu sangat tidak berarti karena ketika awalnya dibuat, mereka harus menjadi penampung yang tidak ada yang kembali. Akhirnya orang menemukan cara untuk memperbaiki masalah bukan karena pesan tetapi DISPITE mereka.
Sejak saat itu, orang-orang yang belajar mandiri tidak pernah memiliki contoh yang baik tentang apa yang harus dikandung pengecualian. Tambahkan ke bahwa lebih banyak pengguna tidak membaca pesan, apalagi mencoba untuk meneruskannya ke dukungan (Saya telah melihat pesan kesalahan yang terpotong-potong oleh yang digunakan yang kemudian dihapus sebelum dikirim dengan komentar kemudian bahwa itu sepertinya banyak informasi dan saya tidak mungkin menginginkan semuanya, jadi mereka secara acak menghapus banyak informasi.
Dan mari kita hadapi itu, dengan terlalu banyak (tidak semua tetapi terlalu banyak) dari generasi coders berikutnya, jika itu lebih banyak pekerjaan dan tidak menambahkan flash, hanya saja tidak layak ...
Catatan terakhir: Jika pesan kesalahan menyertakan kode kesalahan / pengembalian, bagi saya tampaknya di suatu tempat dalam modul yang dieksekusi harus ada baris yang bertuliskan "jika kondisi mengembalikan nilai-kode" dan kondisi harus memberi tahu Anda mengapa kode pengembalian terjadi. Ini sepertinya pendekatan logis yang sederhana, tetapi bagi saya, coba saja agar Microsoft memberi tahu Anda apa yang terjadi ketika pemutakhiran windows gagal pada KODE 80241013 atau pengidentifikasi unik lainnya. Agak sedih, bukan?
sumber
chances are the users will never write it down... and you will be told "Well it said something about a violation..."
Inilah sebabnya mengapa Anda menggunakan alat pencatatan pengecualian untuk secara otomatis menghasilkan laporan kesalahan yang berisi jejak tumpukan dan bahkan mungkin mengirimnya ke server Anda. Saya punya satu pengguna satu kali yang tidak terlalu teknis. Setiap kali dia akan mengirim pesan dari kesalahan logger, itu akan menjadi sesuatu seperti "Saya tidak yakin apa yang saya lakukan salah, tapi ..." tidak peduli berapa kali saya menjelaskan bahwa kesalahan ini berarti bug ada di pihak saya . Tapi, saya selalu mendapat laporan kesalahan darinya!Sementara saya setuju bahwa pengecualian harus mengandung informasi sebanyak mungkin, atau setidaknya kurang generik. Dalam kasus tabel tidak ditemukan, nama tabel akan menyenangkan.
Tetapi Anda tahu lebih banyak tentang apa yang Anda coba lakukan di tempat dalam kode tempat Anda menerima pengecualian. Meskipun Anda sering benar-benar tidak dapat berbuat banyak untuk memperbaiki situasi ketika ada yang tidak beres di perpustakaan di luar kendali Anda, Anda dapat menambahkan informasi yang jauh lebih berguna tentang situasi di mana ada masalah.
Dalam kasus tabel tidak ditemukan, itu tidak akan banyak membantu Anda jika Anda diberitahu bahwa tabel yang tidak dapat ditemukan disebut SISWA, karena Anda tidak memiliki tabel seperti itu, dan string itu tidak ada dalam kode Anda.
Tetapi jika Anda menangkap pengecualian dan mengolahnya kembali dengan pernyataan SQL yang Anda coba jalankan, Anda akan lebih baik, karena ternyata Anda mencoba memasukkan catatan dengan bidang nama adalah Robert '); MAHASISWA TABEL DROP; (Selalu ada xkcd!)
Jadi, untuk memerangi perkecualian yang kurang informatif: cobalah menangkap kembali dengan lebih banyak informasi spesifik tentang apa yang Anda coba lakukan.
Saya mungkin harus menambahkan, agar ini lebih sebagai jawaban mengapa dalam pertanyaan itu, bahwa kemungkinan alasan mengapa fokus dari para pembuat perpustakaan belum membuat pesan pengecualian lebih baik, adalah bahwa mereka tidak tahu mengapa sesuatu telah dicoba gagal, logika itu ada dalam kode panggilan.
sumber
throw_with_nested
banyak menggunakan .Untuk memberikan jawaban yang sedikit berbeda: Kode yang menyinggung mungkin telah dilakukan untuk menyatakan:
Tambahkan tekanan untuk mengirim tepat ke spec (karena takut ditolak dalam peninjauan / pengujian) dalam waktu minimum dan dengan keributan minimum, maka Anda memiliki resep untuk pengecualian perpustakaan yang sepenuhnya sesuai dan tidak membantu.
sumber
Pengecualian memiliki biaya khusus bahasa dan implementasi.
Sebagai contoh, pengecualian C ++ diperlukan untuk menghancurkan semua data yang hidup antara melempar bingkai panggilan dan menangkap bingkai panggilan, dan itu mahal. Oleh karena itu, programmer tidak ingin banyak menggunakan pengecualian.
Di Ocaml, pengecualian melempar hampir secepat C
setjmp
(biayanya tidak tergantung pada jumlah frame panggilan yang dilalui), sehingga pengembang dapat menggunakannya banyak (bahkan untuk kasus yang tidak luar biasa, sangat umum,). Sebaliknya, pengecualian C ++ cukup berat sehingga Anda mungkin tidak akan sering menggunakannya seperti di Ocaml.Contoh khas adalah beberapa pencarian atau eksplorasi rekursif yang dapat "dihentikan" di dalam rekursi yang cukup dalam (mis. Menemukan daun di pohon, atau fungsi penyatuan). Dalam beberapa bahasa lebih cepat (jadi lebih idiomatis) untuk menyebarkan kondisi itu ke setiap penelepon. Dalam bahasa lain, melempar pengecualian lebih cepat.
Jadi tergantung pada bahasa (dan kebiasaan pengembang menggunakannya), pengecualian dapat membawa banyak detail yang berguna, atau sebaliknya digunakan sebagai lompatan non-lokal cepat dan hanya membawa data yang sangat berguna.
sumber
Apa yang membuat Anda berpikir nilai indeks atau rentang yang diperlukan atau nama tabel adalah detail yang berguna, sebagai pengecualian?
Pengecualian bukanlah mekanisme penanganan kesalahan; mereka adalah mekanisme pemulihan .
Tujuan dari pengecualian adalah untuk menggembungkan ke tingkat kode yang dapat menangani pengecualian. Di mana pun level itu, baik Anda memiliki informasi yang dibutuhkan, atau itu tidak relevan. Jika ada informasi yang Anda butuhkan, tetapi tidak memiliki akses langsung ke, Anda tidak menangani pengecualian di tingkat yang sesuai.
Satu kali saya bisa memikirkan di mana informasi tambahan dapat membantu adalah pada tingkat atas absolut aplikasi Anda di mana Anda crash dan memancarkan dump kesalahan; tetapi itu bukan tugas pengecualian untuk mengakses, menyusun dan menyimpan informasi ini.
Saya tidak mengatakan bahwa Anda bisa meletakkan "lempar Pengecualian baru" di mana-mana dan menyebutnya baik, adalah mungkin untuk menulis pengecualian yang buruk. Tetapi termasuk informasi yang tidak relevan tidak perlu untuk menggunakannya dengan benar.
sumber