İşaretli bir istisna yakalamak ve bir RuntimeException oluşturmak iyi bir uygulama mıdır?


70

Bir meslektaşımın bazı kodlarını okudum ve sık sık çeşitli istisnalar yakaladığını ve ardından her zaman bir 'RuntimeException' attığını öğrendim. Her zaman bunun çok kötü bir uygulama olduğunu düşündüm. Yanlış mıyım?


17
"Kontrol edilen istisnaların fiyatı, Açık / Kapalı Prensip ihlalidir. Kodunuzdaki bir yöntemden işaretli bir istisna atarsanız ve alıcı, üç düzeyden daha yüksekse, bu istisnayı siz ve alıcı arasındaki imzada bu istisnayı beyan etmelisiniz. Bu, yazılımın düşük seviyesindeki bir değişikliğin, birçok üst seviyedeki imza değişikliklerini zorlayabileceği anlamına geliyor. ” —Robert C. Martin, «Temiz Kod», sayfa 107
Songo

6
Jim Waldo'nun "Java: The Good Parts" ' daki denetlenmeyen istisnalara karşı övgüyle karşılanması dikkat çekicidir . Sadece 6 yıl önce çıktığımızda JUG'muzda okuduk ve iyi bir tavsiye gibi göründü! Şimdi, fonksiyonel programlama ile, kontrol edilen istisnalar tamamen hantaldır. Scala ve Kotlin gibi diller bile yok. Kontrol edilmeyen istisnalar dışında da kontrol etmeye başladım.
GlenPeterson,

@GlenPeterson ayrıca, tamamıyla yürütmelerden kaçınmak ve bunun yerine toplam türlerini kullanmak için FP'de tavsiyede bulunur
jk.

Fonksiyonel arayüzleri bariz durum da var: yerleşik fonksiyonel arayüzler (yani Function, Predicateparametrize sahip olmayan, vs.) maddeleri atar. Bu , herhangi bir stream () yönteminin iç döngüsünde işaretli istisnaları yakalamanız, sarmanız ve tekrar taramanız gerektiği anlamına gelir . Bu, kendi başına, kontrol edilen istisnaların kötü bir fikir olup olmadığı konusunda benim için dengeyi sağlar.
Joel Cornett

İstisna yoluyla anlam iletmek için RuntimeException özel alt sınıfları oluştururken yanlış bir şey yok.
Joel Cornett

Yanıtlar:


55

Meslektaşınızın yanlış bir şey yapıp yapmadığını bilmek için yeterli bağlamı bilmiyorum, bu yüzden genel anlamda tartışacağım.

Denetlenen istisnaları çalışma zamanı istisnasının bir lezzetine dönüştürmenin her zaman yanlış bir uygulama olduğunu sanmıyorum . İşaretli istisnalar vardır genellikle kötüye ve istismar geliştiriciler tarafından.

Kullanılmadığı durumlarda kontrol edilen istisnaları kullanmak çok kolaydır (kurtarılamaz koşullar ve hatta kontrol akışı). Özellikle, arayan kişinin iyileşemediği durumlar için işaretli bir istisna kullanılırsa, bu istisnayı yararlı bir mesaj / durumla çalışma zamanı istisnasına dönüştürmenin haklı olduğunu düşünüyorum. Maalesef, çoğu durumda kurtarılamaz bir durumla karşı karşıya kaldığınızda, yapabileceğiniz en kötü şeylerden biri olan boş bir toplama bloğu olma eğilimindedir. Böyle bir konuda hata ayıklama bir geliştiricinin karşılaşabileceği en büyük acılardan biridir.

Dolayısıyla, kurtarılabilir bir durumla karşı karşıya olduğunuzu düşünüyorsanız, uygun şekilde ele alınmalı ve istisna bir çalışma zamanı istisnasına dönüştürülmemelidir. Eğer kontrol edilemeyen bir istisna, kurtarılamaz koşullar için kullanılıyorsa, onu bir çalışma zamanı istisnasına dönüştürmek haklı çıkar .


17
Gerçek hayattaki çoğu uygulamada, kurtarılamayan çok az koşul vardır. Neredeyse “Tamam, bu işlem başarısız oldu, bu yüzden güzel bir hata mesajı gösterdik / günlüğe koyuyoruz ve bir sonraki için bekledik / bekle” diyebildiğiniz ve söylemeniz gereken bir seviye var.
Michael Borgwardt 24:11

6
Bu doğru, @MichaelBorgwardt, ancak bu tür işlemlerin yeri genellikle uygulamanın en üst seviyesindedir, bu nedenle geliştiricilerin istisnaları daha düşük seviyelerde "işlem" gördüğümde, işlemeyi kaldırmak ve istisnayı delmek genellikle kolaydır yukarı. Örneğin, JSF gibi bir web çerçevesi en üst düzeyde istisnaları yakalar, günlük mesajlarını yazdırır ve diğer istekleri işlemeye devam eder (varsayılan işlemenin uygun olduğunu söyleyerek değil, sadece bir örnek).
DavidS

40

Bu İYİ olabilir . Lütfen oku:

http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html

Müşteri kodu çoğu zaman SQLExceptions ile ilgili hiçbir şey yapamaz. Bunları denetlenmeyen istisnalara dönüştürmekte tereddüt etmeyin. Aşağıdaki kod parçasını göz önünde bulundurun:

public void dataAccessCode(){
  try{
      ..some code that throws SQLException
  }catch(SQLException ex){
      ex.printStacktrace();
  }
} 

Bu catch bloğu sadece istisnayı bastırır ve hiçbir şey yapmaz. Gerekçe, müşterimin bir SQLException hakkında yapabileceği bir şey olmamasıdır. Aşağıdaki şekilde onunla başa çıkmaya ne dersiniz?

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
} 

Bu, SQLException'ı RuntimeException'a dönüştürür. SQLException oluşursa, catch cümlesi yeni bir RuntimeException atar. Yürütme iş parçacığı askıya alındı ​​ve kural dışı durum bildirildi. Bununla birlikte, özellikle bir SQLException ile ilgili hiçbir şey yapamadığı için, iş nesnesi katmanımı gereksiz istisnalarla meşgul etmiyorum. Eğer yakalamam, root istisna nedenine ihtiyaç duyarsa, JDK1.4'ten itibaren tüm istisna sınıflarında bulunan getCause () metodunu kullanabilirim.

İşaretli istisnaları atmak ve ondan kurtulamamak yardımcı olmuyor.

Bazı insanlar bile kontrol edilen istisnaların hiç kullanılmaması gerektiğini düşünüyor. Bkz http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html

Son zamanlarda, Bruce Eckel ve Rod Johnson da dahil olmak üzere saygın bazı uzmanlar, açık bir şekilde, ilk kez kontrol edilen istisnalar üzerindeki ortodoks konumla tamamen aynı fikirdeyken, kontrol edilen istisnaların özel kullanımının, olduğu kadar iyi bir fikir olmadığı sonucuna vardıklarını açıkça belirtti. İlk başta ortaya çıktı ve kontrol edilen istisnalar birçok büyük proje için önemli bir sorun kaynağı haline geldi. Eckel, tüm istisnaların kontrol edilmemesi gerektiğini öne sürerek daha uç bir görüşe sahip; Johnson'ın görüşü daha muhafazakar, ancak yine de kontrol edilen istisnalar için ortodoks tercihin aşırı olduğunu gösteriyor. (Java teknolojisini kullanma konusunda neredeyse kesinlikle deneyime sahip olan C # mimarlarının, dil tasarımından kontrol edilen istisnaları dışlamayı seçerek tüm istisnaları kontrolsüz istisnalar yapmayı seçtiklerini belirtmek gerekir.

Aynı linkten ayrıca:

Denetlenmeyen istisnalar kullanma kararı karmaşık bir karardır ve bariz bir cevap olmadığı açıktır. Güneş tavsiyesi onları bir hiç için kullanmaktır, C # yaklaşımı (Eckel ve diğerlerinin de hemfikir olduğu) onları her şey için kullanmaktır. Diğerleri "Orta bir zemin var" diyor.


13

Hayır yanlış değilsin. Uygulaması son derece yanlış yönlendirilmiş. Buna neden olan sorunu yakalayan bir istisna atmalısınız. RunTimeException geniş ve kapsamlı. NullPointerException, ArgumentException vb. Olmalıdır. Neyin yanlış gittiğini doğru bir şekilde açıklayan ne varsa. Bu, ele almanız gereken sorunları ayırt etme ve programın “Geçme” senaryosu olması gereken hatalara karşı hayatta kalmasını sağlar. Yaptığı şey, soruda verilen bilgilerde eksik olan bir şey olmadığı sürece, "Sonraki Sırada Devam Ediyor" dan biraz daha iyidir.


1
İpucu için teşekkürler. Ve ya doğrudan RuntimeException'dan miras alan, uyguladığı özel bir istisna atarsa?
RoflcoptrException

27
@Gary Buyn: birçok kişi kontrol istisna başarısız bir dil tasarım deney olduğunu düşünüyorum ve onlar değil alışkanlık meselesi olarak, idareli kullanılması gereken olanlardır.
Michael Borgwardt 23:11

7
@Gary Buyn: İşte tartışmayı oldukça iyi anlatan bir makale: ibm.com/developerworks/java/library/j-jtp05254/index.html Java’nın bu özelliği sunmasından 15 yıldan fazla bir süre sonra, başka hiçbir dilde benimsemediğini not edin. ve C ++ da benzer bir özelliği kullanımdan kaldırmıştır.
Michael Borgwardt

7
@c_maker: Aslında, Bloch çoğunlukla ortodoks görüşü teşvik ediyor ve yorumunuz daha çok istisna, dönem kullanmakla ilgili gibi görünüyor. Benim görüşüme göre, kontrol edilen bir istisna kullanmak için geçerli tek neden, tüm arayanların hemen ilgilenmesini beklediğiniz bir durum olduğudur.
Michael Borgwardt

14
Gereksiz yere atma kontrol istisnaları, kapsüllemeyi ihlal ediyor. 'GetAccounts ()' gibi basit bir yöntem size 'SQLException', 'NullPointerException' veya 'FileNotFoundException' gibi basit bir yöntem atarsa ​​ne yaparsınız? Onunla başa çıkabilir misin? Muhtemelen sadece 'yakalamak (İstisna e) {}'. Ayrıca, bu istisnalar - uygulamasına özel! Sözleşmenin bir parçası olmamalıdır! Tüm bilmeniz gereken bir hata olduğu . Peki ya uygulama değişirse? Birdenbire her şey değişmeli, çünkü yöntem artık 'SQLException'ı değil, yerine' ParseXMLException'ı atıyor!
KL

8

Değişir.

Bu uygulama bile akıllıca olabilir . Bazı istisnalar olursa (örneğin web geliştirmede) birçok durum vardır, bazı istisnalar olursa, hiçbir şey yapamazsınız (örneğin tutarsız DB'yi kodunuzdan onaramazsınız çünkü :-), sadece geliştirici bunu yapabilir). Bu gibi durumlarda, atılan istisnayı çalışma zamanı istisnasına sarmak ve yeniden başlatmak akıllıca olur. Bir istisna işleme katmanında tüm bu istisnaları yakalayabildiğinizden, hatayı günlüğe kaydedin ve kullanıcıya hoş bir yerelleştirilmiş hata kodu + mesajı gösterin.

Öte yandan , istisna çalışma zamanı değilse (işaretli ise), API geliştiricisi bu istisnanın çözülebilir olduğunu ve onarılması gerektiğini belirtir. Mümkünse, kesinlikle yapmalısınız.

Diğer çözüm, bu kontrol edilen istisnayı çağıran katmana yeniden atmak olabilir, ancak bunu çözemediyseniz, istisnanın gerçekleştiği yerde, burada da çözemezsiniz ...


API geliştiricisinin ne yaptığını bildiğini ve kontrol edilen istisnaları iyi kullandığını umarsınız. İstemcinin isterse yakalama seçeneğine sahip olması için belgelendirme sırasında çalışma zamanı istisnalarını atma lehine API'ler görmeye başladım.
c_maker

Bir istisna atan bir yöntem genellikle bir arayanın ondan iyileşip iyileşemeyeceğini bilemez. Öte yandan, bir yöntemin yalnızca, iç yöntemin neden istisnayı attığını biliyorsa ve neden dış yöntemin API'sı ile tutarlı olduğunu biliyorsa, kaçmak için bir iç yöntem tarafından atılan kontrol edilen bir istisna olmasına izin vermesini öneririm. Eğer bir iç yöntem beklenmedik bir şekilde kontrol edilen bir istisna atarsa, kontrol edilen bir istisna olarak kabarcıklı kalmasına izin vermek, arayanı olanlarla ilgili yanlış bilgilendirilmiş bırakabilir.
supercat

2
Bahsettiğiniz için teşekkür ederiz exception handling layer- örneğin bir web uygulamasında, bir filtrede.
Jake Toronto,

5

Bu konuda yorum yapmak istiyorum, ancak bunun mutlaka kötü bir uygulama olmadığı zamanlar olduğunu biliyorum. (Ya da çok kötü). Ama belki yanılıyorum.

Çoğu zaman, kullandığınız bir API, kendi özel kullanım alanınıza gerçekten atıldığını hayal edemediğiniz bir istisna oluşturacaktır. Bu durumda, nedeni olarak istisna olan bir RuntimeException'ı atmak tamamen iyi görünüyor. Bu istisna atılırsa, büyük olasılıkla programlama hatasının nedeni olacaktır ve doğru şartname için sınırların içinde değildir.

RuntimeException uygulamasının daha sonra yakalanmadığını ve yok sayılmadığını varsayarsak, OnErrorResumeNext'in yakınında değil.

OnErrorResumeNext, birileri bir istisna yakaladığında ve bunu görmezden geldiğinde ya da yalnızca yazdırdığında ortaya çıkar. Bu hemen hemen tüm durumlarda çok kötü bir uygulamadır.


Bu, arama ağacının tepesine yakın bir durumda olabilir; yapabileceğiniz tek şey, nezaketle kurtarmayı denemek ve belirli bir hatayı bilmek gerçekten yardımcı olmaz. Bu durumda, hatayı kaydetmeniz ve devam etmeniz gerekebilir (bir sonraki kaydı işleyin, kullanıcıyı bir hatanın meydana geldiği konusunda bilgilendirin, vb.). Aksi takdirde, hayır. İstisnaları her zaman hataya yakın pratikte kullanmalı, bir sonraki işleyiciye beyaz bir fil gibi sarmamalısınız.
Michael K

@MichaelK Sorun "pratikte olduğu kadar hataya yakın" pratikte genellikle "doğrudan kontrolünüz dışında olan birkaç araya giren katmanlar" anlamına gelir. Örneğin, eğer sınıfım belirli bir arayüz uygulamak zorundaysa, ellerim bağlı. Bu, arama ağacında keyfi olarak derinlerde olabilir. Arayüzler benim kontrolüm altında olsa bile, fırlatma bildirileri eklemek, düşünülebilir, ancak makul bir şekilde fırlatabilecek somut uygulamalar kümesi varsa sızdırabilir. Her müşteriye birkaçının uygulama detayının bedelini ödetmesi IMO için çok iyi bir tasarım değişikliği değil.
Tim Seguine

4

TL; DR

Öncül

  • Hata düzeltilemediğinde çalışma zamanı istisnaları atılmalıdır: hata koddayken ve dış duruma bağlı olmadığında (bu nedenle kurtarma kodu düzeltir).
  • Kod doğru olduğunda kontrol edilen istisnalar atılmalıdır, ancak dış durum beklendiği gibi olmamalıdır: ağ bağlantısı yok, dosya bulunamadı veya bozuk vb.

Sonuç

Yayılma ya da arayüz kodu, temeldeki uygulamanın açıkça olmadığı durumlarda dış duruma bağlı olduğunu varsayarsa, kontrol edilen bir istisnayı çalışma zamanı istisnası olarak yeniden yazabiliriz.


Bu bölümde, istisnalardan birinin ne zaman atılacağı konusu ele alınmaktadır. Sonuç için daha ayrıntılı bir açıklama okumak istiyorsanız bir sonraki yatay çubuğa geçebilirsiniz.

Çalışma zamanı istisnası atmak ne zaman uygundur? Kodun yanlış olduğu ve kurtarma işleminin kodu değiştirerek uygun olduğu açık olduğunda bir çalışma zamanı istisnası atarsınız.

Örneğin, aşağıdakiler için bir çalışma zamanı istisnası atmak uygun olur:

float nan = 1/0;

Bu, sıfır çalışma zamanı istisnasına göre bir bölünme atacaktır. Bu uygundur, çünkü kod hatalı.

Örneğin, yapıcının bir kısmı HashMap:

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                loadFactor);
    // more irrelevant code...
}

Başlangıçtaki kapasiteyi veya yük faktörünü düzeltmek için, doğru değerlerin girildiğinden emin olmak için kodu düzenlemeniz uygundur. Diskin mevcut durumuna bağlı olarak uzaktaki bazı sunuculara bağlı değildir. bir dosya veya başka bir program. Bu yapıcı geçersiz argümanlarla çağrılıyor, çağıran kodun doğruluğuna bağlı olarak, yanlış parametrelere veya yanlış bir hataya neden olan uygunsuz akışa yol açan yanlış bir hesaplama yapılır.

Kontrol edilen bir istisna atmak ne zaman uygundur? Sorun zaman bir kontrol istisna olan kodu değiştirmeden geri kazanılabilir. Veya farklı terimlerle ifade etmek gerekirse, kod doğruyken hata durumla ilgili olduğunda işaretli bir istisna atarsınız.

Şimdi "kurtarma" kelimesi burada zor olabilir. Hedefe ulaşmak için başka bir yol bulduğunuz anlamına gelebilir: Örneğin, eğer sunucu cevap vermezse, bir sonraki sunucuyu denemelisiniz. Eğer durumunuz için bu tür bir kurtarma mümkün ise, o zaman bu harikadır, ancak kurtarma işleminin tek yolu bu değildir - kurtarma, kullanıcıya ne olduğunu açıklayan bir hata iletişim kutusu görüntülüyor olabilir ya da bu bir sunucu uygulamasıysa bu olabilir. Yöneticiye bir e-posta göndermek veya sadece hatayı uygun ve tam olarak kaydetmek.

Mrmuggles'ın cevabında bahsedilen örneği ele alalım:

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
}

Bu, kontrol edilen istisnayı ele almanın doğru yolu değildir. Bu yöntemin kapsamındaki istisnayı ele alma konusundaki yetersizlik , uygulamanın çökmesi gerektiği anlamına gelmez. Bunun yerine, bunun gibi daha yüksek bir kapsamda yayılması uygundur:

public Data dataAccessCode() throws SQLException {
    // some code that communicates with the database
}

Arayan tarafından kurtarma imkanı sağlayan:

public void loadDataAndShowUi() {
    try {
        Data data = dataAccessCode();
        showUiForData(data);
    } catch(SQLException e) {
        // Recover by showing an error alert dialog
        showCantLoadDataErrorDialog();
    }
}

Kontrol edilen istisnalar statik bir analiz aracıdır, bir programcının belirli bir çağrıda neyin yanlış gidebileceğini, uygulamayı öğrenmelerini veya bir deneme yanılma sürecinden geçmelerini gerektirmeden açıkça belirtirler. Bu, hata akışının hiçbir bölümünün göz ardı edilmemesini sağlamayı kolaylaştırır. Kontrol edilmiş bir istisnayı çalışma zamanı istisnası olarak yeniden görüntülemek, emek tasarrufu sağlayan bu statik analiz özelliğine karşı çalışıyor.

Çağıran katmanın yukarıda gösterildiği gibi daha büyük şema şemasının daha iyi bir bağlamına sahip olduğunu belirtmekte fayda var. Çağrılacak birçok neden olabilir dataAccessCode, aramanın özel nedeni sadece arayanlar tarafından görülebilir - bu nedenle başarısızlığın ardından doğru iyileşme konusunda daha iyi bir karar verebiliyor.

Şimdi bu ayrımı netleştirdiğimize göre, kontrol edilmiş bir istisnayı çalışma zamanı istisnası olarak yeniden başlatmanın uygun olduğu durumlarda karar vermeye devam edebiliriz.


Yukarıda verilenlere göre, bir RuntimeException olarak işaretli bir istisnayı yeniden ne zaman uygun görmek gerekir? Kullanmakta olduğunuz kod dış duruma bağımlı olduğunu varsaydığında, ancak dış duruma bağlı olmadığını açıkça belirtebilirsiniz.

Aşağıdakileri göz önünde bulundur:

StringReader sr = new StringReader("{\"test\":\"test\"}");
try {
    doesSomethingWithReader(sr); // calls #read, so propagates IOException
} catch (IOException e) {
    throw new IllegalStateException(e);
}

Bu örnekte, kodun yayılması, IOExceptionçünkü API'si Readerdış duruma erişmek için tasarlandı, ancak StringReaderuygulamanın dış duruma erişmediğini biliyoruz . Çağrıda yer alan kısımların IO'ya veya başka bir dış duruma erişmediğini kesinlikle iddia edebileceğimiz bu kapsamda, istisnaları uygulamalarımızdan habersiz (ve muhtemelen GÇ erişim kodunun atacağını varsayarak bir IOException).


Dış devlete bağlı istisnaları kesin olarak kontrol altında tutmanın nedeni, deterministik olmadıklarıdır (mantık bağımlı istisnaların aksine, kodun bir sürümü için her zaman tahmin edilebilir şekilde çoğaltılacaktır). Örneğin, 0'a bölmeye çalışırsanız, her zaman bir istisna oluşturacaksınız. Eğer 0'a bölmezseniz, asla bir istisna üretmezsiniz ve bu istisna vakasını ele almanız gerekmez, çünkü asla gerçekleşmez. Bununla birlikte, bir dosyaya erişme durumunda, bir kez başarılı olmak, bir dahaki sefere başarılı olacağınız anlamına gelmez - kullanıcı izinleri değiştirmiş olabilir, başka bir işlem dosyayı silmiş veya değiştirmiş olabilir. Bu yüzden, her zaman bu istisnai durumla başa çıkmak zorunda kalırsınız veya muhtemelen bir hata yaşarsınız.


2

Bağımsız uygulamalar için. Uygulamanızın, kontrol edilen RuntimeException'ı atmak yerine yapabileceğiniz istisnayı çözemediğini bildiğinizde, Hata atmak, uygulamanın çökmesine izin vermek, hata raporları için umut vermek ve uygulamanızı düzeltmek. (Bkz cevabı ait mrmuggles yanlısı ve con kontrolsüz karşı kontrol ait bir daha derinlemesine tartışma için.)


2

Bu, pek çok çerçevede yaygın bir uygulamadır. Örneğin Hibernate, tam olarak bunu yapar. Buradaki fikir, API'lerin istemci tarafı için müdahaleci olmaması ve müdahaleci olmaması gerektiğidir Exception, çünkü api olarak adlandırdığınız yerde bunları işlemek için açıkça kod yazmanız gerekir. Ancak, bu yer istisnayı ilk başta ele almak için doğru yer olmayabilir.
Aslında dürüst olmak gerekirse, bu "sıcak" bir konudur ve birçok anlaşmazlık vardır, bu yüzden taraf tutmayacağım ama arkadaşınızın yaptığı / önerdiği şeyin sıradışı veya sıradışı olmadığını söyleyeceğim.


1

"Kontrol edilen istisna" olayının tamamı kötü bir fikirdir.

Yapısal programlama, bilginin sadece "yakın" olduklarında işlevler arasında (veya Java parlance'de yöntemler) geçirilmesine izin verir. Daha doğrusu, bilgi sadece iki şekilde fonksiyonlar arasında hareket edebilir:

  1. Arayandan toplanana, argüman geçme yoluyla.

  2. Bir arayandan arayan kişiye, dönüş değerleri olarak.

Bu temelde iyi bir şey. Yerel olarak kodunuz hakkında akıl yürütmenize izin veren şey şudur: programınızın bir bölümünü anlamanız veya değiştirmeniz gerekirse, yalnızca o kısma ve diğer "yakındaki" bölümlere bakmanız gerekir.

Bununla birlikte, bazı durumlarda, “bilinmeyen” ortadaki hiç kimse olmadan bilgiyi “uzak” bir işleve göndermek gerekir. Bu tam olarak istisnaların kullanılması gerektiği zamandır. Bir istisna olan gizli bir gönderilen mesaj raiser (Kodunuzun kısmı içerebilir olursa olsun throwbir karşı bildiri) işleyicisi (Kodunuzun kısmı içerebilir olursa olsun catcholdu istisna ile uyumludur bloğu thrown).

Kontrol edilen istisnalar, mekanizmanın gizliliğini ve onunla birlikte varoluş nedenini tahrip eder. Eğer bir işlev, arayan kişiye bir bilgi parçasını "bilmesini" sağlayabilirse, bu bilgiyi doğrudan geri dönüş değerinin bir parçası olarak gönderin.


Bir yöntemin, arayan tarafından sağlanan bir işlevi yerine getirmesi durumunda, bu tür bir sorunun gerçekten büyük hasara yol açabileceğinden bahsetmek iyi olabilir. İşlevi alan yöntemin yazarı, çoğu durumda, arayanın ne yapmasını beklediğini, ne de arayanın beklediği gibi bir şeyi umursamayacak hiçbir nedene sahip değildir. Yöntemi alan kodun işaretli bir istisna atmasını beklememesi durumunda, tedarik edilen yöntemin, tedarikçisinin yakalayabileceği denetlenmeyen istisnalar içine atabileceği işaretlenmiş istisnaları sarması gerekebilir.
supercat,

0

Bu duruma göre değişebilir. Bazı senaryolarda, arkadaşınızın ne yaptığını yapmak akıllıca olacaktır, örneğin bazı müşteriler için bir api gösterdiğinizde ve bazı uygulama istisnalarının özel olabileceğini bildiğiniz durumlarda, müşterinin uygulama detaylarından en az haberdar olmasını istediğinizde Uygulama detayları ve müşteriye açıklanamaz.

Kontrol edilen istisnaları engelleme dışında bırakarak, müşterinin istisnai koşulları önceden doğrulamış olabileceği için müşterinin daha temiz kod yazmasını sağlayacak api'yi açığa çıkarabilirsiniz.

Örneğin, Integer.parseInt (String) bir dize alır ve tamsayıya eşdeğerini döndürür ve dizenin sayısal olmaması durumunda NumberFormatException değerini döndürür. Şimdi, bir alanla birlikte bir form gönderiminin agebu yöntemle dönüştürüldüğünü hayal edin , ancak müşteri kendi tarafında zaten doğrulama sağladı, bu nedenle istisna kontrolünü zorlamanın bir anlamı yoktu.


0

Burada gerçekten birkaç soru var.

  1. Kontrol edilen istisnaları kontrol edilmeyenlere dönüştürmelisiniz?

Genel kural, arayanın yakalaması ve kurtarması beklenen istisnaların kontrol edilmesi gerektiğidir. Diğer istisnalar (tek makul sonucun bütün operasyonu iptal etmek olduğu ya da özellikle onları idare etmekten endişe duymayacağının yeterince düşük olduğunu düşündüğünüz yerler) kontrol edilmemelidir.

Bazen bir istisnanın yakalamayı ve kurtarmayı hak edip etmediği konusundaki kararınız, birlikte çalıştığınız API'den farklıdır. Bazen bağlam önemlidir, bir durumda ele almaya değer bir istisna başka bir durumda ele almaya değmeyebilir. Bazen eliniz mevcut arayüzler tarafından zorlanır. Öyleyse evet, kontrol edilen bir istisnayı kontrol edilmeyen istisnalara (veya farklı türde kontrol edilen istisnalara) dönüştürmenin yasal nedenleri var

  1. Denetlenmeyen bir istisnayı işaretlenmiş istisnaya dönüştürecekseniz, nasıl yapmalısınız.

Öncelikle ve en önemlisi istisna zincirleme tesisini kullandığınızdan emin olun. Bu şekilde, orijinal istisnadan elde edilen bilgiler kaybolmaz ve hata ayıklama için kullanılabilir.

İkincisi, hangi istisna türünü kullanacağınıza karar vermelisiniz. Düz bir runtimeexception kullanmak, arayanın neyin yanlış gittiğini tespit etmesini zorlaştırır, ancak arayan kişi neyin yanlış gittiğini belirlemeye çalışıyorsa, kontrol etmemek için istisnayı değiştirmemesi gerektiğinin bir göstergesi olabilir.


0

Boolean bir soruda, tartışmalı iki cevabın ardından farklı cevaplar vermek zor, ama birkaç yerde bile olsa, sahip olduğu önem için yeterince vurgulamadığı bir bakış açısı vermek istiyorum.

Yıllar boyunca, her zaman birinin önemsiz bir sorun hakkında kafasının karıştığını, bazı temel hususların anlaşılmadığını fark ettim.

Katman. Bir yazılım uygulaması (en azından olması gerekiyordu) üst üste katmanlar yığını. İyi tabakalaşma için önemli bir beklenti, alt tabakaların, üst tabakadan potansiyel olarak birden fazla bileşen için işlevsellik sağlamasıdır.

Diyelim ki uygulamanız alttan üste NET, TCP, HTTP, REST, VERİ MODELİ, İŞLETMEYE kadar aşağıdaki katmanları içeriyor.

Eğer iş katmanınız dinlenmek için bir çağrı yapmak istiyorsa ... bir saniye bekleyin. Bunu neden söyledim? Neden HTTP isteği veya TCP işlemi söylemedim ya da ağ paketleri göndermedim? Çünkü bunlar benim iş katmanım için önemli değil. Onlarla başa çıkmayacağım, onların ayrıntılarına bakmayacağım. Eğer bir sebep olarak aldığım istisnalar dışında derinlerse ve tamamlarının bile olduğunu bilmek istemiyorum.

Dahası, ayrıntıları bilmem kötü bir şey çünkü yarın eğer TCP protokolüne özgü ayrıntılarla ilgilenen altı çizili taşıma protokollerini değiştirmek istiyorum, REST soyutlamamın kendisini soyutlamak için iyi bir iş yapmadığı anlamına geliyor özel uygulama.

Bir istisnayı katmandan katmana geçirirken, onun her yönünü ve geçerli katmanın sağladığı soyutlama için ne anlam ifade edeceğini gözden geçirmek önemlidir. İstisnayı başkaları ile değiştirmek olabilir, birkaç istisna dışında olabilir. Ayrıca onları kontrol edilmeden denetlenmemiş veya tam tersi duruma geçirebilir.

Elbette, bahsettiğiniz gerçek yerlerin farklı bir hikaye olduğu, ancak genel olarak - evet, yapılması gereken iyi bir şey olabilir.


-2

Bence,

Çerçeve düzeyinde, aynı yerde istilacıya daha fazla deneme yakalama bloğunu azaltmak için çalışma zamanı istisnaları olmalıyız.

Uygulama düzeyinde, çalışma zamanı istisnalarını nadiren yakalıyoruz ve bu uygulamanın kötü olduğunu düşünüyorum.


1
Ve bu istisnalar ile çerçeve düzeyinde ne yapacaksınız?
Matthieu

Çerçevede istisnaları kaldırabilecek bir UI katmanı varsa, UI bir şeyin yanlış gittiğini gösteren bir hata mesajı sunar. Tek sayfalık bir javascript uygulaması durumunda, uygulama bir hata mesajı gösterebilir. Verilen, UI katmanının hatayı ancak daha derin bir katman gerçekten hatadan kurtaramazsa işlemesi gerekir.
Jake Toronto
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.