it-swarm.dev

Boş bir catch bildirimi hazır mı?

Bunu düşündüm ve bir örnek bulamadım. Neden biri bir istisna yakalamak ve bu konuda hiçbir şey yapmak istemez ki? Bir örnek verebilir misin? Belki de asla yapılmaması gereken bir şeydir.

61
ysolik

D dönüşüm hataları gibi şeyler ile her zaman yaparım:

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

Bununla birlikte, bir şey sadece açıklayan bir yorum olsa bile, tüm yakalama bloklarının bir şey olması gerektiğini düşünüyorum neden istisna görmezden geliyor.

Düzenleme: Ayrıca, böyle bir şey yapacaksanız, sadece göz ardı etmek istediğiniz özel istisnayı yakalamak için dikkatli olmanız gerektiğini vurgulamak istiyorum. Eski bir düz catch {} Yapmak neredeyse her zaman kötü bir şeydir.

78
dsimcha

İstisnasız herhangi bir şey yapmadan, hatta istisnayı günlüğe kaydetmeden, sadece istisnayı yutmanın iyi olduğunu düşündüğüm bir örnek, günlük kodunun içinde.

Bir şeyi günlüğe kaydetmeye çalıştıysanız ve istisnanız varsa, bu konuda yapabileceğiniz çok şey yoktur:

  • tabii ki giriş yapamazsınız;
  • yedek kayıt mekanizmasına geri dönebilirsiniz, ancak çoğu uygulama o kadar karmaşık değildir ve yeterince gelişmiş olanlar için yedek kayıt mekanizması ile aynı tasarım sorunu ortaya çıkacaktır;
  • hızlı başarısızlık - çoğu uygulama için çok radikal bir çözüm olacaktır;
  • istisna atmak biraz iyi olacaktır çünkü neredeyse kesin olarak kayıt yapmaya çalışacak olan bir catch deyiminde sonuçlanacak ...

Bu, uygulamanın ana işini yapmaya devam etmesine izin vererek, ancak sorun giderme yeteneğinden ödün vererek, onu sessizce yutmanın "en az şeytani" seçeneği ile bırakır.

50
kdubinets

Yine de isteğe bağlı bir işlem tarafından bir istisna atılırsa, yapılacak bir şey olmayabilir. Günlüğe kaydetmek yararlı olmayabilir. Bu durumda, sadece yakalamak ve hiçbir şey yapmak istemeyebilirsiniz.

Bunu yapıyorsanız, bir yorum ekleyin. Her zaman hataya benzeyen her şeyi yorumlayın (switch ifadesinde geçiş, boş catch bloğu, bir koşulda atama).

Bunun istisnaların uygun bir kullanımı olmadığını iddia edebilirsiniz, ancak bu başka bir soru için.

8
David Thornley

Bazı durumlarda, Java, kesinlikle hiçbir koşulda gerçekleşmeyecek bir özel durumla başa çıkmanızı gerektirir. Bu kodu göz önünde bulundurun:

try {
   bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}

Java platformunun her uygulaması, aşağıdaki standart karakter kümelerini desteklemek için gereklidir.

...

UTF-8

Java platformunuzu kırmadan, bu istisnayı neden olmanın hiçbir yolu yoktur. Peki neden bu konuyu ele geçirmek zahmetine giriyorsunuz?.

6
user281377

Genel bir kural olarak, hayır. İstisnayı yığına atmak veya olanları günlüğe kaydetmek istiyorsunuz.

Ancak, bunu genellikle dizeleri ayrıştırırken ve sayılara dönüştürürken yaparım (özellikle bir kez kullanımda olan ve çeşitli atma projelerinde haritalama projelerinde).

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

Boş catch blokları çoğu dilde kod kokusudur. Ana fikir istisnai durumlar için istisnalar kullanmak ve bunları mantıksal kontrol için kullanmamaktır. Tüm istisnalar bir yerde ele alınmalıdır.

Bu yaklaşımı benimsemenizin bir sonucu olarak, belirli bir uygulama katmanını programladığınızda birkaç seçeneğiniz vardır:

  • istisna hakkında hiçbir şey yapma. Farklı bir katman tarafından yakalanacak ve ele alınacaktır.
  • yakalayın ve düzeltici eylemi gerçekleştirin.
  • yakalayın, bir şeyler yapın, ancak başka bir katmanın işlemesi için yeniden atın

Bu, hiçbir şey yapmayan, boş catch bloklara yer bırakmaz.

EKLE EDİTİLDİ: istisnaları atmanın program mantığını kontrol etmenin normal yolu olduğu bir dilde programladığınızı varsayalım (goto seçeneklerinden biri). Daha sonra bu dilde yazılmış bir programdaki boş bir catch bloğu, geleneksel bir dilde boş bir else bloğuna çok benzer (veya hiç else bloğu yok). Ancak, bunun C #, Java veya C++ geliştirme toplulukları tarafından önerilen) olmadığını düşünüyorum.

6
azheglov

Bazı durumlarda, istisna hiç de istisnai değildir; aslında beklenir. Bu örneği düşünün:

    /* 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 */ }

Java.lang.Process () yönteminde isAlive () yöntemi olmadığından, hala canlı olup olmadığını kontrol etmenin tek yolu, işlem hala çalışıyorsa bir IllegalThreadStateException özel durumu oluşturan exitValue () yöntemini çağırmaktır.

3
user281377

Mütevazı deneyimime göre, nadiren bu iyi şeydir. Kilometre değişebilir.

Neredeyse her zaman kod üssünde bunu gördüm, çünkü ben yemiş istisna gizlenmiş bir hata izledi çünkü. Başka bir deyişle, herhangi bir kod sağlayarak uygulamanın bir hatayı gösterme veya başka bir eylem gerçekleştirme yolu yoktur.

Bazen, API katmanlarında, istisnaların geçmiş olmasına izin vermeyebilir veya izin veremeyebilirsiniz, bu durumda, en genel olanı yakalamaya ve sonra bunları günlüğe kaydetmeye eğilimliyim. Bir kez daha, en azından bir hata ayıklama/tanı oturumuna şans vermek.

Genellikle, must boş olması durumunda, en azından yaptığım bir tür iddia koymaktır, bu yüzden en azından bir hata ayıklama oturumu sırasında bir şey olur. Bununla başa çıkamazsam, onları tamamen ihmal etme eğilimindeyim dedi.

2
DevSolo

IMO boş catch deyimlerinin uygun olduğu tek bir yer var. Bir istisna beklediğiniz test durumlarında:

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

Ben boş bir yakalamak yan tümcesi haklı olduğu bazı durumlarda olduğuna inanıyorum - bu sadece belirli bir işlem başarısız olursa kod devam etmek istediğiniz durumlar. Bununla birlikte, bu modelin kolayca aşırı kullanılabileceğini düşünüyorum, bu yüzden her kullanım, onu ele almanın daha iyi bir yolu olmadığından emin olmak için yakından incelenmelidir. Özellikle, programı tutarsız bir durumda bırakırsa veya kodun başka bir bölümünün daha sonra başarısız olmasına yol açabiliyorsa, bu asla yapılmamalıdır.

2
o. nate

Varlık kontrolü iyi bir kullanım durumudur:

// 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);
}

Başka bir durum, bir finally yan tümcesi kullanıldığındadır:

 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();

ECMAScript'te bu ve benzeri kullanım durumlarına ilişkin yakalama bağlayıcısının atlanması 'a izin vermek için bir teklif vardır.

Referanslar

1
Paul Sweatte

Bir istisna meydana geldiğinde uyarı düzeyine sahip olmadığına inanmıyorum - programlama hedeflerinden biri kodu geliştirmek değil mi? Bir istisna zamanın% 10'unda meydana gelirse ve bunu asla bilmiyorsanız, istisna her zaman bu kadar kötü veya daha kötü olacaktır.

Ancak, diğer tarafı görüyorum, eğer istisna kodun işlenmesinde gerçek bir zarar vermezse, o zaman neden kullanıcı bunu ortaya çıkarır. Genelde uyguladığım çözüm logger sınıfım tarafından günlüğe kaydediliyor (işte yazdığım her sınıfta).

Benign bir istisna varsa, o zaman Logger's .Debug () yöntemine bir çağrı yapmak; aksi takdirde, Logger.Error () (ve (belki) atın).

try
{
   doWork();
}
catch(BenignException x)
{
  _log.Debug("Error doing work: " + x.Message);
}

Bu arada, logger uygulamamda .Debug () yöntemine çağrı yapmak yalnızca App.Config dosyamın program yürütme günlüğü düzeyinin Hata Ayıklama modunda olduğunu belirtmesi durumunda günlüğe kaydeder.

1
Tim Claason

Sonunda en kritik parça ne olursa olsun, bir dizi yürütülmesi gerektiğinde sorun yoktur.

Örneğin. Ana makinenin denetleyiciye hareket kontrol iletişimi. Acil durumlarda hareketi iptal etmek, yörünge üretimini durdurmak, motorları yavaşlatmak, kesintileri etkinleştirmek, amplifikatörü devre dışı bırakmak ve bundan sonra veri yolu gücünü öldürmek için bir dizi hazırlık adımı vardır. Her şey sırayla gerçekleşmelidir ve adımlardan biri başarısız olursa, donanımın zarar görme riski kabul edilmiş olsa bile adımların geri kalanı yine de yürütülmelidir. Yukarıdakilerin hepsi başarısız olsa bile, kill veri yolu gücü yine de gerçekleşmelidir.

0
user7071

Böyle bir şey yapmak için gerçekten ihtiyacım olan tek zaman, bir konsol uygulaması için bir kayıt sınıfıydı. Hatayı STDOUT'a gönderen, hatayı bir dosyaya kaydeden, ardından uygulamayı> 0 hata koduyla kapatan bir üst düzey global catch işleyicisi vardı.

Buradaki sorun bazen dosyaya girişin başarısız olmasıydı. Dizin izinleri dosyayı yazmanızı engelledi, dosya ne olursa olsun sadece kilitlendi. Bu olursa, istisnayı başka bir yerde yaşadığım şekilde ele alamazdım (catch, ilgili ayrıntıları günlüğe kaydet, daha iyi bir istisna türüne sarın, vb.) Çünkü istisna ayrıntılarının kaydedilmesi kaydediciye neden oldu başarısız olan aynı eylemleri (bir dosyaya yazmaya çalışarak) geçmek. Tekrar başarısız olduklarında ... Nereye gittiğimi görüyorsun. Sonsuz bir döngüye girer.

Try {} bloklarının bazılarını bırakırsanız, bir mesaj kutusunda görünen istisna ile sonuçlanabilir (sessiz bir yapılandırma uygulaması için istediğinizi değil). Günlük dosyasına yazan bu yöntemde, boş bir catch işleyicim var. Hala 0'dan fazla hata kodunu aldığınız için bu hata gömülmez, sadece sonsuz döngüyü durdurur ve uygulamanın zarif bir şekilde çıkmasına izin verir.

Elbette, neden boş olduğunu açıklayan bir yorum var.

(Bunu daha önce gönderecektim, unutulmaya hazırlanmaktan korkuyordum. Yine de tek kişi olmadığım için ...)

0
JohnL

Bir hatadan kurtulmak için sistem kaynaklarını incelikle kapatma

Örneğin. Arka planda, kullanıcıya geri bildirim sağlamayan bir hizmet çalıştırıyorsanız, kullanıcıya bir hata belirtisi göndermek istemeyebilirsiniz, ancak do kaynakları kapatmanız gerekir zarif bir şekilde kullanılması.

try
{
    // execution code here
}
catch(Exception e)
{
    // do nothing here
}
finally
{
    // close db connection
    // close file io resource
    // close memory stream
    // etc...
}

İdeal olarak, hataları yakalamak ve sınamak için konsola veya günlük dosyasına yazdırmak için catch'i hata ayıklama modunda kullanırsınız. Bir üretim ortamında, arka plan hizmetlerinin genellikle bir hata atıldığında kullanıcıyı kesintiye uğratmaması ve böylece hata çıktısının bastırılması beklenir.

0
Evan Plaice