Koddaki çalışma zamanı istisnalarını işlemek iyi bir uygulama değil mi?


11

Bir Java uygulaması üzerinde çalışıyorum ve Çalışma zamanı istisnalarının birçok yerde işlendiğini görüyorum. Örneğin,

try {
    // do something
} catch(NullPointerException e) {
    return null;
}

Sorularım, Çalışma Zamanı istisnalarını işlemek ne zaman iyi bir uygulamadır? İstisnalar ne zaman ele alınmamalıdır?


7
-1: Bu geniş ve belirsiz soruya tek bir cevap yok. Bu kadar odaklanmamış bir soruya tek bir cevap vermek imkansızdır. Bu soru korkunç. Lütfen şüphelerinizin olduğu yerlere özel örnekler verin.
S.Lott

@ S.Lott Bu durumda, "İyi" Rasyonellik olmadan böyle bir durum olduğunu düşünen, programcıların bir alt kümesi olduğu için bu duruma katılmıyorum.
SoylentGray

2
@Chad: "Bu," İyi "Rasyonellik" olmadığı bir durumdur. Doğru olabilir. Ancak olası tek cevap “duruma bağlıdır” olmalıdır. Bu nedenle, soru hatalı görünüyor.
S.Lott

Yanıtlar:


18

Değişir.

Örneğin , sağlanan dize ayrıştırılamazsa (bir RTE olan) Integer#parseIntatar NumberFormatException. Ancak, uygulamanızın yalnızca kullanıcı tamsayılar için olan bir metin alanına "x" yazdığı için kilitlenmesini istemiyor musunuz? İlk önce ayrıştırmaya çalışmadığınız sürece dizenin ayrıştırılıp ayrıştırılamayacağını nasıl anlarsınız? Bu durumda, RTE sadece bir tür hata mesajına neden olması gereken bir hata sinyalidir. Bunun kontrol edilmiş bir istisna olması gerektiği söylenebilir, ancak ne yapabilirsiniz - değil.


2
"Buna bağlı" olarak katılıyorum, ancak ayrıştırma örneğiniz oldukça kötü bir API tasarımı örneği gibi görünüyor. Integer#parseIntgerçekten Maybe<Integer>bunun yerine dönmeli ve herhangi bir istisna atmamalıdır .
Jörg W Mittag

3
@ Jörg W Mittag: Kötü API tasarımı olduğuna katılıyorum, ancak başa çıkmamız gereken gerçek dünya. Atılabilirler / dönüş değerlerini doğru bir şekilde nasıl ele alacağınız, dünyanın en iyi nasıl çalışması gerektiğine değil, gerçekte nasıl çalıştığına bağlıdır :-)
Joonas Pulakka

Burada amaç, beklenen bir durum için anlamlı bir şey yapabilirsiniz (kullanıcı girişi tamsayı değil). Sadece NPE'yi yutmak kötü bir stildir ve sadece mevcut programlama hatalarını kapsayacaktır.
Jürgen Strobel

7

NullPointerExceptions genellikle eksik bir boş denetimin işaretidir. Bu nedenle, bu şekilde yakalamak yerine, istisnayı atmadığınızdan emin olmak için uygun null kontrolü eklemelisiniz.

Ancak bazen RunTimeExceptions ile çalışmak uygun olur. Örneğin, uygun yere boş denetim eklemek için kodu değiştiremediğinizde veya özel durum bir NullPointerException dışında bir şey olduğunda.

İstisnaları ele alma örneğiniz korkunç. Bunu yaptığınızda, yığın izlemesini ve sorunla ilgili kesin bilgileri kaybedersiniz. Ve muhtemelen başka bir NullPointerException'ı farklı bir yerde tetikleyeceğiniz ve ne olduğu ve nasıl çözüleceği hakkında yanıltıcı bilgiler alacağınız için çözmüyorsunuz.


1
Bir null kontrolün performans açısından daha iyi bir karar olduğunu eklemek isterim.
Mahmoud Hossam

... yine de, tek bir yerde "asla başarısız olmamalı" düzinelerce tahsisat yapıyorsanız, her biri için boş kontroller eklemek gülünç bir şekilde kodu gizleyebilir. Bir tümünü yakalama istisnası (sadece durumu değil, durumu zarifçe idare return null;edecek) daha iyi bir çözüm olacaktır.
SF.

Java'yı başka bir şeyle karıştırıyorsunuz (örnek için C ++). Bir ayırma başarısız olduğunda, OutOfMemoryError veya benzeri bir şey alırsınız, hiçbir zaman boş gösterici olmaz. İstisna yerine null döndürmeyi gizlemek, kodun başka bir yerde patlamasını bekleyen hatayı gizler.
deadalnix

newstd::bad_allocC ++ 'da atar .
R. Martinho Fernandes

Yeni operatörün aşırı yüklenmediğini varsayarsak, bu yaygın bir uygulamadır. C ++ ile her şey olabilir;) Ama tamam, diyelim ki C malloc. Önemli olan, bunu asla Java'da elde etmemenizdi.
deadalnix

4

Beklediğim istisnaları beklediğim yerde hallederim. (DB okuma / yazma hataları gibi). Beklenmedik istisnalar patlar. Başka bir yerde istisna bekliyor olabilir ve bunun mantığı olabilir.


2

İstisnalar sadece .. istisnalar olmalıdır. İstisnaları kullanırken en iyi uygulama, bunları olmasını beklediğiniz şeyin aksine bir durumun ortaya çıkması için kullanmaktır. Klasik örnek, bir dosya orada olmadığında atılan FileNotFoundException'dır. Dosyanın varlığını test ediyorsanız, bir şeye çarpıp çarpmadığınızı görmek için sadece 10 ayaklık bir çubukla prodding yaptığınızdan File.exists () kullanırsınız.

Teknik olarak aynı sonuçları bir deneme yakalamasında sararak ve dosyayı varmış gibi kullanarak başarabilirsiniz, ancak A) istisnalar genellikle kaynak açısından zordur ve B) programcılar dosyanın varsa var olduğunu düşündüğünüzü varsayarlar. bir programın genel karışıklığına katkıda bulunan bir try catch.

Bir veritabanından bazı değer getiren bir yöntem yazacağım birçok durum vardır. Bin şey yanlış gidebilir ve sadece küçük bir bilgiye nasıl ihtiyacım olduğunu görünce, 5 farklı istisna içeren bir deneme yakalama listesi ile çağrıyı çevrelemek uygun değildir. Yani, getirme yönteminde istisnalar yakalayacağım. Bir şeyler ters giderse, veritabanı bağlantısını veya nihayet yan tümcesinde neyi kapatmak ve null değerini döndürmek için uygun eylemi gerçekleştiririm. Bu sadece kodunuzu basitleştirdiği için değil, aynı zamanda "null" ifadesinin bir istisnadan almış olabileceğiniz aynı mesajı gönderdiği için bir şey planlandığı gibi gitmediği için iyi bir uygulamadır. Getirme yönteminde istisna özelliklerini yönetin, ancak işler yapmadığında ne yapacağınızı yönetin '

Örneğin:

Integer getUserCount() {
   Integer result = null;
   try {
      // Attempt to open database and retrieve data
   } catch (TimeoutException e) {
      logger.error("Got a watch?");
   } catch (MissingDatabaseException e) {
      logger.error("What are you smoking?");
   } catch (PermissionsToReadException e) {
      logger.error("Did you *really* think you were getting away with that?");
   } catch (PressedSendButtonToHardException e) {
      logger.error("Seriously.. just back away from the computer... slowly..");
   } catch (WTFException e) {
      logger.error("You're on your own with this one.. I don't even know what happened..");
   } finally {
      // Close connections and whatnot
   }
   return result;
}

void doStuff() {
   Integer result = getUserCount();
   if(result != null) {
       // Went as planned..
   }
}

6
File.exists () kullanır ve sonuca güvenirseniz, dosya File.exists () ile File.open () arasında doğrudan silinirse bir yarış durumu oluşabilir. Bu güvenlik açısından kritik bir hatayı tetiklerse, bir saldırgan bu duruma bilerek neden olabilir. Bu nedenle, operasyonu atomik tutmak, yani denemek ve istisnayı yakalamak bazen daha iyidir.
user281377

1
Ayrıca, uygulamanın çalışması için bulunması gereken dosyalar da vardır. Bunlar istisnai koşullar olurdu. Uygulamanın çalışması için sahip olmanız gereken bir dosya varsa, bu dosyadan okumamanız ve sonra istisnai durumun istisnasını işlememeniz için hiçbir neden yoktur. Niyetin daha açık olduğuna inanıyorum.
Thomas Owens

Bu null dönmek için kötü bir karar. Bir noktada NullPointerException ile sonuçlanacak ve neyin yanlış gittiğini ayıklamak gerçekten zor olacak. Çünkü birisi bir noktada boş kontrolü unutur.
deadalnix

@ deadalnix: Aksi takdirde bir try-catch ile çevreyi kolayca unutabileceğinizi iddia edebilirim. Fark işlevsellik değil, bir stil meselesidir.
Neil

@ ammoQ: Katılmıyorum. File.exists () ve kullanmadan önce silinmesi nadir durumlarda, bir istisna daha uygun olduğunu düşünüyorum. Aradaki fark yakalamanızı koruduğunuz yer. Günlüğe kaydetmek ve raporlamak için beklenmedik hatalar için basit bir istisna yakalayıcıya sahip olmanız yeterlidir.
Neil

-5

evet doğru kullanım, çalışma zamanı istisnaları iyi bir uygulama değildir. nedeni pahalı / bellek yoğun olarak kabul edilir.


5
Merhaba prassee, cevabınızı biraz açıklayabilir misiniz? Gerçeklerle, referanslarla veya deneyimlerle desteklenmeyen tek gömlekler çok yararlı değildir.
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.