Saat ini saya sedang melakukan tinjauan kode dan salah satu hal yang saya perhatikan adalah jumlah pengecualian di mana pesan pengecualian sepertinya mengulangi di mana pengecualian terjadi. misalnya
throw new Exception("BulletListControl: CreateChildControls failed.");
Semua tiga item dalam pesan ini saya dapat bekerja dari sisa pengecualian. Saya tahu kelas dan metode dari jejak stack dan saya tahu itu gagal (karena saya punya pengecualian).
Itu membuat saya berpikir tentang pesan apa yang saya masukkan dalam pesan pengecualian. Pertama saya membuat kelas pengecualian, jika seseorang belum ada, untuk alasan umum (misalnya PropertyNotFoundException
- alasannya ), dan kemudian ketika saya melemparkannya pesan menunjukkan apa yang salah (mis. "Tidak dapat menemukan properti 'IDontExist' pada Node 1234 "- apa ). Di mana ada di StackTrace
. The ketika mungkin berakhir dalam log (jika ada). The bagaimana bagi pengembang untuk bekerja (dan memperbaiki)
Apakah Anda punya kiat lain untuk melempar pengecualian? Khususnya berkaitan dengan pembuatan jenis baru dan pesan pengecualian.
sumber
Jawaban:
Saya akan mengarahkan jawaban saya lebih lanjut ke apa yang muncul setelah pengecualian: apa manfaatnya dan bagaimana seharusnya peranti lunak berperilaku, apa yang harus dilakukan pengguna Anda dengan pengecualian? Teknik hebat yang saya temui di awal karier saya adalah selalu melaporkan masalah dan kesalahan dalam 3 bagian: konteks, masalah & solusi. Menggunakan disiplin ini mengubah penanganan kesalahan sangat besar dan membuat perangkat lunak jauh lebih baik bagi operator untuk digunakan.
Berikut beberapa contohnya.
Dalam hal ini, operator tahu persis apa yang harus dilakukan dan ke file mana yang harus terpengaruh. Mereka juga tahu bahwa perubahan pooling koneksi tidak mengambil dan harus diulang.
Saya menulis sistem sisi server dan operator saya umumnya mendukung lini pertama yang mengerti teknologi. Saya akan menulis pesan secara berbeda untuk perangkat lunak desktop yang memiliki audiens yang berbeda tetapi menyertakan informasi yang sama.
Beberapa hal indah terjadi jika seseorang menggunakan teknik ini. Pengembang perangkat lunak sering kali berada di posisi terbaik untuk mengetahui bagaimana menyelesaikan masalah dalam kode mereka sendiri sehingga solusi enkode dengan cara ini saat Anda menulis kode adalah manfaat besar bagi pengguna akhir yang berada pada solusi pencarian yang kurang menguntungkan karena mereka sering kehilangan informasi tentang apa sebenarnya yang dilakukan perangkat lunak. Siapa pun yang pernah membaca pesan kesalahan Oracle akan tahu apa yang saya maksud.
Hal luar biasa kedua yang terlintas dalam pikiran adalah ketika Anda menemukan diri Anda mencoba menggambarkan solusi dalam pengecualian Anda dan Anda sedang menulis "Periksa X dan jika A maka B lagi C". Ini adalah tanda yang sangat jelas dan jelas bahwa pengecualian Anda sedang diperiksa di tempat yang salah. Anda programmer memiliki kapasitas untuk membandingkan hal-hal dalam kode sehingga "jika" pernyataan harus dijalankan dalam kode, mengapa melibatkan pengguna dalam sesuatu yang dapat diotomatisasi? Kemungkinannya adalah dari kode yang lebih dalam dan seseorang telah melakukan hal yang malas dan melempar IOException dari sejumlah metode dan menangkap potensi kesalahan dari semuanya dalam blok kode panggilan yang tidak dapat secara memadai menggambarkan apa yang salah, apa yang spesifikkonteksnya dan bagaimana cara memperbaikinya. Ini mendorong Anda untuk menulis kesalahan butir yang lebih halus, menangkap dan menanganinya di tempat yang tepat dalam kode Anda sehingga Anda dapat mengartikulasikan dengan benar langkah-langkah yang harus diambil operator.
Di satu perusahaan, kami memiliki operator terbaik yang mengenal perangkat lunak dengan sangat baik dan menyimpan "buku bacaan" mereka sendiri yang menambah pelaporan kesalahan kami dan menyarankan solusi. Untuk mengenali hal ini, perangkat lunak mulai menyertakan tautan wiki ke run book dalam pengecualian sehingga tersedia penjelasan dasar serta tautan ke diskusi dan pengamatan yang lebih maju oleh operator dari waktu ke waktu.
Jika Anda memiliki disiplin untuk mencoba teknik ini, akan jauh lebih jelas apa yang harus Anda beri nama pengecualian Anda dalam kode saat membuat Anda sendiri. NonRecoverableConfigurationReadFailedException menjadi sedikit singkatan untuk apa yang akan Anda gambarkan lebih lengkap kepada operator. Saya suka menjadi verbose dan saya pikir itu akan lebih mudah bagi pengembang berikutnya yang menyentuh kode saya untuk menafsirkan.
sumber
FileNotFound
atauConnectException
Anda tahu apa yang harus dilakukan))Dalam pertanyaan yang lebih baru ini saya menyatakan bahwa pengecualian tidak boleh mengandung pesan sama sekali. Menurut pendapat saya, fakta yang mereka lakukan adalah kesalahpahaman yang sangat besar. Yang saya usulkan adalah itu
Pengecualian harus mengandung dalam variabel anggotanya sendiri sebanyak mungkin detail tentang apa yang terjadi; misalnya,
IndexOutOfRangeException
harus berisi nilai indeks yang ditemukan tidak valid, serta nilai-nilai atas dan bawah yang berlaku pada saat pengecualian dilemparkan. Dengan cara ini, menggunakan refleksi Anda dapat memiliki pesan yang dibuat secara otomatis yang berbunyi seperti ini:IndexOutOfRangeException: index = -1; min=0; max=5
dan ini, bersama dengan jejak tumpukan, harus menjadi semua informasi objektif yang Anda butuhkan untuk memecahkan masalah. Memformatnya menjadi pesan cantik seperti "index -1 tidak antara 0 dan 5" tidak menambah nilai apa pun.Dalam contoh khusus Anda,
NodePropertyNotFoundException
kelas akan berisi nama properti yang tidak ditemukan, dan referensi ke simpul yang tidak mengandung properti. Hal ini penting: harus tidak berisi nama node; itu harus berisi referensi ke simpul yang sebenarnya. Dalam kasus khusus Anda ini mungkin tidak perlu, tetapi ini adalah masalah prinsip dan cara berpikir yang lebih disukai: perhatian utama ketika membangun pengecualian adalah bahwa itu harus dapat digunakan oleh kode yang mungkin menangkapnya. Kegunaan oleh manusia adalah hal yang penting, tetapi hanya masalah sekunder.Ini menangani situasi yang sangat membuat frustrasi yang mungkin Anda saksikan pada suatu saat dalam karir Anda, di mana Anda mungkin telah menangkap pengecualian yang berisi informasi penting tentang apa yang terjadi dalam teks pesan, tetapi tidak di dalam variabel anggotanya, sehingga Anda harus melakukan penguraian string teks untuk mencari tahu apa yang terjadi, berharap bahwa teks pesan akan tetap sama di versi masa depan dari lapisan yang mendasarinya, dan berdoa agar teks pesan tidak akan dalam beberapa bahasa asing ketika program Anda dijalankan di negara lain.
Tentu saja, karena nama kelas pengecualian adalah pesan pengecualian, (dan variabel anggota pengecualian adalah detail spesifik), ini berarti bahwa Anda memerlukan banyak dan banyak pengecualian berbeda untuk menyampaikan semua pesan yang berbeda, dan ini baik saja.
Sekarang, kadang-kadang, ketika kita menulis kode, kita menemukan situasi yang salah di mana kita hanya ingin cepat kode
throw
pernyataan dan melanjutkan penulisan kode kita daripada harus mengganggu apa yang kita lakukan untuk membuat kelas pengecualian baru sehingga kita bisa lempar ke sana. Untuk kasus ini, saya memilikiGenericException
kelas yang sebenarnya menerima pesan string sebagai parameter waktu konstruksi, tetapi konstruktor dari kelas pengecualian ini dihiasi denganFIXME XXX TODO
komentar ungu terang besar yang sangat besar yang menyatakan bahwa setiap instance dari kelas ini harus diganti dengan instantiasi dari beberapa kelas pengecualian yang lebih terspesialisasi sebelum sistem perangkat lunak dirilis, lebih disukai sebelum kode dikomit.sumber
node
objek dijaga oleh klausa use-disposable (dalam C #) atau coba-dengan-sumber daya (di Jawa): objek yang disimpan dengan pengecualian akan dibuang / ditutup, menjadikannya ilegal untuk mengaksesnya untuk mendapatkan informasi yang berguna darinya di tempat pengecualian ditangani. Saya berasumsi bahwa dalam kasus ini semacam ringkasan objek harus disimpan dalam pengecualian, bukan objek itu sendiri. Saya tidak bisa memikirkan cara bukti bodoh untuk secara umum menangani ini untuk semua kasus.Sebagai aturan umum, pengecualian harus membantu pengembang menentukan penyebab dengan memberikan informasi yang berguna (nilai yang diharapkan, nilai aktual, kemungkinan penyebab / solusi, dll.).
Tipe pengecualian baru harus dibuat ketika tidak ada tipe bawaan yang masuk akal . Jenis tertentu memungkinkan pengembang lain untuk menangkap pengecualian tertentu dan menanganinya. Jika pengembang tahu cara menangani pengecualian Anda, tetapi tipenya adalah
Exception
, ia tidak akan bisa menanganinya dengan benar.sumber
Dalam. NET tidak pernah
throw new Exception("...")
(seperti yang ditunjukkan oleh penulis pertanyaan). Exception adalah tipe Exception root dan tidak seharusnya dibuang secara langsung. Alih-alih melempar salah satu jenis pengecualian .NET yang diturunkan atau membuat pengecualian kustom Anda sendiri yang berasal dari Pengecualian (atau jenis pengecualian lain).Mengapa tidak membuang Pengecualian? Karena melemparkan Exception tidak melakukan apa pun untuk menggambarkan pengecualian Anda dan memaksa kode panggilan Anda untuk menulis kode seperti
catch(Exception ex) { ... }
yang umumnya bukan hal yang baik! :-).sumber
Hal-hal yang ingin Anda cari untuk "ditambahkan" ke pengecualian adalah elemen-elemen data yang tidak melekat dalam pengecualian atau jejak tumpukan. Apakah itu bagian dari "pesan" atau perlu dilampirkan saat login adalah pertanyaan yang menarik.
Seperti yang telah Anda catat, pengecualian mungkin memberi tahu Anda apa, stacktrace mungkin memberi tahu Anda di mana tetapi "mengapa" mungkin lebih terlibat (seharusnya, orang akan berharap) daripada hanya mengintip satu atau dua baris dan berkata " doh! Tentu saja ". Ini bahkan lebih benar ketika mencatat kesalahan dalam kode produksi - Saya sudah terlalu sering digigit oleh data buruk sehingga menemukan jalannya ke sistem hidup yang tidak ada dalam sistem pengujian kami. Sesuatu yang sesederhana mengetahui ID apa dari catatan dalam database yang menyebabkan (atau berkontribusi) kesalahan dapat menghemat banyak waktu.
Jadi ... Entah terdaftar atau, untuk .NET, ditambahkan ke pengumpulan data pengecualian yang dicatat (cf @Plip!):
Beberapa hal, tentu saja, Anda tidak akan tahu Anda perlu sampai Anda tidak memilikinya dalam laporan / log kesalahan awal Anda. Beberapa hal yang tidak Anda sadari bisa Anda dapatkan sampai Anda menemukan Anda membutuhkannya.
sumber
Apa Pengecualian untuk ?
(1) Memberitahu pengguna ada yang salah?
Ini harus menjadi pilihan terakhir, karena kode Anda harus bersyafaat dan menunjukkan kepada mereka sesuatu yang "lebih baik" daripada Pengecualian.
Pesan "kesalahan" harus secara jelas dan ringkas menyatakan apa yang salah dan apa, jika ada, yang dapat dilakukan pengguna untuk pulih dari kondisi kesalahan.
mis. "Tolong jangan tekan tombol ini lagi"
(2) Memberitahu Pengembang ketika terjadi kesalahan?
Ini adalah jenis hal yang Anda login ke file untuk analisis selanjutnya.
The Stack Trace akan memberitahu Developer mana kode pecah; pesan itu harus, sekali lagi, menunjukkan apa yang salah.
(3) Memberi tahu penangan Exception (kode yaitu) bahwa ada yang salah?
The Jenis dari Eksepsi akan menentukan handler pengecualian akan mendapatkan untuk melihat itu dan sifat didefinisikan pada objek Exception akan memungkinkan pawang untuk menghadapinya.
Pesan Pengecualian sama sekali tidak relevan .
sumber
Jangan membuat tipe baru jika Anda bisa membantu. Mereka dapat menyebabkan kebingungan ekstra, kerumitan dan menyebabkan lebih banyak kode untuk dipelihara. Mereka mungkin membuat kode Anda harus diperluas. Mendesain hierarki pengecualian membutuhkan banyak waktu dan pengujian. Ini bukan pemikiran setelah. Seringkali yang terbaik adalah menggunakan hierarki pengecualian bahasa bawaan.
Isi pesan pengecualian bergantung pada penerima pesan - jadi Anda harus menempatkan diri pada posisi orang tersebut.
Seorang insinyur pendukung harus dapat mengidentifikasi sumber kesalahan secepat mungkin. Sertakan string deskriptif pendek plus data apa pun yang dapat membantu memecahkan masalah. Selalu sertakan jejak tumpukan - jika Anda bisa - ini akan menjadi satu-satunya sumber informasi yang sebenarnya.
Menyajikan kesalahan kepada pengguna umum sistem Anda tergantung pada jenis kesalahan: jika pengguna dapat memperbaiki masalah, dengan memberikan input yang berbeda misalnya, maka pesan deskriptif singkat diperlukan. Jika pengguna tidak dapat memperbaiki masalah, maka yang terbaik adalah menyatakan kesalahan telah terjadi dan mencatat / mengirim kesalahan untuk mendukung (menggunakan pedoman di atas).
Juga - jangan muntah besar "HALT ERROR!" ikon. Ini adalah kesalahan - ini bukan akhir dari dunia.
Jadi secara ringkas: pikirkan tentang para aktor dan gunakan kasing untuk sistem Anda. Tempatkan diri Anda pada posisi pengguna tersebut. Berguna. Bersikap baik. Pikirkan ini di depan dalam desain sistem Anda. Dari perspektif pengguna Anda - kasus pengecualian ini dan bagaimana sistem menanganinya, sama pentingnya dengan kasus normal di sistem Anda.
sumber