it-swarm-tr.com

Bir istisna ne zaman atılır?

Başvurumun beklemediği her koşul için yaratılmış istisnalar var. UserNameNotValidException, PasswordNotCorrectException vb.

Ancak bana bu koşullar için istisnalar yaratmamam gerektiği söylendi. UML'mde bu ARE istisnaları ana akışa göre, o zaman neden bir istisna olmamalı?

İstisnalar oluşturmak için rehberlik veya en iyi uygulamalar?

405
Kwan Cheng

Kişisel rehberim şudur: mevcut kod bloğunun temel bir varsayımının yanlış olduğu tespit edildiğinde bir istisna atılır.

Örnek 1: isteğe bağlı bir sınıfı incelemek ve o sınıfın <> Listesinden miras alması durumunda true döndürmek için gereken bir işleve sahip olduğumu söylüyor. Bu işlev “Bu nesne Listenin soyundan mıdır?” Sorusunu sorar. Bu işlev hiçbir zaman bir istisna atmamalıdır, çünkü işleminde gri alan yoktur - her bir sınıf <> listesinden ya alır veya almaz, bu nedenle yanıt her zaman "evet" veya "hayır" olur.

Örnek 2: Listeyi <> inceleyen ve uzunluğu 50'den büyükse true döndüren başka bir işleve sahibim ve uzunluk daha küçükse false. Bu işlev, "Bu listede 50'den fazla öğe var mı?" Sorusunu sorar. Ancak bu soru bir varsayımda bulunur - verilen nesnenin bir liste olduğunu varsayar. NULL verirseniz, bu varsayım yanlıştır. Bu durumda, işlev dönerse ya doğru veya yanlış, o zaman kendi kurallarını çiğniyor. İşlev geri dönemez herhangi bir şey ve soruyu doğru cevapladığını iddia ediyorum. Böylece geri dönmez - bir istisna atar.

Bu, "yüklenen soru" mantıksal yanlışlıkla karşılaştırılabilir. Her fonksiyon bir soru sorar. Eğer verilen girdi bu soruyu yanlış yaparsa, bir istisna at. Bu satır, boşluğu döndüren işlevlerle çizmek daha zordur, ancak alt satır şudur: işlevin girdileri hakkındaki varsayımları ihlal edilirse, normal döndürmek yerine bir istisna atması gerekir.

Bu denklemin diğer tarafı şudur: İşlevlerinizi sık sık istisnalar atıyorsanız, muhtemelen onların varsayımlarını düzeltmeniz gerekir.

590

Çünkü onlar normal olacak şeyler. İstisnalar kontrol akış mekanizmaları değildir. Kullanıcılar genellikle şifreleri yanlış alırlar, bu istisnai bir durum değildir. İstisnalar gerçekten nadir bir şey olmalı, UserHasDiedAtKeyboard tip durumlar.

278
blowdart

Küçük rehberlerim büyük "Kod tamamlandı" kitabından etkilendi:

  • İhmal edilmemesi gereken şeyleri bildirmek için istisnalar kullanın.
  • Hata yerel olarak işlenebiliyorsa istisnalar kullanmayın
  • İstisnaların, rutininizin geri kalanıyla aynı seviyede olduğundan emin olun.
  • İstisnalar, gerçekten istisnai için ayrılmalıdır.
61
Commander Keen

Kullanıcı adı geçerli değilse veya şifre doğru değilse bir istisna değildir. Bunlar normal çalışma akışında beklemeniz gereken şeyler. İstisnalar, normal program işleminin bir parçası olmayan ve oldukça nadir olan şeylerdir.

EDIT: İstisnaları kullanmaktan hoşlanmıyorum çünkü bir yöntemin sadece aramaya bakarak bir istisna atıp atmadığını söyleyemezsiniz. Bu nedenle istisnalar yalnızca durumu iyi bir şekilde idare edemiyorsanız kullanılmalıdır (“bellek yetersiz” veya “bilgisayar yanıyor” şeklinde düşünün).

34
EricSchaefer

Temel kurallardan biri, normal olarak tahmin edemediğiniz bir durumda istisnaları kullanmaktır. Örnekler veritabanı bağlantısı, diskte eksik dosya vb. Tahmin edebileceğiniz senaryolar için, yani kötü bir parola ile giriş yapmaya çalışan kullanıcılar için, boolean döndüren ve durumu iyi bir şekilde nasıl ele alacağınızı bildiğiniz işlevleri kullanmanız gerekir. Birisi şifresini yanlış yazdığı için bir istisna atıp aniden yürütmeyi sonlandırmak istemezsiniz.

25
japollock

Diğerleri, kullanıcı yanlış yazarsa hatalı girişin normal bir akışta bekleneceği için istisnaların kullanılmaması gerektiğini öne sürmektedir. Aynı fikirde değilim ve nedenini anlamıyorum. Bir dosyayı açmakla karşılaştırın ... eğer dosya mevcut değilse veya bir nedenden ötürü mevcut değilse, çerçeve tarafından bir istisna atılır. Bunun üzerindeki mantığı kullanarak Microsoft tarafından bir hataydı. Bir hata kodu geri göndermeliydiler. Ayrıştırma, web istekleri, vb. İçin de aynı.

Normal bir akışın hatalı bir giriş parçası olduğunu düşünmüyorum, bu olağanüstü. Normalde kullanıcı doğru şifreyi yazar ve dosya var. İstisnai durumlar istisnaidir ve bunlar için istisnalar kullanmak tamamen iyidir. Geri dönüş değerlerini n seviyelerine doğru ilerleterek kodunuzu karmaşık hale getirmek, enerji kaybıdır ve dağınık kodla sonuçlanacaktır. İşe yarayabilecek en basit şeyi yap. Hata kodları kullanarak zamanından önce optimizasyon yapmayın, tanımlara göre istisnai şeyler nadiren gerçekleşir ve istisnalar siz atmadığınız sürece hiçbir ücrete tabi olmaz.

23
Bjorn Reppen

İstisnalar, biraz pahalı bir etkidir; örneğin, geçersiz bir şifre sağlayan bir kullanıcı varsa, genellikle bir başarısızlık bayrağını geri almak veya geçersiz olduğunu gösteren başka bir gösterge daha iyi bir fikirdir.

Bu, istisnaların ele alınma şekli, gerçek hatalı girdi ve benzersiz kritik durdurma öğelerinin istisnalar olması ancak giriş bilgilerinin başarısız olmaması nedeniyledir.

16
Mitchel Sellers

Sadece şu andaki durumunuzdan çıkmak için yapabileceğiniz hiçbir şey olmadığında bir istisna atmanız gerektiğini düşünüyorum. Örneğin, hafıza tahsis ediyorsanız ve tahsis edilecek herhangi bir şey yoksa. Bahsettiğiniz durumlarda bu durumlardan açıkça kurtulabilir ve bir hata kodunu arayana geri gönderebilirsiniz.


Bu sorunun cevabını da içeren, sadece "istisnai" durumlarda istisnalar atmanız gerektiği konusunda çok fazla tavsiye göreceksiniz. Bu yüzeysel olarak makul gözüküyor, ancak hatalı bir tavsiye, çünkü bir soruyu (“ne zaman bir istisna atmalıyım”) başka bir öznel soruyla (“istisnai olan”) değiştiriyor. Bunun yerine, Herb Sutter'in tavsiyelerine uyun (C++ için Dr Dobbs makalesinde mevcuttur. İstisnalar Ne Zaman ve Nasıl Kullanılmalı , ve ayrıca Andrei Alexandrescu adlı kitabında, C++ Kodlama Standartları ): eğer bir istisna atarsanız,

  • bir önkoşul yerine getirilmez (bu, tipik olarak aşağıdakilerden birini imkansız kılar) veya
  • alternatif bir şartı yerine getirmede başarısız olur
  • alternatif, değişmezliği sürdürmede başarısız olur.

Bu neden daha iyi? Ön şartlar, son şartlar ve değişmezler hakkındaki birkaç soru ile soruyu değiştirmez mi? Bağlantılı nedenlerden dolayı bu daha iyidir.

  • Ön koşullar, son koşullar ve değişmezler programımızın tasarım özellikleridir (dahili API), throw için verilen karar bir uygulama detayıdır. Tasarımı ve uygulamasını ayrı olarak dikkate almamız gerektiğini ve bir yöntemi uygularken yaptığımız işin tasarım kısıtlarını karşılayan bir şey üretmektir.
  • Metodumuzun sadece metodumuzun arayanlarının yapması gereken ve tam olarak ifade etmesi gereken varsayımlar olan ön şartlar, son şartlar ve değişmezler açısından düşünmeye zorlar. Programımızın bileşenleri arasında gevşek bağlantı kurulmasını sağlar.
  • Bu gevşek bağlantı daha sonra gerekirse uygulamayı yeniden düzenlememize izin verir.
  • Post-koşullar ve değişmezler test edilebilir; Ünite testi kodumuzun kontrol edebileceğini (iddia ettiğini) tahmin ettikten sonra, ünite testinin kolayca test edilebileceği kodla sonuçlanır.
  • Post-koşullar açısından düşünmek, doğal olarak, istisnaları kullanmak için doğal bir stil olan post-koşul olarak başarılı olan bir tasarım üretir. Programınızın normal ("mutlu") çalıştırma yolu doğrusal olarak düzenlenir, tüm hata işleme kodları catch cümlelerine taşınır.
14
Jon

İstisnaların ne zaman kullanılacağına dair kesin ve hızlı kurallar olmadığını söyleyebilirim. Ancak bunları kullanmak veya kullanmamak için iyi nedenler vardır:

İstisnaları kullanma nedenleri:

  • Genel dava için kod akışı daha açıktır
  • Karmaşık hata bilgisini bir nesne olarak döndürebilir (bu, aynı zamanda başvuruda geçirilen "out" hatası kullanılarak da elde edilebilir)
  • Diller genellikle istisna olması durumunda düzenli temizliği yönetmek için bazı imkanlar sağlar (C #, C++ 'da C++ kullanarak Java'yı deneyin/nihayet)
  • İstisna atılmadığı takdirde, yürütme bazen dönüş kodlarını kontrol etmekten daha hızlı olabilir
  • Java'da, kontrol edilen istisnalar bildirilmeli veya yakalanmalıdır (buna karşı bir sebep olabilir)

İstisnaları kullanmama nedenleri:

  • Hata işleme basitse, bazen çok üzülür
  • İstisnalar belgelenmemiş veya beyan edilmemişse, arama kodunun henüz bir dönüş kodunu görmezden gelmesinden daha kötü olan arama kodu tarafından yakalanmamış olabilirler (uygulama çıkışı - sessiz başarısızlığı - bu durum senaryoya bağlı olabilir)
  • C++ 'da istisnalar kullanan kod istisna güvenli olmalıdır (atmaz veya yakalamasanız bile, atma işlevini dolaylı olarak çağırsanız bile)
  • C++ 'da, bir işlevin ne zaman atılabileceğini söylemek zordur, bu nedenle kullanırsanız istisna güvenliği konusunda paranoyak olmanız gerekir.
  • İstisnaları atma ve yakalama genellikle bir geri dönüş bayrağını kontrol etmekten çok daha pahalıdır.

Genel olarak, istisnaları C++ veya C # 'dan ziyade Java' de kullanma eğilimindeyim, çünkü bir istisnanın temelde bir fonksiyonun biçimsel arayüzünün bir parçası olduğu kanısındayım. istisna garantinizi değiştirmek çağıran kodu kırabilir. Bunları Java IMO'da kullanmanın en büyük avantajı, arayan tarafınızın istisnayı ele alması gerektiğini bilmenizdir ve bu, doğru davranış olasılığını artırır.

Bu nedenle, herhangi bir dilde, tüm istisnaları her zaman bir kod katmanında veya API'de ortak bir sınıftan türetirdim, böylece arama kodu her zaman istisnaları yakalamayı garanti edebilir. Ayrıca, bir API veya kütüphane yazarken uygulamaya özel istisna sınıfları atmanın kötü olacağını düşünmekteyim (diğer bir deyişle istisnaları alt katmanlardan ayırın, böylece arayan kişinin aldığı istisna arayüzünüzün bağlamında anlaşılabilir).

Java öğesinin bildirilmemesi gereken genel ve Çalışma Zamanı istisnaları arasında ayrım yaptığını unutmayın. Yalnızca Runtime istisna sınıflarını, hatanın programdaki bir hatanın sonucu olduğunu bildiğiniz zaman kullanırdım.

10
Robert

İstisna sınıfları "normal" sınıflar gibidir. Farklı alanlar ve farklı işlemler içeren farklı bir nesne türü "olduğunda" yeni bir sınıf oluşturursunuz.

Genel bir kural olarak, istisna sayısı ile istisnaların ayrıntı derecesi arasındaki dengeyi denemelisiniz. Yönteminiz 4-5'ten fazla farklı istisna atarsa, bazılarını muhtemelen daha "genel" istisnalar (örneğin, "AuthenticationFailedException") durumunda birleştirebilir ve neyin yanlış gittiğini detaylandırmak için istisna mesajını kullanabilirsiniz. Kodunuz her birini farklı şekilde ele almadıkça, birçok istisna sınıfı oluşturmanıza gerek yoktur. Ve eğer öyleyse, sadece ortaya çıkan hata ile bir enum vermelisin. Bu şekilde biraz temizleyici.

5
Shachar

Tekrar tekrar tekrar istisnaya neden olacak bir döngü içinde çalışan kod ise, istisnalar atmak iyi bir şey değildir, çünkü büyük N için oldukça yavaşlar. sorun. Bunların hepsinin kalıtımsal olduğu, BaseException veya buna benzer bir şey olarak adlandırılan bir temel istisna olduğundan emin olun. BaseException System.Exception devralınır, ancak istisnalarınızın tümü BaseException'ı devralır. Benzer türleri gruplamak için İstisna türleri ağacına bile sahip olabilirsiniz, ancak bu fazlaca olabilir veya olmayabilir.

Dolayısıyla kısa cevap, önemli bir performans cezasına neden olmazsa (çok fazla istisna atmadığınız sürece yapmaması gereken), o zaman devam edin.

5
Charles Graham

Oradaki japollock yöntemiyle aynı fikirdeyim - bir operasyonun sonucundan emin değilsen bir suçlama at. API'lere yapılan çağrılar, dosya sistemlerine, veritabanı çağrılarına vb. Erişme. Programlama dilinizin "sınırlarını" ne zaman geçerseniz.

Eklemek istiyorum, standart bir istisna atmaktan çekinmeyin. "Farklı" bir şey yapmayacaksanız (görmezden gelin, e-postayla, günlükle, Twitter balinasının resmini göster, vb.), O zaman özel istisnalar ile uğraşma.

3
dclaysmith

istisnalar atmak için başparmak kuralı oldukça basittir. kodunuz UNRECOVERABLE INVALID durumuna girdiğinde bunu yaparsınız. Eğer veriler tehlikeye girerse ya da ortaya çıkan işlemi geri alamazsanız, o zaman sonlandırmalısınız. gerçekten başka ne yapabilirsin? işlem mantığınız sonunda başka yerde başarısız olur. eğer bir şekilde iyileşebilirsen o zaman bunu yap ve istisna atma.

özel bir durumda, para çekme işlemini kabul etmek gibi aptalca bir şey yapmaya zorlandıysanız ve yalnızca o zaman kullanıcı/parolayı kontrol edin, kötü bir şeyin olduğunu bildirmek ve daha fazla hasarı önlemek için bir istisna atarak işlemi sonlandırmanız gerekir.

3
goran

Genelde her köktenciliğin cehenneme gittiğini söyleyebilirim.

Kesinlikle istisna güdümlü akışla sonuçlanmak istemezsiniz, ancak istisnaları tamamen ortadan kaldırmak da kötü bir fikirdir. Her iki yaklaşım arasında bir denge bulmak zorundasın. Yapmayacağım şey, her istisnai durum için bir istisna türü yaratmaktır. Bu verimli değil.

Genelde tercih ettiğim, sistemde kullanılan iki temel istisna türü oluşturmaktır: LogicalException ve TechnicalException . Gerekirse bunlar alt tiplerle daha da ayırt edilebilir, ancak genel olarak gerekli değildir.

Teknik istisna, veritabanı sunucusunun kapalı olması gibi gerçekten beklenmeyen bir istisnayı, web servisine bağlantıyı IOException ve benzeri şekilde attığını gösterir.

Öte yandan, mantıksal istisnalar, daha az ciddi olan hatalı durumu üst katmanlara yaymak için kullanılır (genellikle bazı doğrulama sonuçları).

Lütfen mantıksal istisnanın bile program akışını kontrol etmek için düzenli olarak kullanılmasının amaçlanmadığını, akışın gerçekten sona ermesi gereken durumu vurgulamak için kullanılmadığını unutmayın. Java'da kullanıldığında, her iki istisna türü de RuntimeException alt sınıflarıdır ve hata işlemesi yüksek oranda yönelimlidir.

Bu nedenle, giriş örneğinde AuthenticationException gibi bir şey oluşturmak ve somut durumları enum değerleriyle ayırt etmek akıllıca olabilir. UsernameNotExisting , PasswordMismatch vs. Öyleyse, büyük bir istisna hiyerarşisine sahip olmayacaksınız ve catch bloklarını sürdürülebilir seviyede tutabilirsiniz. Bazı genel istisna işleme mekanizmalarını kolayca da kullanabilirsiniz, çünkü kategorilere ayrılan istisnalar vardır ve kullanıcıya neyin nasıl yayılacağını oldukça iyi bilirsiniz.

Tipik kullanımımız, kullanıcının girişi geçersiz olduğunda Web Hizmeti çağrısı sırasında LogicalException'ı atmaktır. İstisna, SOAPFault detayına göre düzenlenir ve daha sonra istisnaya uygun şekilde eşlendiğinden, belirli bir web sayfası giriş alanında validasyon hatasının gösterilmesiyle sonuçlanan istemcide tekrar istisnaya bırakılır.

Bu kesinlikle tek durum değil: istisnayı atmak için web servisine basmanıza gerek yok. İstisnai herhangi bir durumda bunu yapmakta özgürsünüz (hızlı-başarısız olmanız gerektiği gibi) - tamamen sizin takdirinize bağlı.

2
Petr Macek

İstisnalar, anormal davranışlar, hatalar, başarısızlıklar vb. Olan olaylara yöneliktir. İşlevsel davranış, kullanıcı hatası vb. Bunun yerine program mantığı ile ele alınmalıdır. Kötü bir hesap veya parola, bir giriş yordamındaki mantık akışının beklenen bir parçası olduğundan, bu durumları istisnasız ele alması gerekir.

2
Joe Skora

Genel olarak, uygulamanızda meydana gelebilecek herhangi bir şey için "İstisnai" olan bir istisna atmak istiyorsunuz.

Örneğinizde, bu istisnaların her ikisi de onları bir şifre/kullanıcı adı doğrulaması ile çağırıyor gibi görünüyorsunuz. Bu durumda, birinin bir kullanıcı adı/şifresini yanlış yazması gerçekten istisnai olmadığı söylenebilir.

Bunlar, UML’nizin ana akışına "istisnalar" dır, ancak işlemede daha fazla "daldır".

Şifre dosyasına veya veritabanına erişmeye çalıştıysanız ve başaramazsanız, bu istisnai bir durum olur ve bir istisna atma garantisi verir.

2
Gord

Öncelikle, API’nizin kullanıcıları belirli, ince taneli hatalarla ilgilenmiyorsa, bunlar için özel istisnalar olması hiçbir değer taşımaz.

Kullanıcılarınız için neyin yararlı olabileceğini bilmek genellikle mümkün olmadığından, daha iyi bir yaklaşım özel istisnalara sahip olmaktır, ancak ortak bir sınıftan miras aldıklarından emin olmaktır (örneğin, std :: istisna veya türevlerini C++). Bu, müşterinizin isterse özel istisnalar veya umursamıyorsa daha genel istisna yakalamasını sağlar.

2
Jason Etheridge

İstisnaların kullanımında felsefi problemlerim var. Temel olarak, belirli bir senaryonun gerçekleşmesini bekliyorsunuz, ancak açıkça ele almak yerine, sorunu “başka bir yerde” ele almak için zorluyorsunuz. Ve bu "başka bir yer" in nerede olduğu tahmin edilebilir.

2
Dan

Yakaladığım üç tür şart var.

  1. Kötü veya eksik giriş bir istisna olmamalıdır. Mesajları belirlemek, nitelikleri belirlemek ve aynı sayfaya geri dönmek için hem istemci tarafı j'leri hem de sunucu tarafı regex'ini kullanın.

  2. AppException. Bu genellikle kodunuzda algıladığınız ve attığınız bir istisnadır. Başka bir deyişle, bunlar beklediğinizlerdir (dosya mevcut değil). Kaydedin, mesajı ayarlayın ve genel hata sayfasına geri iletin. Bu sayfa genellikle olanlarla ilgili biraz bilgi içerir.

  3. Beklenmeyen İstisna. Bunlar bilmedikleriniz. Ayrıntılarla oturum açın ve bunları genel bir hata sayfasına iletin.

Bu yardımcı olur umarım

1
Michael

benim için İstenilen bir teknik kural veya iş kuralı başarısız olduğunda istisna atılmalıdır. örneğin, bir otomobil varlığı 4 lastik dizisiyle ilişkilendirilmişse ... bir lastik veya daha fazla lastik boşsa ... bir istisna kullanılmalıdır "NotEnoughTiresException", çünkü sistemin farklı bir seviyesine yakalanabilir ve önemli ölçüde günlüğe kaydetme yoluyla anlam. Bunun yanında, sadece null kontrol etmek ve arabanın ısınmasını önlemek için akmaya çalışırsak. Asla sorunun kaynağını bulamayacağız, çünkü lastiğin ilk başta boş kalmaması gerekiyordu.

1
Genjuro

Basit bir cevap, ne zaman bir işlem imkansız ise (OR uygulamasından herhangi biri nedeniyle, işletme mantığını ihlal edecek). Bir yöntem çağrılırsa ve yöntemin ne yazdığını yapmak imkansızsa, bir İstisna atayın. İyi bir örnek, sağlanan parametreler kullanılarak bir örnek oluşturulamıyorsa, yapıcıların her zaman ArgumentExceptions değerini atmasıdır. Başka bir örnek ise, başka bir üye veya sınıfın üyeleri nedeniyle bir işlem yapılamadığında atılan InvalidOperationException'dır.

Durumunuzda, Login (kullanıcı adı, şifre) gibi bir yöntem çağrılırsa, kullanıcı adı geçerli değilse, bir KullanıcıAdıNotValidException ya da parola yanlışsa bir ParolaNotCorrectException oluşturmak doğru olur. Kullanıcı verilen parametreleri kullanarak giriş yapamaz (yani, kimlik doğrulamasını ihlal edeceği için bu mümkün değildir), bu yüzden bir İstisna at. Yine de, iki İstisna da, ArgumentException öğesinden miras kalmış olabilir.

Bir oturum açma hatası çok yaygın olabileceğinden bir İstisna atmak istemiyorsanız, bunun yerine bir stratejinin farklı hataları temsil eden türleri döndüren bir yöntem oluşturmak olduğunu söylemiştiniz. İşte bir örnek:

{ // class
    ...

    public LoginResult Login(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            return new UserInvalidLoginResult(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            return new PasswordInvalidLoginResult(user, password);
        }
        else
        {
            return new SuccessfulLoginResult();
        }
    }

    ...
}

public abstract class LoginResult
{
    public readonly string Message;

    protected LoginResult(string message)
    {
        this.Message = message;
    }
}

public class SuccessfulLoginResult : LoginResult
{
    public SucccessfulLogin(string user)
        : base(string.Format("Login for user '{0}' was successful.", user))
    { }
}

public class UserInvalidLoginResult : LoginResult
{
    public UserInvalidLoginResult(string user)
        : base(string.Format("The username '{0}' is invalid.", user))
    { }
}

public class PasswordInvalidLoginResult : LoginResult
{
    public PasswordInvalidLoginResult(string password, string user)
        : base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
    { }
}

Çoğu geliştiriciye, onları atmanın neden olduğu genel gider nedeniyle İstisnalar'dan kaçınılması öğretilir. Kaynak bilincine sahip olmak harika ancak genellikle uygulama tasarımınızın pahasına değil. Muhtemelen bu iki İstisna'yı atmamanın söylenmesinin nedeni budur. İstisnaların kullanılıp kullanılmayacağı, İstisna'nın ne sıklıkta gerçekleşeceğine bağlı değildir. Oldukça yaygın veya oldukça beklenen bir sonuç ise, bu durum çoğu geliştiricinin İstisnalardan kaçınacağı ve bunun yerine, sözde kaynak kullanımı nedeniyle başarısızlığı belirtmek için başka bir yöntem oluşturduğu durumdur.

Aşağıda, Try () desenini kullanarak, sadece tanımlandığı gibi bir senaryoda İstisnalar'ı kullanmaktan kaçınmanın bir örneği verilmiştir:

public class ValidatedLogin
{
    public readonly string User;
    public readonly string Password;

    public ValidatedLogin(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            throw new UserInvalidException(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            throw new PasswordInvalidException(password);
        }

        this.User = user;
        this.Password = password;
    }

    public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
    {
        if (IsInvalidUser(user) || 
            IsInvalidPassword(user, password))
        {
            return false;
        }

        validatedLogin = new ValidatedLogin(user, password);

        return true;
    }
}
1
core

Aklıma göre, asıl soru, bir koşul ortaya çıktığında, arayan kişinin normal program akışına devam etmek isteyip istemediği sorusudur. Eğer bilmiyorsanız, ayrı bir şeyler yapın ve deneyin, birincinin bir hata döndürdüğü ve ikincinin hata vermeyeceği bir yöntem kullanın veya başarısız olduğunda bir istisna atılıp atılmayacağını belirtmek için bir parametreyi kabul eden bir rutine sahip olun). Uzak bir sisteme komut göndermek ve yanıtları bildirmek için bir sınıf düşünün. Bazı komutlar (örneğin, yeniden başlatma), uzaktaki sistemin yanıt göndermesine neden olur, ancak belirli bir süre boyunca yanıt vermez. Bu nedenle, bir "ping" komutu gönderebilmek ve uzaktaki sistemin bir istisna atmak zorunda kalmadan makul bir süre içerisinde yanıt verip vermediğini bulmak yararlıdır (arayan kişi ilk birkaç kişiden beklediğini bekler "). ping "girişimler başarısız olur, ancak sonuçta işe yarar. Öte yandan, birinin aşağıdaki gibi bir komut dizisi varsa:

 exchange_command ("açık tempfile"); 
 exchange_command ("tempfile verileri {her ne olursa olsun" yazın)]; 
 exchange_command ("tempfile verilerini yazın {ne olursa olsun" "); 
 .] exchange_command ("tempfile verisi {ne olursa olsun" "yaz); 
 exchange_command (" tempfile verisi {ne olursa olsun "" yaz); 
 exchange_command ("tempfile ver"); 
 exchange_command ("tempfile dosyasını gerçek dosyaya kopyala"); 

biri herhangi bir işlemin tüm sırayı iptal etmemesini ister. Başarılı olmak için her bir işlemi kontrol etmek mümkün olsa da, bir komut başarısız olursa exchange_command () yordamının bir istisna atması daha yararlı olur.

Aslında, yukarıdaki senaryoda, birkaç hata işleme modunu seçmek için bir parametrenin kullanılması yararlı olabilir: hiçbir zaman istisnalar atma, yalnızca iletişim hataları için istisnalar atma veya bir komutun "başarılı olamayacağı" durumlarda istisnalar atma "gösterge.

1
supercat

bir istisna atmamaktan kaçınmanın ana nedeni, bir istisna atmakla ilgili çok fazla ek yükün olmasıdır.

Aşağıdaki makalenin bir istisnasının istisnai koşullar ve hatalar için yazdığı bir şey var.

Yanlış bir kullanıcı adı mutlaka bir program hatası değil, kullanıcı hatası olabilir ...

.NET içindeki istisnalar için iyi bir başlangıç ​​noktası: http://msdn.Microsoft.com/en-us/library/ms229030 (VS.80) .aspx

1
Sam

Güvenlik, örneğin: Bir saldırgana bir kullanıcı adının bulunduğunu söylememelisin, fakat şifre yanlış. Paylaşmanız gerekmeyen ekstra bilgiler. Sadece "kullanıcı adı veya şifre yanlış" deyin.

1
anon

İstisnaları atmak istifin gevşemesine neden olur, bu da bazı performans etkilerine sahiptir (kabul edilen, modern yönetilen ortamlar bu konuda iyileştirilmiştir). Yine de iç içe geçmiş bir durumda istisnaları tekrar tekrar atmak ve yakalamak kötü bir fikir olabilir.

Muhtemelen bundan daha önemli olan istisnalar istisnai durumlar içindir. Sıradan kontrol akışı için kullanılmamalıdırlar, çünkü bu kodunuzun okunabilirliğine zarar verecektir.

1
Arno

Bir istisnanın uygun olup olmadığına karar verirken düşünülmesi gereken bazı şeyler:

  1. i̇stisna adayının ortaya çıkmasından sonra hangi kod seviyesini çalıştırmak istediğinizi - yani, arama yığınının kaç katmanı çözmeniz gerektiği anlamına gelir. Genel olarak, bir istisnayı, gerçekleştiği yere mümkün olduğunca yakın bir şekilde ele almak istersiniz. Kullanıcı adı/şifre doğrulaması için, bir istisna kabarcığı oluşturmak yerine normalde aynı kod bloğundaki arızaları ele alırsınız. Bu yüzden bir istisna muhtemelen uygun değildir. (OTOH, üç başarısız giriş denemesinden sonra, kontrol akışı başka bir yere kayabilir ve burada bir istisna uygun olabilir.)

  2. Bu olay, hata günlüğünde görmek isteyeceğiniz bir şey mi? Her istisna bir hata günlüğüne yazılmaz, ancak bir hata günlüğündeki bu girişin yararlı olup olmadığını sormak yararlıdır - yani, bunun hakkında bir şeyler yapmayı dener misiniz yoksa göz ardı edeceğiniz çöp olur mu?.

0
Mike Kantor

İki ana istisna sınıfı vardır:

1) Sistem istisnası (örn. Veritabanı bağlantısı kesildi) veya 2) Kullanıcı istisnası. (örn. Kullanıcı girişi doğrulama, 'şifre yanlış')

Kendi Kullanıcı İstisna Sınıfını oluşturmayı yararlı buldum ve bir kullanıcı hatası atmak istediğimde farklı şekilde ele almak istiyorum (yani kullanıcıya görüntülenen kaynaklı hata) sonra ana hata işleyicimde tek yapmam gereken nesne türünü kontrol etmek. :

            If TypeName(ex) = "UserException" Then
               Display(ex.message)
            Else
               DisplayError("An unexpected error has occured, contact your help  desk")                   
               LogError(ex)
            End If
0
Crusty

"PasswordNotCorrectException" istisnaları kullanmak için iyi bir örnek değil. Kullanıcıların şifrelerini yanlış alması beklenir, bu nedenle IMHO'nun istisnası değildir. Muhtemelen güzel bir hata mesajı göstererek ondan kurtulabilirsiniz, bu yüzden sadece bir geçerlilik kontrolü.

İşlenmeyen istisnalar sonunda uygulamayı durdurur - ki bu iyi. Yanlış, boş veya hata kodları döndürüyorsanız, programın durumunu tek başına ele almanız gerekir. Bir yerde koşulları kontrol etmeyi unutursanız, programınız yanlış verilerle çalışmaya devam edebilir ve what oldu ve where öğelerini bulmakta zorlanabilirsiniz.

Elbette, boş catch ifadeleriyle aynı soruna neden olabilirsiniz, ancak en azından bunları tespit etmek daha kolaydır ve mantığı anlamanızı gerektirmez.

Yani, kural olarak:

İstemediğiniz her yerde kullanın veya bir hatadan kurtulamazsınız.

0
DanMan

Bu şartlar için biraz genel istisnalar kullanabilirsiniz. Örneğin ArgumentException, bir yönteme ilişkin parametrelerde bir sorun olduğunda (ArgumentNullException hariç) kullanılacaktır. Genel olarak LessThanZeroException, NotPrimeNumberException vb. İstisnalara gerek duymazsınız. Yönteminizin kullanıcısını düşünün. Özel olarak ele almak isteyeceği koşulların sayısı, yönteminizin atması gereken istisnaların türüne eşittir. Bu şekilde, ne kadar ayrıntılı istisnalara sahip olacağınızı belirleyebilirsiniz.

Bu arada, kütüphanelerinizin kullanıcılarının istisnalardan kaçınmaları için her zaman bazı yollar sağlamaya çalışın. TryParse iyi bir örnektir, int.Parse kullanmanız ve bir istisna yakalamanız gerekmez. Sizin durumunuzda, kullanıcı adının geçerli olup olmadığını veya parolanın doğru olup olmadığını kontrol etmek için bazı yöntemler sağlamak isteyebilirsiniz; Bu umarım daha okunabilir kod ve daha iyi performans ile sonuçlanacaktır.

0
Serhat Ozgel

Nihayetinde karar, istisna yönetimi ya da durum kodlarını döndürmek gibi kendi yuvarlanan mekanizmanız aracılığıyla bunun gibi uygulama düzeyinde hatalarla uğraşmanın daha yararlı olup olmadığına karar veriyor. Hangisinin daha iyi olduğu konusunda hızlı ve zor bir kural olduğunu sanmıyorum, ancak şunu düşünürdüm:

  • Kodunu kim arıyor? Bu bir çeşit genel API veya dahili bir kütüphane mi?
  • Hangi dili kullanıyorsun Örneğin, eğer Java ise, (işaretli) bir istisna atmak, görmezden gelebilecek bir iade durumuna karşılık, bu hata koşulunu bir şekilde ele almak için arayan kişiye açık bir yük getirir. Bu iyi ya da kötü olabilir.
  • Aynı uygulamadaki diğer hata koşulları nasıl ele alınmaktadır? Arayanlar, sistemdeki hiçbir şeyden farklı olarak hataları kendine özgü bir şekilde ele alan bir modülle uğraşmak istemeyeceklerdir.
  • Söz konusu rutinde kaç şey yanlış gidebilir ve nasıl farklı şekilde ele alınabilirdi? Farklı hataları işleyen bir dizi yakalama bloğu ile bir hata kodundaki bir anahtar arasındaki farkı düşünün.
  • Dönmeniz gereken hata hakkında yapılandırılmış bilginiz var mı? Bir istisna atmak, bu bilgiyi koymak için sadece bir statü döndürmekten daha iyi bir yer sağlar.
0
eli