Bunu düşündüm ve bir örnek bulamadım. Neden biri bir istisna yakalamak istiyor ve bunun hakkında hiçbir şey yapmıyor? Bir örnek verebilir misin? Belki de asla yapılmaması gereken bir şeydir.
Bunu düşündüm ve bir örnek bulamadım. Neden biri bir istisna yakalamak istiyor ve bunun hakkında hiçbir şey yapmıyor? Bir örnek verebilir misin? Belki de asla yapılmaması gereken bir şeydir.
Yanıtlar:
Her zaman D'deki dönüştürme hataları gibi şeylerle yapıyorum:
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 sorun , istisnayı neden görmezden geldiğinizi açıklayan bir yorum olsa bile , tüm catch bloklarının içinde bir şey olması gerektiğini düşünüyorum .
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 isterim. Eski bir düz yapmak catch {}
neredeyse her zaman kötü bir şeydir.
Bir şey yapmadan, istisnayı günlüğe kaydetse bile, istisnayı yutmanın tamam olduğunu düşündüğüm bir örnek, günlük kodunun kendisindedir.
Bir şeyi kaydetmeye çalıştıysanız ve istisna aldıysanız, bu konuda yapabileceğiniz fazla bir şey yoktur:
Bu, uygulamanın ana işini yapmaya devam etmesine izin vererek, sorunu giderme yeteneğinden ödün vermesine izin vererek, sessizce yutmanın "kötülüğün en az" seçeneğine sahip olmasını sağlar.
Yine de isteğe bağlı olan bir işlem tarafından bir istisna atılırsa, yapılacak hiçbir şey olmayabilir. Giriş yapmak kullanışlı olmayabilir. Bu durumda, sadece onu yakalamak ve hiçbir şey yapmamak isteyebilirsiniz.
Bunu yapıyorsanız, bir yorum ekleyin. Her zaman bir hataya benzeyen herhangi bir şeyi yorumlayın (bir switch
ifadenin tam ortasında , boş catch
blok, bir koşulda atama).
Bunun istisnaların uygun bir kullanımı olmadığını iddia edebilirsiniz, ama bu başka bir soru için.
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:
Bu gerçekten hiçbir şey yapmadan, boş catch
bloklar için yer bırakmaz .
EKLENEN EDİLDİ : Diyelim ki istisnaları atmanın program mantığını kontrol etmenin normal yoludur (alternatiflerden biri goto
). O zaman catch
, bu dilde yazılmış bir programdaki boş bir else
blok, geleneksel bir dilde (veya hiç else
blok yok ) boş bir blok gibidir . Ancak, bunun C #, Java veya C ++ geliştirme toplulukları tarafından önerilen programlama stili olmadığını düşünüyorum.
Bazı durumlarda, Java kesinlikle hiçbir koşulda gerçekleşmeyecek bir istisnayı ele almanızı gerektirir. Bu kodu göz önünde bulundurun:
try {
bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}
Java platformunun her bir uygulaması, aşağıdaki standart tabloları desteklemek için gereklidir.
...
UTF-8
Java platformunuzu bozmadan, bu istisnaya neden olmanın hiçbir yolu yoktur. Peki neden onu rahatsız etmiyorsun? Ancak try-catch-yan tümcesini atlatamazsınız.
throw new Error(e)
hiçbir şeyi kaçırmadığımdan (ya da gerçekten kırılmış bir platformu rapor ettiğimden) kesinlikle emin olmak için cazip davranacağım .
Genel bir kural olarak, hayır. Ya istisnayı yığına atmak ya da ne olduğunu kayıt etmek istersiniz.
Ancak, bunu genellikle dizeleri ayrıştırırken ve sayılara dönüştürürken yaparım (özellikle, bir kez kullanılan ve çeşitliliği uzaklaştıran projeleri eşlerken).
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;
Bazı durumlarda istisna istisnai değildir; Aslında, bekleniyor. 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 () öğesinde isAlive () yöntemi olmadığından, hala hayatta olup olmadığını kontrol etmenin tek yolu, işlem hala çalışıyorsa bir IllegalThreadStateException'ı atan exitValue () yöntemini çağırmaktır.
Alçak gönüllü deneyimlerime göre, nadiren bu iyi şey. Kilometreler değişebilir.
Neredeyse her zaman bunu kod tabanımızda görüyordum, çünkü yenen istisnanın sakladığı bir hatayı buldum. Başka bir deyişle, herhangi bir kod sağlayarak, uygulamanın bir hata belirtme veya başka bir işlem gerçekleştirme yolu yoktur.
Bazen, örneğin API katmanlarında, istisnaların geçmişte kalmasını istemeyebilir veya izin vermeyebilirsiniz, bu durumda, en genel olanı yakalamaya çalışıp bunları günlüğe kaydederim. Bir kez daha, en azından bir hata ayıklama / teşhis oturumu için bir şans vermek.
Genellikle, boş olması gerekiyorsa, en azından yaptığım şey bir tür iddiada bulunmaktır, bu nedenle en azından bir hata ayıklama oturumu sırasında olur. Bununla başa çıkamazsam, onları tamamen göz ardı etme eğiliminde olduğumu söyledi.
IMO, boş catch ifadelerinin tamam olduğu 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
}
Boş bir yakalama yan tümcesine sahip olmanın haklı olduğu bazı durumlar olduğuna inanıyorum - bunlar, belirli bir işlem başarısız olursa kodun devam etmesini istediğiniz zamanlar olur. Ancak, bu kalıbın kolayca aşırı kullanılabileceğini düşünüyorum, bu yüzden daha iyi bir yolun kullanılmadığından emin olmak için her kullanım yakından incelenmelidir. Özellikle, programı tutarsız bir durumda bırakırsa veya daha sonra başarısız olan kodun başka bir bölümüne götürebilirse, bu kesinlikle yapılmamalıdır.
Bir istisna meydana geldiğinde bir uyarı seviyesine sahip olmadığımı sanmıyorum - programlamanın amaçlarından 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.
Bununla birlikte, diğer tarafı görüyorum, istisna kodun işlenmesinde gerçek bir zararı yoksa, kullanıcıyı neden bu duruma maruz bırakıyor? Genelde uyguladığım çözüm logger sınıfım tarafından kaydedilmektedir (işte şimdiye kadar yazdığım her sınıfta).
Benign bir istisna ise, Logger’ın .Debug () yöntemine çağrı yapıyorum; Aksi takdirde, Logger.Error () (ve (belki) atın).
try
{
doWork();
}
catch(BenignException x)
{
_log.Debug("Error doing work: " + x.Message);
}
Bu arada, günlüğümü uygulamamda, .Debug () yöntemine çağrı yapmak yalnızca App.Config dosyam program yürütme günlüğü düzeyinin Hata Ayıklama modunda olduğunu belirttiğinde, günlüğe kaydetecektir.
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, finally
yan tümce kullanıldığında:
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ıyla ilgili olan mandal bağlamanın ihmal edilmesine izin verme önerisi vardır .
Referanslar
Bunun gibi bir şeyi yapmam için tek ihtiyacım olan şey, bir konsol uygulaması için bir günlük sınıfındaydı. Hatayı STDOUT'a yayan, dosyayı bir dosyaya kaydeden, ardından uygulamayı> 0 hata koduyla kapatan bir üst düzey global catch işleyicisi vardı.
Buradaki sorun, bazen, dosyaya giriş yapmanın başarısız olmasıydı. Dizin izinleri dosyayı yazmanıza engel oldu, dosya tamamen kilitlendi, her neyse. Böyle bir durumda, istisnayı başka bir yerde bulunduğum gibi idare edemedim (özel bilgileri ayrıntılarıyla yakalayın, ilgili ayrıntıları girin , daha iyi bir istisna türünü sarın, vb.) ) zaten başarısız olan bir dosyaya yazmaya çalışıyorum. Yine başarısız olduklarında ... Nereye gittiğimi görüyorsun. Sonsuz bir döngüye girer.
Try {} bloklarından bazılarını bırakırsanız, bir mesaj kutusunda görünen istisna olabilir (sessiz bir yapılandırma uygulaması için istediğinizi değil). Bu yüzden günlük dosyasına yazan bu yöntemde, boş bir catch işleyicim var. Bu, hala> 0 hata kodunu aldığınız için hatayı gömmez, yalnızca 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, sadece unutulmaktan alevlenmekten korkuyordum. Çünkü sadece ben değilim ...)
Sonunda en kritik parçaya ne olursa olsun, bir dizinin yürütülmesi gerektiğinde durum iyidir.
Örneğin. Ana kontrol cihazına hareket kontrolü iletişimde. Acil durumlarda hareketi durdurmak, yörünge üretimini durdurmak, motorları yavaşlatmak, molaları etkinleştirmek, yükselticiyi devre dışı bırakmak ve bundan sonra veri yolu gücünü kesmek için bir takım hazırlık adımları vardır. Her şey sırayla yapılmalı ve adımlardan biri başarısız olursa, donanımın zarar görmesi tehlikesiyle bile olsa, geri kalan adımların gerçekleştirilmesi gerekir. Yukarıdakilerin hepsi başarısız olsa bile, kill bus gücünün yine de gerçekleşmesi gerektiğini söyleyin.
Hatadan kurtulmak için sistem kaynaklarını incelikle kapatma
Örneğin. Eğer kullanıcıya geri bildirimde sağlamaz arka planda bir hizmeti çalıştırıyorsanız, kullanıcıya hata bir göstergesini itmek istemeyebilir ama do zarif bir şekilde kullanılmakta olan kaynaklara göz kapatmak gerekir.
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 bunları test etmek için konsola veya bir günlük dosyasına yazdırmak için catch hata ayıklama modunda kullanırsınız. Bir üretim ortamında, arka plan hizmetlerinin genellikle bir hata atıldığında kullanıcıyı rahatsız etmemesi beklenir, bu nedenle hata çıktısının bastırılması gerekir.