it-swarm-id.com

Apakah tidak masalah memiliki pernyataan penangkapan kosong?

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.

61
ysolik

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 sesuat 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 yang lama biasa catch {} Hampir selalu merupakan hal yang buruk.

78
dsimcha

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:

  • anda tidak dapat mencatatnya tentu saja;
  • anda mungkin dapat kembali ke mekanisme pencadangan cadangan, tetapi sebagian besar aplikasi tidak secanggih itu, dan bagi mereka yang cukup canggih masalah desain yang sama akan muncul dengan mekanisme pencatatan cadangan;
  • gagal cepat - akan menjadi solusi yang terlalu radikal untuk sebagian besar aplikasi;
  • melempar eksepsi akan sedikit bermanfaat karena akan berakhir dengan catch catch up stack yang hampir pasti akan mencoba untuk login ...

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.

50
kdubinets

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 (gagal dalam pernyataan switch, kosong catch blok, tugas dalam kondisi).

Anda mungkin berpendapat bahwa ini bukan penggunaan pengecualian, tapi itu untuk pertanyaan lain.

8
David Thornley

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 standar berikut ini.

...

UTF-8

Tanpa merusak platform Anda Java, tidak ada cara untuk menyebabkan pengecualian ini. Jadi, mengapa repot-repot menanganinya? Tapi Anda tidak bisa begitu saja mengabaikan klausa coba-tangkap.

6
user281377

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;
6
Fil

Kosong catch blok 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:

  • tidak melakukan apa-apa tentang pengecualian. Ini akan ditangkap dan ditangani oleh lapisan yang berbeda
  • tangkap dan lakukan tindakan korektif.
  • tangkap, lakukan sesuatu, tapi lemparkan kembali agar lapisan lain bisa ditangani

Ini tidak benar-benar menyisakan ruang untuk melakukan apa-apa, kosong catch blok.

DIedit UNTUK MENAMBAH: misalkan Anda memprogram dalam bahasa di mana melempar pengecualian adalah cara normal untuk mengendalikan logika program (salah satu alternatif untuk goto). Maka blok catch kosong dalam program yang ditulis dalam bahasa ini sangat mirip dengan blok else 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++.

6
azheglov

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.

3
user281377

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.

Kadang-kadang, 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 harus kosong, setidaknya yang saya lakukan adalah memberikan semacam penegasan, jadi setidaknya sesuatu terjadi selama sesi debug. Yang mengatakan, jika saya tidak bisa mengatasinya, saya cenderung menghilangkannya sepenuhnya.

2
DevSolo

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
}
2

Saya percaya ada 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.

2
o. nate

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 klausa finally 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 mengizinkan penghilangan tangkapan mengikat dalam naskah ECMAS yang berkaitan dengan ini dan kasus penggunaan serupa.

Referensi

1
Paul Sweatte

Saya tidak percaya tidak memiliki tingkat peringatan ketika pengecualian terjadi - bukankah 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);
}

Ngomong-ngomong, 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.

1
Tim Claason

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 Host to controller. Dalam situasi darurat ada sejumlah langkah persiapan untuk menggagalkan gerakan, menghentikan generasi lintasan, memperlambat motor, mengaktifkan break, menonaktifkan amplifier dan setelah ini Anda harus mematikan tenaga 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.

0
user7071

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> 0 kode kesalahan.

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 (tangkap, catat detail yang relevan, bungkus dengan jenis pengecualian yang lebih baik, dll) karena mencatat detail pengecualian menyebabkan pencatat untuk pergi melalui 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 dapat 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 punya handler 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 ...)

0
JohnL

Menutup sumber daya sistem dengan anggun untuk memulihkan dari kesalahan

Contohnya. Jika Anda menjalankan layanan di latar belakang yang tidak memberikan umpan balik kepada pengguna, Anda mungkin tidak ingin Menekan indikasi kesalahan kepada pengguna tetapi Anda lakukan perlu menutup sumber daya 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.

0
Evan Plaice