Soru İstisnaları işleme, bu iyi bir yoldur?


Uygulamamızdaki istisnaları doğru bir şekilde ele almak için bir politika ile mücadele ediyoruz. İşte bunun için hedeflerimiz (özetlenmiş):

  • Yalnızca belirli istisnaları kullanın.
  • Yalnızca düzeltebileceğiniz istisnaları kullanın
  • Sadece bir kez giriş yapın.

Genel bir Uygulamaya Özgü İstisna içeren bir çözümle ortaya çıktık ve böyle bir kod parçası üzerinde çalışıyoruz:

try {
  // Do whatever
}
catch(ArgumentNullException ane)
{
  // Handle, optinally log and continue
}
catch(AppSpecificException)
{
  // Rethrow, don't log, don't do anything else
  throw;
}
catch(Exception e)
{
  // Log, encapsulate (so that it won't be logged again) and throw
  Logger.Log("Really bad thing", e.Message, e);
  throw new AppSpecificException(e)
}

Tüm özel durum günlüğe kaydedilir ve daha sonra bir daha oturum açılmayacak şekilde bir AppSpecificException döndürülür. Sonunda, eğer gerekiyorsa onunla ilgilenecek olan son çare olay işleyicisine ulaşacaktır.

İstisna işleme kalıpları konusunda çok fazla tecrübem yok ... Bu hedeflerimizi çözmenin iyi bir yolu mu? Herhangi bir büyük dezavantaj mı yoksa büyük kırmızı uyarı mı?

Not: Bunun dezavantajlarından biri, ilk yakalamadan sonra belirli bir özel durumla başa çıkabilme yeteneğini kaybedersiniz (başka bir yöntemi çağıran bir yöntem çağırırsanız ve ikincisi bunu gerçekleştiremeyeceğiniz bir istisna atarsanız) ama ben ve ben bunu hiç bir şekilde yapmadım ... Sadece istisnaları tek bir derinlik seviyesinde ele alıyorum ...


28
2018-03-18 12:39


Menşei




Cevaplar:


İstisnai ilk kez atılan zamana çok yakın bir zamanda kaydederseniz, tam yığın izlemeyi kaydetmezsiniz.

Sap istisnalar (yani, onları düzeltin), atıldıklarında mümkün olduğunca yakın. Bağlanma anında mümkün olan en kısa sürede içerik hakkında bilgi toplayın. Ancak istisnaların gerçekte nerede kullanılabileceğine kadar yayılmasına izin verin. Günlüğe kaydetme son çare olarak ele alınır, bu yüzden uygulama alt sistemlerinin dış katmanlarında gerçekleşmelidir.

Bu, başlangıçta yakalanmaması gereken bir istisna kaydettirmek için bir belirteç olarak kullanılan uygulamaya özel bir istisna ihtiyacını ortadan kaldırmalıdır.


59
2018-03-18 12:47



Yığın izinin istisna nesnesine gömüldüğünü sanıyordum ... - Jorge Córdoba
@Jorge: İstisna olarak yığın izleme eklenir yığın seviyeleri katlar. "Bugüne kadar" yığın izi. - John Saunders
+1 Bu en iyi tavsiyedir - Keşke bunu iki kere alabilirim! - Andrew Hare
+1 Soruda önerilen deseni kullanırsanız, pişman olacağınızdan şüpheleniyorum. Sadece pratik olarak, uygulama katmanında oturum açmak için karşılaştırıldığında, büyük miktarda gereksiz kod gerektirir. - Jeff Sternal
Günlükleme mekanizması bunu destekliyorsa, istisna oluştuğunda günlüğe kaydetme mekanizması notuna sahip olmanın yararlı olabileceğini düşünürdüm, ancak istisna çağrı zincirine yükseldikçe günlük girdisi "üst üste" konulmalıdır. Aksi takdirde, henüz henüz kullanılmamış eski bir istisnadan yığını çözerken bir istisna meydana gelirse, daha önceki istisna hakkında bir şey kaydetmenin bir yolu yoktur. - supercat


Bir istisna kaydetme ve ardından yeniden atma - oluşturduğunuz istisnaları işlemek / günlüğe kaydetme görevlilerinin sorumluluğundadır.

İşlenecek bir özel durumu yakalayın (örneğin, oturum açmak için) veya içeriğe özel bilgiler ekleyin.


6
2018-03-18 12:52





Bu istisna işleme problemini çözmek için oldukça yaygın bir yaklaşımdır (daha spesifik olandan daha az spesifik olana).

Belirli sorunları yakalamak istiyorsanız, o uygulamada / yöntemde meydana gelen her şeyi yakalamak için genel bir ApplicationSpecific özel durumunun olması harika bir fikir olmadığını unutmayın. Sonunda, daha özel istisnalarla genişletmeyi deneyin.

Yeniden sıralama istisnası iyidir, daha iyi yöntem belirli istisnalar atmak ve arayanların bunları işlemesine izin vermektir. Bu şekilde daha az kod oluşturmanız gerekir ve bazı kontrolleri merkezileştirebilirsiniz.


0
2018-03-18 12:47



-1: bir yöntemin hangi istisnalar yaptığını aslında "bildiremezsiniz" - John Saunders


Yığın izleme sorununu çözmek için ilk seçenek:

class AppSpecificException : ApplicationException
{
    public string SpecificTrace { get; private set; }
    public string SpecificMessage { get; private set; }

    public AppSpecificException(string message, Exception innerException)
    {
        SpecificMessage = message;
        SpecificTrace = innerException.StackTrace;
    }

}

Soruyu anlamak ve stacktrace problemini kontrol etmek için bir örnek yazmam gerekti, bu benim için kod, button2_click yöntemine dikkat çek, sonunda metin kutum kilitlenme dizisini ve stacktrace'i gösteriyor:

    private String internalValue;

    private void Operation1(String pField)
    {
        if (pField == null) throw new ArgumentNullException("pField");
        internalValue = pField;
    }

    private void Operation2(Object pField)
    {
        if (pField == null) throw new ArgumentNullException("pField");
        internalValue = Convert.ToInt32(pField).ToString();
    }

    private void Operation3(String pField)
    {
        if (pField == null) throw new ArgumentNullException("pField");
        internalValue = pField;
        Operation2(-1);
    }


    /// <exception cref="AppSpecificException"><c>AppSpecificException</c>.</exception>
    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            Operation1("One");
            Operation2("Two");
            Operation3("Three");
            MessageBox.Show(internalValue);
        }
        catch (ArgumentNullException ex)
        {
            textBoxException.Text = ex.Message + (char) 13 + (char) 10 + ex.StackTrace;
        }
        catch (AppSpecificException ex)
        {
            //textBoxException.Text = ex.Message + (char)13 + (char)10 + ex.StackTrace;
            throw;
        }
        catch (Exception ex)
        {
            textBoxException.Text = ex.Message + (char)13 + (char)10 + ex.StackTrace;                    
            throw new AppSpecificException("crash", ex);
        }

    }

    private void button2_Click(object sender, EventArgs e)
    {
        try
        {
            button1_Click(sender, e);
        }
        catch (AppSpecificException ex)
        {
            textBoxException.Text = ex.SpecificMessage + (char) 13 + (char) 10 + ex.SpecificTrace;
        }
    }

0
2018-03-18 14:02



-1 birçok sebepten dolayı: ApplicationException, (char) 13+ (char) 10'un kullanımı (platforma özgü yeni satır değilse?) ex.ToString () yerine ex.StackTrace kullanımı, yakalamak ArgumentNullException Ama değil ArgumentException, vb. Bunu yıllar önce görmüştüm. - John Saunders


Yeni bir istisna oluşturmamaya çalışın ve yeniden sıralama yapın; çünkü bir istisna atmak, yığın izini istisnanın atıldığı yere ayarlar. Sadece düz bir atış yapın. Görmek Çok fazla kullanım Eric Lippert'in Blog'unda.


0
2018-03-18 14:11





"Teslim" için hangi kalıpları kullanmak istediğinize daha fazla düşünmenizi öneririm

İşleme desenleriniz günlüğe kaydedilip yeniden çizilirse, yeniden oluşturulan hata günlüğe kaydedilir. Sonuç olarak, sadece hata günlüğü. ASP.NET kullanıyorsanız elmah kullanın, en azından kodunuz try / catch-and-log kazan plakası ile kaplanmamıştır.

Sadece oturum açma ile bitmeyen hataları "işlemek" için yalnızca birkaç yol vardır.

Yeniden deneyin. (Sonsuz döngülere dikkat edin)

Bekle ve tekrar dene.

Farklı fakat eşdeğer bir teknik deneyin (http’lara bağlanamıyor mu? Https’de bağlanmayı deneyin).

Eksik koşulları oluşturun (FolderNotFoundException öğesini kuran klasörü oluşturun)

Hatayı görmezden gel - bu konuda iki kez düşünün, yalnızca bir sorun olmadığını gördüğümde, 3. parti kütüphanesi geçerli olmayan bir koşul hakkında sizi uyarıyormuş gibi geliyor.


0
2018-03-18 14:15



Yukarıdaki liste, birçok durumda, bir istisnayı ele almanın en kullanışlı yolu olarak ne görmezden geldiğinizi görmezden gelir: sadece, neden talep edilmeksizin, istenen bir operasyonun gerçekleşmediği gerçeğini ele alır. Bir kullanıcı bir belge açmayı isterse ve yükleme girişimi başarısız olursa, kullanıcıya belgenin açılamadığını bildirir. Neden açılmayacağına dair ayrıntılar yardımcı olabilir, ancak isteğin başarısız olduğu kadar önemli değildir. Ne yazık ki, "Denenmiş operasyonun yan etkileri olmadan başarısız oldu" ayırt etmek için standart bir sözleşme yoktur ... - supercat
... "bazı paylaşılan nesneler bozuldu, bu yüzden kod kullanmadan olabildiğince zarif bir şekilde kapatılmalıdır". Bu nedenle, kesin özellikleriyle beklenmeyen bir istisna ile karşılaşan kodun çoğu zaman bir seçimi yoktur, ancak başarısızlığı, kiminle başa çıkmaya hazırlandığı bir şey yapmadan işlem yapıp yapmamasını tahmin etmelidir. ateş ve aniden kapatma yapmak veya arada bir şey yapıp yapmamak. - supercat
O zaman bir cevap gönderin ya da aşağıya oy verin (ve benzer cevaplar gönderen diğer insanlar), neden beni 4 yıldır rahatsız ediyorsunuz? - MatthewMartin


İstisna işlemeyle ilgili iyi bir çözüm, Interception kullanıyor. Ancak, bu desenin, mimariye bağlı olarak uygulamanıza uygulanıp uygulanmayacağını doğrulamanız gerekir: Interception, bir kapsayıcı gerektirir.

Buradaki ilke, istisna işlemlerinizi, yöntemlerin dışındaki öznitelikler (özel) kullanarak özellestirmek ve ardından örneklerinizi başlatmak için kapsayıcıyı kullanmaktır. Konteyner, tezleri örneklerle yansıtacaktır: çağrılan örnekler. Yöntem örnekleri aracılığıyla her zamanki gibi yöntemlerinizi çağırmanız ve yöntemden önce veya sonra kodladığınız işi durdurma mekanizmasına izin vermeniz gerekir.

Engelleyicilerinizde yönetilmeyen belirli istisnaları yönetmek için yöntemlerde try catch özelliğini ekleyebilirsiniz.

Birlik müdahale: http://msdn.microsoft.com/en-us/library/dd140045.aspx


-1
2018-03-18 13:24