Saya memikirkannya dan tidak dapat memberikan contoh. Mengapa seseorang ingin menangkap pengecualian dan tidak melakukan apa-apa? Bisakah Anda memberi contoh? Mungkin itu hanya sesuatu yang tidak boleh dilakukan.
Saya memikirkannya dan tidak dapat memberikan contoh. Mengapa seseorang ingin menangkap pengecualian dan tidak melakukan apa-apa? Bisakah Anda memberi contoh? Mungkin itu hanya sesuatu yang tidak boleh dilakukan.
Jawaban:
Saya selalu melakukannya dengan hal-hal seperti kesalahan konversi di D:
import std.conv, std.stdio, std.exception;
void main(string[] args) {
enforce(args.length > 1, "Usage: foo.exe filename");
double[] nums;
// Process a text file with one number per line into an array of doubles,
// ignoring any malformed lines.
foreach(line; File(args[1]).byLine()) {
try {
nums ~= to!double(line);
} catch(ConvError) {
// Ignore malformed lines.
}
}
// Do stuff with nums.
}
Yang mengatakan, saya pikir semua blok tangkap harus memiliki sesuatu di dalamnya, bahkan jika sesuatu itu hanya komentar yang menjelaskan mengapa Anda mengabaikan pengecualian.
Sunting: Saya juga ingin menekankan bahwa, jika Anda akan melakukan sesuatu seperti ini, Anda harus berhati-hati untuk hanya menangkap pengecualian spesifik yang ingin Anda abaikan. Melakukan hal yang biasa-biasa saja catch {}
hampir selalu merupakan hal yang buruk.
Salah satu contoh di mana saya pikir OK untuk hanya menelan pengecualian tanpa melakukan apa-apa, bahkan mencatat pengecualian, adalah di dalam kode logging itu sendiri.
Jika Anda mencoba mencatat sesuatu dan mendapat pengecualian, tidak banyak yang dapat Anda lakukan:
Itu membuat Anda memiliki opsi "yang paling tidak jahat" untuk menelannya dengan diam-diam, memungkinkan aplikasi untuk terus melakukan pekerjaan utamanya, tetapi mengkompromikan kemampuan untuk memecahkannya.
Jika pengecualian dilemparkan oleh operasi yang opsional, mungkin tidak ada yang bisa dilakukan. Mungkin tidak berguna untuk mencatatnya. Dalam hal ini, Anda mungkin hanya ingin menangkapnya dan tidak melakukan apa pun.
Jika Anda melakukan ini, sertakan komentar. Selalu berkomentar apa pun yang tampak seperti bug (fallthrough dalam switch
pernyataan, catch
blok kosong , tugas dalam kondisi).
Anda mungkin berpendapat bahwa ini bukan penggunaan pengecualian, tapi itu untuk pertanyaan lain.
catch
Blok kosong adalah bau kode di sebagian besar bahasa. Gagasan utamanya adalah menggunakan pengecualian untuk situasi luar biasa dan tidak menggunakannya untuk kontrol logis. Semua pengecualian harus ditangani di suatu tempat.
Sebagai konsekuensi dari mengambil pendekatan ini, ketika Anda memprogram satu lapisan aplikasi tertentu, Anda memiliki beberapa pilihan:
Ini tidak benar-benar meninggalkan ruang untuk melakukan apa-apa, catch
blok kosong .
DIedit UNTUK MENAMBAH : misalkan Anda memprogram dalam bahasa di mana melemparkan pengecualian adalah cara normal untuk mengendalikan logika program (salah satu alternatif untuk goto
). Kemudian catch
blok kosong dalam program yang ditulis dalam bahasa ini sangat mirip dengan else
blok kosong dalam bahasa tradisional (atau tidak ada else
blok sama sekali). Namun, saya percaya ini bukan gaya pemrograman yang direkomendasikan oleh komunitas pengembangan C #, Java atau C ++.
Dalam beberapa kasus, Java mengharuskan Anda untuk menangani pengecualian yang dapat, dalam keadaan apa pun, tidak pernah terjadi. Pertimbangkan kode ini:
try {
bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}
Setiap implementasi platform Java diperlukan untuk mendukung rangkaian karakter standar berikut.
...
UTF-8
Tanpa merusak platform Java Anda, tidak ada cara untuk menyebabkan pengecualian ini. Jadi mengapa repot-repot menanganinya? Tetapi Anda tidak bisa begitu saja menghilangkan klausa coba-tangkap.
throw new Error(e)
hanya untuk benar-benar yakin bahwa saya tidak melewatkan apa pun (atau melaporkan platform yang benar-benar rusak).
Sebagai aturan umum, tidak. Anda ingin melemparkan pengecualian ke tumpukan, atau mencatat apa yang terjadi.
Namun, saya sering melakukan ini ketika saya mem-parsing string dan mengkonversi ke angka (terutama dalam memetakan proyek yang digunakan-sekali dan membuang variasi).
boolean isNonZeroNumber = false;
try {
if(StringUtils.isNotBlank(s) && new BigDecimal(s).compareTo(BigDecimal.ZERO) != 0) {
b = true;
}
} catch(NumberFormatException e) {
//swallow this exception; b stays false.
}
return b;
Dalam beberapa kasus, pengecualian sama sekali tidak luar biasa; bahkan diharapkan. Pertimbangkan contoh ini:
/* Check if the process is still alive; exitValue() throws an exception if it is */
try {
p.exitValue();
processPool.remove(p);
}
catch (IllegalThreadStateException e) { /* expected behaviour */ }
Karena tidak ada metode isAlive () di java.lang.Process (), satu-satunya cara untuk memeriksa apakah masih hidup adalah dengan memanggil exitValue (), yang melempar IllegalThreadStateException jika prosesnya masih berjalan.
Dalam pengalaman saya yang sederhana, jarang hal yang baik ini. Jarak tempuh Anda mungkin bervariasi.
Hampir setiap kali saya melihat ini di basis kode kami, itu karena saya telah melacak bug yang disembunyikan oleh pengecualian yang dimakan. Dengan kata lain, dengan tidak memberikan kode apa pun, aplikasi tidak memiliki cara untuk menunjukkan kesalahan, atau melakukan tindakan lain.
Terkadang, pada lapisan API misalnya, Anda mungkin tidak ingin atau tidak dapat membiarkan pengecualian lewat, jadi dalam hal ini, saya cenderung mencoba dan menangkap yang paling umum, lalu mencatatnya. Sekali lagi, untuk setidaknya memberikan kesempatan sesi debug / diagnosis.
Biasanya, jika itu harus kosong, paling tidak saya lakukan adalah meletakkan semacam pernyataan, jadi setidaknya sesuatu terjadi selama sesi debug. Yang mengatakan, jika saya tidak bisa mengatasinya, saya cenderung menghilangkannya sepenuhnya.
IMO ada satu tempat di mana pernyataan penangkapan kosong OK. Dalam kasus uji di mana Anda mengharapkan pengecualian:
try
{
DoSomething(); //This should throw exception if everything works well
Assert.Fail('Expected exception was not thrown');
}
catch(<whatever exception>)
{
//Expected to get here
}
Saya percaya ada kasus-kasus tertentu di mana dibenarkan memiliki klausa tangkapan kosong - ini adalah kasus ketika Anda ingin kode terus berjalan jika operasi tertentu gagal. Namun, saya berpikir bahwa pola ini dapat dengan mudah digunakan secara berlebihan, sehingga setiap penggunaan harus diperiksa dengan cermat untuk memastikan tidak ada cara yang lebih baik untuk menanganinya. Secara khusus, ini tidak boleh dilakukan jika meninggalkan program dalam keadaan tidak konsisten atau jika itu dapat menyebabkan beberapa bagian lain dari kode gagal nanti.
Saya tidak percaya tidak memiliki tingkat peringatan ketika pengecualian terjadi - tidakkah seharusnya salah satu tujuan pemrograman adalah untuk meningkatkan kode? Jika pengecualian terjadi 10% dari waktu, dan Anda tidak pernah mengetahuinya, maka pengecualian akan selalu seburuk itu, atau lebih buruk.
Namun, saya memang melihat sisi lain, bahwa jika pengecualian tidak membahayakan nyata dalam pemrosesan kode, lalu mengapa mengekspos pengguna untuk itu. Solusi yang biasanya saya terapkan adalah dengan login oleh kelas logger saya (yang ada di setiap kelas tunggal yang pernah saya tulis di tempat kerja).
Jika ini adalah pengecualian yang tidak berbahaya, maka saya melakukan panggilan ke metode .debug () Logger saya; jika tidak, Logger.Error () (dan (mungkin) melempar).
try
{
doWork();
}
catch(BenignException x)
{
_log.Debug("Error doing work: " + x.Message);
}
Omong-omong, dalam implementasi logger saya, membuat panggilan ke metode .Debug () hanya akan mencatatnya jika file App.Config saya menentukan bahwa level log eksekusi program dalam mode Debug.
Pemeriksaan keberadaan adalah kasus penggunaan yang baik:
// If an exception happens, it doesn't matter. Log the initial value or the new value
function logId(person) {
let id = 'No ID';
try {
id = person.data.id;
} catch {}
console.log(id);
}
Kasus lain adalah ketika finally
klausa digunakan:
function getter(obj){}
function objChecker()
{
try
{
/* Check argument length and constructor type */
if (getter.length === 1 && getter.constructor === Function)
{
console.log("Correct implementation");
return true;
}
else
{
console.log("Wrong implementation");
return false;
}
}
catch(e)
{
}
finally
{
console.log(JSON.stringify(getter))
}
}
// Test the override of the getter method
getter = getter;
objChecker();
getter = [];
objChecker();
getter = {};
objChecker();
getter = RegExp;
objChecker();
getter = Function;
objChecker();
Ada proposal untuk memungkinkan penghilangan tangkapan yang mengikat dalam ECMAScript yang berkaitan dengan ini dan kasus penggunaan serupa.
Referensi
Satu-satunya waktu saya benar-benar perlu melakukan sesuatu seperti ini adalah dengan kelas logging untuk aplikasi konsol. Ada penangkap tangkapan global tingkat atas yang memancarkan kesalahan ke STDOUT, mencatat kesalahan ke file, lalu menutup aplikasi dengan kode kesalahan> 0.
Masalahnya di sini adalah bahwa kadang-kadang, logging ke file gagal. Izin direktori menghentikan Anda dari menulis file, file itu dikunci secara eksklusif, apa pun. Jika itu terjadi, saya tidak bisa menangani pengecualian dengan cara yang sama seperti di tempat lain (menangkap, mencatat detail yang relevan , membungkus dengan tipe pengecualian yang lebih baik, dll) karena mencatat detail pengecualian menyebabkan logger melakukan tindakan yang sama ( mencoba menulis ke file) yang sudah gagal. Ketika mereka gagal lagi ... Anda lihat ke mana saya pergi. Itu masuk ke loop tak terbatas.
Jika Anda membatalkan beberapa blok percobaan {}, Anda bisa berakhir dengan pengecualian yang muncul di kotak pesan (bukan yang Anda inginkan untuk aplikasi konfigurasi senyap). Jadi dalam metode yang menulis ke file log, saya memiliki penangan tangkapan kosong. Ini tidak mengubur kesalahan karena Anda masih mendapatkan kode kesalahan> 0, itu hanya menghentikan loop tak terbatas dan memungkinkan aplikasi untuk keluar dengan anggun.
Ada komentar tentu saja, menjelaskan mengapa itu kosong.
(Aku akan memposting ini sebelumnya, aku hanya takut dinyalakan dilupakan. Karena aku bukan satu-satunya, meskipun ...)
Tidak apa-apa dalam situasi ketika beberapa urutan harus dieksekusi tidak peduli apa pun dengan bagian paling kritis yang ditempatkan di akhir.
Sebagai contoh. Komunikasi kontrol gerak dari host ke pengontrol. Dalam situasi darurat ada sejumlah langkah persiapan untuk menggagalkan gerakan, menghentikan generasi lintasan, memperlambat motor, mengaktifkan jeda, menonaktifkan amplifier dan setelah ini Anda harus mematikan daya bus. Semua harus terjadi secara berurutan dan jika salah satu dari langkah-langkah yang gagal, sisa dari langkah-langkah lainnya harus dieksekusi walaupun dengan risiko yang diterima dari kerusakan perangkat keras. Katakanlah bahkan jika semua di atas gagal, daya bunuh bus harus tetap terjadi.
Menutup sumber daya sistem dengan anggun untuk memulihkan dari kesalahan
Misalnya. Jika Anda menjalankan layanan di latar belakang yang tidak memberikan umpan balik kepada pengguna, Anda mungkin tidak ingin mendorong indikasi kesalahan kepada pengguna tetapi Anda tidak perlu menutup sumber daya yang digunakan dengan cara yang anggun.
try
{
// execution code here
}
catch(Exception e)
{
// do nothing here
}
finally
{
// close db connection
// close file io resource
// close memory stream
// etc...
}
Idealnya, Anda akan menggunakan tangkapan dalam mode debug untuk menangkap kesalahan dan mencetaknya ke konsol atau ke file log untuk pengujian. Dalam lingkungan produksi, layanan latar belakang umumnya diharapkan tidak mengganggu pengguna ketika kesalahan dilemparkan sehingga output kesalahan harus ditekan.