Sağlanan kodun bulunduğu durumu düşünelim:
public void delete() throws IOException, SQLException { // Non-Compliant
/* ... */
}
Buradaki tehlike, aramak için yazdığınız kodun şöyle delete()
görünmesidir:
try {
foo.delete()
} catch (Exception e) {
/* ... */
}
Bu da kötü. Ve istisna sınıfını temel alan bayraklara işaret eden başka bir kuralla yakalanacak.
Anahtar, başka yerde kötü kod yazmak istemenize neden olan kod yazmamaktır.
Karşılaştığınız kural oldukça yaygın bir kuraldır. Checkstyle tasarım kurallarına sahiptir:
ThrowsCount
Kısıtlamalar ifadeleri belirtilen bir sayıya atar (varsayılan olarak 1).
Gerekçe: İstisnalar, bir yöntemin arayüzünün bir parçasını oluşturur. Çok fazla farklı köklü istisnalar atmak için bir yöntem belirtmek istisnaları istisna hale getirir ve catch gibi kod yazma gibi kötü programlama uygulamalarına yol açar (İstisna ex). Bu kontrol, geliştiricilerin istisnaları bir hiyerarşiye koymaya zorlar; öyle ki en basit durumda, yalnızca bir istisna türünün bir arayan tarafından kontrol edilmesi gerekir, ancak gerekirse herhangi bir alt sınıfın yakalanması gerekir.
Bu tam olarak sorunu ve sorunun ne olduğunu ve neden yapmamanız gerektiğini açıklar. Birçok statik analiz aracının tanımlayacağı ve işaretleyeceği iyi kabul edilmiş bir standarttır.
Eğer ederken olabilecek dil tasarımına göre bunu, ve orada olabilir bunu yapmak için doğru şey olduğunda kat, bunu görüp hemen dönmeli şeydir "um, bunu neden yapıyorum?" Herkesin asla yetmeyeceği kadar disiplinli olduğu iç kurallar için kabul edilebilir catch (Exception e) {}
, ancak daha çok, insanların özellikle iç ortamlarda köşelerini kestiklerini görmediğimden daha sık.
Sınıfınızı kullanan kişilerin kötü kod yazmak istememelerini sağlayın.
Bunun öneminin Java SE 7 ve sonrasında azaltıldığını belirtmeliyim, çünkü tek bir catch ifadesi birden fazla istisna yakalayabilir ( Birden Fazla İstisna Türünü Yakalama ve Oracle'dan Geliştirilmiş Tip Denetimi ile İstisnaları Yeniden İnceleme ).
Java 6 ve önceki sürümlerde, şuna benzeyen bir kodunuz olurdu:
public void delete() throws IOException, SQLException {
/* ... */
}
ve
try {
foo.delete()
} catch (IOException ex) {
logger.log(ex);
throw ex;
} catch (SQLException ex) {
logger.log(ex);
throw ex;
}
veya
try {
foo.delete()
} catch (Exception ex) {
logger.log(ex);
throw ex;
}
Java 6 ile bu seçeneklerin hiçbiri ideal değil. Birinci yaklaşım ihlal KURU . Birden fazla blok aynı şeyi tekrar tekrar yapıyor - her istisna için bir kez. İstisnayı günlüğe kaydetmek ve yeniden açmak ister misiniz? Tamam. Her istisna için aynı kod satırı.
İkinci seçenek birkaç nedenden dolayı daha kötü. İlk olarak, tüm istisnaları yakaladığınız anlamına gelir. Boş gösterici orada yakalanır (ve olmamalıdır). Ayrıca, bir yeniden atma vardır Exception
yöntem imzası olacağını hangi araçlar deleteSomething() throws Exception
sadece şimdi vardır kodunuzu kullanan kişiler olarak yığını daha yukarı bir karışıklık yapar zorla etmek catch(Exception e)
.
Java 7 ile bu kadar önemli değildir çünkü bunun yerine:
catch (IOException|SQLException ex) {
logger.log(ex);
throw ex;
}
Dahası, biri olmadığını kontrol tipi gelmez istisnalar türlerini yakalamak atılan:
public void rethrowException(String exceptionName)
throws IOException, SQLException {
try {
foo.delete();
} catch (Exception e) {
throw e;
}
}
Tip denetleyicisi bunun yalnızca veya türünde e
olabileceğini tanır . Bu tarzın kullanımı konusunda hala çok fazla hevesli değilim, ancak Java 6'da olduğu gibi kötü bir koda neden olmuyor (burada, yöntem imzasını istisnaların genişlettiği üst sınıf olmaya zorlar).IOException
SQLException
Tüm bu değişikliklere rağmen, birçok statik analiz aracı (Sonar, PMD, Checkstyle) hala Java 6 stil rehberlerini uygulamaktadır. Bu kötü bir şey değil. Bunların hala uygulanmaları yönünde bir uyarıda bulunma eğilimindeyim , ancak ekibinizin önceliklerine göre onlara göre önceliği büyük veya küçük olarak değiştirebilirsiniz.
İstisnalar kontrol veya kontrolsüz şekilde olursa ... o meselesidir g r e bir t tartışmayı kolayca Tartışmanın her tarafını kaplıyor sayısız blog postaları bulabilir. Ancak, işaretli istisnalar ile çalışıyorsanız, en azından Java 6'nın altında birden fazla tür atmaktan kaçınmanız gerekir.