Neden her bloğu “dene” - “yakala”?


430

Her zaman, bir yöntem bir istisna atabilirse, bu çağrıyı anlamlı bir deneme bloğu ile korumamanın pervasız olduğuna inanıyorum.

Ben sadece ' HER ZAMAN denemek, blokları yakalamak çağrıları sarmak gerekir yayınladı . ' bu soruya ve' oldukça kötü bir tavsiye 'olduğu söylendi - nedenini anlamak istiyorum.


4
Bir yöntemin bir istisna atacağını bilseydim, ilk etapta düzeltirdim. Çünkü nerede ve neden kod onları (her yöntem - bir genel try-catch) onları yakalamak istisnalar atacak bilmiyorum çünkü. Mesela bir ekip bana daha eski bir veritabanına sahip bir kod tabanı verdi. Birçok sütun eksikti ve sadece SQL katmanında try catch eklendikten sonra yakalandı. İkincisi, çevrimdışı hata ayıklama için yöntem adını ve iletisini günlüğe kaydedebilirim - aksi takdirde nereden kaynaklandığını bilmiyorum.
Çakra

Yanıtlar:


340

Bir yöntem yalnızca mantıklı bir şekilde işleyebiliyorsa bir istisna yakalamalıdır.

Aksi takdirde, çağrı yığınının yukarısındaki bir yöntemin mantıklı olabileceği umuduyla, üst üste aktarın.

Diğerlerinin belirttiği gibi, ölümcül hataların günlüğe kaydedilmesini sağlamak için çağrı yığınının en üst düzeyinde işlenmeyen bir istisna işleyicisine (günlük kaydıyla) sahip olmak iyi bir uygulamadır.


12
Ayrıca trybloklar için maliyetler (üretilen kod açısından) olduğunu belirtmek gerekir . Scott Meyers'ın "Daha Etkili C ++" ında iyi bir tartışma var.
Nick Meyer

28
Aslında trybloklar herhangi bir modern C derleyicisinde ücretsizdir, bu bilgiler Nick'e tarihlenir. Ayrıca, yer bilgisini (yönerge başarısız olduğu gerçek yer) kaybettiğiniz için üst düzey bir istisna işleyicisi olması konusunda aynı fikirde değilim.
Blindy

31
@Blindly: üst istisna işleyicisi istisnayı işlemek için orada değil, aslında işlenmeyen bir istisna olduğunu yüksek sesle bağırmak, mesajını vermek ve programı zarif bir şekilde sonlandırmak (çağrı yerine 1 döndür terminate) . Daha çok bir güvenlik mekanizması. Ayrıca, try/catchherhangi bir istisna olmadığında az çok ücretsizdir. Bir yayılma olduğunda, her atıldığında ve yakalandığında zaman harcar, bu yüzden try/catchsadece tekerlemenin bir zinciri maliyetsiz değildir.
Matthieu M.29

17
Her zaman yakalanmayan bir istisnadan vazgeçmeniz gerektiğine katılmıyorum. Modern yazılım tasarımı çok bölümlere ayrılmıştır, bu yüzden neden bir hata olduğu için uygulamanın geri kalanını (ve daha da önemlisi kullanıcı!) Neden cezalandırmalısınız? Yapmak istediğiniz kesinlikle son şey çöküyor, en azından kullanıcıya, uygulamanın geri kalanına erişilemese bile çalışmayı kaydetmelerini sağlayacak küçük bir kod penceresi vermeye çalışın.
Kendall Helmstetter Gelner

21
Kendall: Üst düzey bir işleyiciye bir istisna gelirse, başvurunuz tanım gereği tanımlanmamış bir durumdadır. Bazı özel durumlarda, kullanıcının verilerini korumaya değer olabilir (Word'ün belge kurtarma akla gelir), program herhangi bir dosyanın üzerine yazmamalı veya bir veritabanına bağlanmamalıdır.
Hugh Brackett

136

As Mitch ve diğerleri belirtildiği, size bir şekilde ele planı yok o bir istisna yakalamak gerekir. Uygulamayı tasarlarken istisnaları sistematik olarak nasıl ele alacağını düşünmelisiniz. Bu genellikle soyutlamalara dayalı hata işleme katmanlarına sahip olur - örneğin, veri erişim kodunuzdaki SQL ile ilgili tüm hataları işlersiniz, böylece uygulamanın etki alanı nesneleriyle etkileşim kuran kısmı, başlık altında bir yerde bir DB.

Kesinlikle "her yerde yakalamak" kokusuna ek olarak kesinlikle kaçınmak istediğiniz birkaç ilgili kod kokuları vardır .

  1. "catch, log, rethrow" : Kapsamlı günlük kaydı istiyorsanız, bir istisna (ala std::uncaught_exception()) nedeniyle yığın açılırken yıkıcısına bir günlük deyimi yayan bir sınıf yazın . Yapmanız gereken tek şey, ilgilendiğiniz kapsamda bir günlük kaydı örneği bildirmektir ve işte, günlük kaydı vardır ve gereksiz try/ catchmantık yoktur .

  2. "yakalamak, tercüme etmek atmak" : bu genellikle bir soyutlama sorununa işaret eder. Birkaç özel istisnayı daha genel bir çözüme dönüştürdüğünüz birleşik bir çözüm uygulamadığınız sürece, muhtemelen gereksiz bir soyutlama katmanınız vardır ... ve "yarın buna ihtiyacım olabilir" demeyin .

  3. "yakala, temizle, tekrar et" : bu benim evcil hayvanımdan biri. Bunların çoğunu görürseniz, Kaynak Edinme Başlatma tekniklerini uygulamalı ve temizleme bölümünü bir hademe nesnesi örneğinin yıkıcısına yerleştirmelisiniz .

Ben kod inceleme ve yeniden düzenleme için iyi bir hedef olarak try/ catchblokları ile çevrili kodu düşünün . İstisna işlemenin iyi anlaşılmadığını veya kodun bir amœba haline geldiğini ve ciddi bir yeniden düzenleme ihtiyacı olduğunu gösterir.


6
# 1 benim için yeni. Bunun için +1. Ayrıca, # 2 için ortak bir istisna belirtmek isterim, yani bir kütüphane tasarlıyorsanız, kuplajı azaltmak için dahili istisnaları kütüphane arayüzünüz tarafından belirtilen bir şeye dönüştürmek istersiniz (bu, demek istediğiniz şey olabilir) "federal çözüm" ile, ancak bu terime aşina değilim).
rmeador


1
Kod kokusu değil, mantıklı olan # 2, eski istisnayı iç içe olarak tutarak geliştirilebilir.
Tekilleştirici

1
# 1 ile ilgili olarak: std :: uncaught_exception () size uçuşta yakalanmamış bir istisna olduğunu söyler, ancak AFAIK yalnızca bir catch () cümlesi bu istisnanın gerçekte ne olduğunu belirlemenizi sağlar. Bu nedenle, yakalanmamış bir istisna nedeniyle bir kapsamdan çıkmakta olduğunuz gerçeğini günlüğe kaydedebilirsiniz, ancak yalnızca ekli bir try / catch, herhangi bir ayrıntıyı günlüğe kaydetmenizi sağlar. Doğru?
Jeremy

@Jeremy - haklısın. Kural dışı durumu işlerken genellikle kural dışı durum ayrıntılarını günlüğe kaydederim. Araya giren karelerin izine sahip olmak çok faydalıdır. Günlük satırlarını ilişkilendirmek için genellikle iş parçacığı tanımlayıcısını veya bazı tanımlayıcı bağlamları günlüğe kaydetmeniz gerekir. Her günlük satırında iş parçacığı kimliğini içeren Loggerbenzer bir sınıf kullandım log4j.Loggerve bir özel durum etkinken yıkıcıda bir uyarı yayınladı.
D.Shawley

48

Bir sonraki soru "Bir istisna yakaladım, sonra ne yapacağım?" Ne yapacaksın? Hiçbir şey yapmazsanız - bu hata gizleme ve program ne olduğunu bulma şansı olmadan "sadece işe yaramadı". İstisnayı yakaladıktan sonra tam olarak ne yapacağınızı anlamanız ve sadece biliyorsanız yakalamanız gerekir.


29

Sen kapsayacak gerekmez her bir try-catch hala çağrı yığını altındaki fonksiyonlarda atılan işlenmemiş özel durumlar yakalamak çünkü deneme-yakalar bloğu. Bu nedenle, her işlevin bir deneme yakalaması yerine, uygulamanızın en üst düzey mantığına sahip olabilirsiniz. Örneğin, SaveDocument()diğer yöntemleri vb. Çağıran birçok yöntemi çağıran bir üst düzey rutin olabilir . Bu alt yöntemler kendi deneme yakalamalarına ihtiyaç duymaz, çünkü atarlarsa hala yakalama tarafından SaveDocument()yakalanırlar.

Bu üç nedenden dolayı güzel: bir hata bildirmek için tek bir yeriniz olduğu için kullanışlıdır: SaveDocument()catch blok (lar) ı. Bunu tüm alt yöntemler boyunca tekrarlamaya gerek yoktur ve yine de istediğiniz şeydir: kullanıcıya yanlış giden bir şey hakkında yararlı bir teşhis vermek için tek bir yer.

İkinci olarak, bir istisna atıldığında kaydetme iptal edilir. Her alt yöntem try-catch ile, bir istisna atılırsa, bu yöntemin catch bloğuna girersiniz, yürütme işlevi terk eder ve devam eder SaveDocument(). Eğer bir şeyler zaten yanlış giderse, muhtemelen orada durmak istersiniz.

Üç, tüm alt yöntemleriniz her çağrının başarılı olduğunu varsayabilir . Bir çağrı başarısız olursa, yürütme catch bloğuna atlar ve sonraki kod hiçbir zaman yürütülmez. Bu, kodunuzu daha temiz hale getirebilir. Örneğin, hata kodlarıyla birlikte:

int ret = SaveFirstSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

ret = SaveSecondSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

ret = SaveThirdSection();

if (ret == FAILED)
{
    /* some diagnostic */
    return;
}

Bunun istisnalar dışında nasıl yazılacağı aşağıda açıklanmıştır:

// these throw if failed, caught in SaveDocument's catch
SaveFirstSection();
SaveSecondSection();
SaveThirdSection();

Şimdi ne olduğu çok daha açık.

Özel durum güvenli kodunun başka yollarla yazılması daha zor olabilir: bir istisna atılırsa herhangi bir belleğe sızmak istemezsiniz. İstisnalardan önce nesneler her zaman tahrip edildiğinden, RAII , STL kapları, akıllı işaretçiler ve kaynaklarını yıkıcılarda serbest bırakan diğer nesneleri bildiğinizden emin olun .


2
Muhteşem örnekler. Evet, bir yük / kaydet / vb. Gibi bazı 'işlemsel' işlemler gibi mantıksal birimlerde mümkün olduğunca yüksek yakalayın. Hiçbir şey görünüyor tekrarlayan, yedekli ile biberli kod daha kötü try- catchblokları her biraz farklı hepsi aynı bitmeli gerçekte biraz farklı bir mesajla, bazı hata permütasyon, yukarı bayrağa girişimi: işlem veya program hatası ve çıkış! İstisnai bir hata oluşursa, çoğu kullanıcının sadece yapabildiklerini kurtarmak istediği ya da en azından, bu konuda 10 mesaj seviyesiyle uğraşmak zorunda kalmadan yalnız kalmak istediğine bahse girerim.
underscore_d

Sadece bunun şimdiye kadar okuduğum en iyi "erken at, geç yakala" açıklamalarından biri olduğunu söylemek istedim: özlü ve örnekler puanlarınızı mükemmel bir şekilde göstermektedir. Teşekkür ederim!
corderazo00

27

Herb Sutter bu sorun hakkında burada yazdı . Herhalde okumaya değer.
Fragman:

"İstisna-güvenli kod yazmak temelde doğru yerlere" dene "ve" yakala "yazmakla ilgilidir." Tartışır.

Açıkçası, bu ifade istisna güvenliğinin temel bir yanlış anlaşılmasını yansıtır. İstisnalar sadece hata raporlamanın başka bir şeklidir ve kesinlikle hata korumalı kod yazmanın sadece dönüş kodlarını nereden kontrol edeceğiniz ve hata koşullarını nasıl ele alacağımızla ilgili olmadığını biliyoruz.

Aslında, istisna güvenliğinin nadiren 'denemek' ve 'yakalamak' yazmakla ilgili olduğu ortaya çıkıyor - ve daha nadiren daha iyi. Ayrıca, istisna güvenliğinin bir kod tasarımını etkilediğini asla unutmayın; Baharat için olduğu gibi birkaç ekstra yakalama ifadesi ile uyarlanabilecek sadece bir sonradan düşünülemez.


15

Diğer yanıtlarda belirtildiği gibi, yalnızca bir tür mantıklı hata işleme yapabiliyorsanız bir istisna yakalamanız gerekir.

Örneğin , sorunuzu ortaya çıkaran soruda, soru soran lexical_cast, bir tamsayıdan dizgeye kadar olan istisnaları göz ardı etmenin güvenli olup olmadığını sorar . Böyle bir oyuncu asla başarısız olmamalı. Başarısız olursa, programda bir şeyler çok yanlış gitti. Bu durumda iyileşmek için ne yapabilirsiniz? Muhtemelen programın ölmesine izin vermek en iyisidir, çünkü güvenilir olmayan bir durumdadır. Bu nedenle, istisnayı ele almamak en güvenli şey olabilir.


12

İstisnaları her zaman istisna atabilecek bir yöntemin arayanında hemen ele alırsanız, istisnalar işe yaramaz hale gelir ve hata kodlarını kullanmanız daha iyi olur.

İstisnaların asıl amacı, çağrı zincirindeki her yöntemde ele alınmaları gerekmemesidir.


9

Duyduğum en iyi tavsiye, istisnai durum hakkında makul bir şey yapabileceğiniz noktalarda istisnaları yakalamanız gerektiğidir ve "yakala, kaydet ve bırak" iyi bir strateji değildir (bazen kütüphanelerde kaçınılmazsa).


2
@ KeithB: Bunu en iyi ikinci strateji olarak görüyorum. Günlüğü başka bir şekilde yazabilmeniz daha iyi olur.
David Thornley

1
@ KeithB: Bu bir "kütüphanede hiç yoktan iyidir" stratejisidir. "Yakala, günlüğe kaydet, düzgün bir şekilde baş et" mümkün olduğunda daha iyidir. (Evet, her zaman mümkün olmadığını biliyorum.)
Donal Fellows

6

Mümkün olan en düşük düzeyde istisnaları ele almak için sorunuzun temel yönüne katılıyorum.

Mevcut cevaplardan bazıları "İstisna ile başa çıkmanıza gerek yok. Başka biri bunu yığınının üstünde yapacak." Deneyimlerime göre, şu anda geliştirilen kod parçasında istisna işleme hakkında düşünmemek , bir başkasının veya daha sonra problemi istisna haline getirmek için kötü bir bahane .

Bu sorun, bir iş arkadaşı tarafından uygulanan bir yöntemi çağırmanız gerekebilecek dağıtılmış geliştirmede önemli ölçüde büyüyor. Ve sonra size neden bazı istisnalar attığını öğrenmek için iç içe bir yöntem çağrıları zincirini incelemeniz gerekir; bu, en derin iç içe yöntemde çok daha kolay ele alınabilirdi.


5

Bilgisayar bilimi profesörümün bana bir kez verdiği öneri şuydu: "Try ve Catch bloklarını sadece hatayı standart yöntemlerle ele almak mümkün olmadığında kullanın."

Örnek olarak, bir programın, aşağıdaki gibi bir şey yapmanın mümkün olmadığı bir yerde ciddi bir sorunla karşılaşması durumunda şunları söyledi:

int f()
{
    // Do stuff

    if (condition == false)
        return -1;
    return 0;
}

int condition = f();

if (f != 0)
{
    // handle error
}

O zaman deneyin, blokları yakalamak gerekir. Bunun üstesinden gelmek için istisnalar kullanabilirsiniz, ancak istisnalar pahalı performans açısından akıllıca olduğu için genellikle önerilmez.


7
Bu bir stratejidir, ancak birçok kişi bunun yerine istisnaları kullanarak işlevlerden asla hata kodları veya başarısızlık / başarı durumları döndürülmesini önermez . İstisna tabanlı hata işlemeyi okumak hata kodu tabanlı koda göre daha kolaydır. (Bir örnek için AshleysBrain'in bu soruya verdiği cevaba bakınız.) Ayrıca, birçok bilgisayar bilimi profesörünün gerçek kod yazma konusunda çok az deneyime sahip olduğunu daima unutmayın.
Kristopher Johnson

1
-1 @Sagelika Cevabınız istisnadan kaçınmaktan ibarettir, bu yüzden denemeye gerek yoktur.
Vicente Botet Escriba

3
@Kristopher: Dönüş kodunun diğer büyük dezavantajları, bir dönüş kodunu kontrol etmeyi unutmanın gerçekten kolay olmasıdır ve çağrıdan hemen sonra sorunu ele almak için en iyi yer değildir.
David Thornley

ehh, duruma göre değişir, ancak birçok durumda (gerçekten yapmamaları gerektiğinde atan insanları bir kenara koyun), istisnalar birçok nedenden dolayı kodları iade etmekten daha üstündür. içinde en durumlarda, istisnalar performansı için zararlı olduğu fikri [kaynak belirtilmeli] büyük bir ol' olduğu
underscore_d

3

Her işlevin sonucunu test etmek istiyorsanız, dönüş kodlarını kullanın.

İstisnaların amacı, sonuçları daha az test edebilmenizdir. Fikir, istisnai (olağandışı, daha nadir) koşulları daha sıradan kodunuzdan ayırmaktır. Bu, sıradan kodu daha temiz ve basit tutar - ancak yine de bu istisnai durumlarla başa çıkabilir.

İyi tasarlanmış kodda daha derin fonksiyonlar fırlayabilir ve daha yüksek fonksiyonlar yakalanabilir. Ancak kilit nokta, "aradaki" birçok işlevin istisnai koşulların üstesinden gelme yükünden muaf olacağıdır. Sadece "istisna güvenli" olmaları gerekir, bu da yakalamaları gerektiği anlamına gelmez.


2

Bu tartışmaya, C ++ 11'den beri , her catchbloğun rethrowişlenebileceği / ele alınması gereken noktaya kadar istisna olduğu sürece çok mantıklı olduğunu eklemek isterim . Bu şekilde bir geri izleme oluşturulabilir . Bu nedenle önceki görüşlerin kısmen modası geçmiş olduğuna inanıyorum.

Kullan std::nested_exceptionvestd::throw_with_nested

Burada ve burada StackOverflow'da bunu nasıl başaracağınız anlatılmaktadır .

Bunu herhangi bir türetilmiş istisna sınıfıyla yapabileceğiniz için, böyle bir geri izlemeye çok fazla bilgi ekleyebilirsiniz! Ayrıca , bir backtrace'ın şöyle görüneceği GitHub'daki MWE'mize de göz atabilirsiniz :

Library API: Exception caught in function 'api_function'
Backtrace:
~/Git/mwe-cpp-exception/src/detail/Library.cpp:17 : library_function failed
~/Git/mwe-cpp-exception/src/detail/Library.cpp:13 : could not open file "nonexistent.txt"

2

Uygulamanın çok fazla hatası olduğu ve kullanıcıların sorunlardan ve çalışmalardan bıktıkları için birkaç projeyi kurtarmak için "fırsat" verildi ve yöneticiler tüm dev ekibinin yerini aldı. Bu kod tabanlarının tümü, en üst oyu verilen yanıtın açıkladığı gibi uygulama düzeyinde merkezi hata işlemeye sahipti. Bu cevap en iyi uygulamadırsa neden işe yaramadı ve önceki geliştirici ekibin sorunları çözmesine izin vermedi? Belki bazen işe yaramıyor? Yukarıdaki yanıtlar, geliştiricilerin tek sorunları düzeltmek için ne kadar zaman harcadıklarından bahsetmiyor. Sorunları çözmek için zaman anahtar metrikse, try..catch blokları ile enstrüman kodu daha iyi bir uygulamadır.

Ekibim kullanıcı arayüzünü önemli ölçüde değiştirmeden sorunları nasıl çözdü? Basit, her yöntem try..catch bloke edildi ve her şey, hata adı, hata mesajı, uygulama adı, tarih, ve sürüm. Bu bilgi ile geliştiriciler en çok oluşan istisnayı belirlemek için hatalar üzerinde analiz çalıştırabilir! Veya en fazla sayıda hata içeren ad alanı. Ayrıca, bir modülde oluşan bir hatanın düzgün bir şekilde işlendiğini ve birden fazla nedenden kaynaklanmadığını doğrulayabilir.

Bunun bir başka avantajı da geliştiricilerin hata günlüğü yönteminde bir kırılma noktası ayarlayabilmeleri ve bir kırılma noktası ve "adım atma" hata ayıklama düğmesine tek bir tıklama ile, gerçek tam erişim ile başarısız olan yöntemde hata noktasında, hemen pencerede bulunan nesneler. Hata ayıklamayı çok kolay hale getirir ve kesin satırı bulmak için sorunu çoğaltmak için yürütme yönteminin başlangıcına geri sürüklenmesine izin verir. Merkezi kural dışı durum işleme, bir geliştiricinin 30 saniye içinde bir kural dışı durumu kopyalamasına izin veriyor mu? Hayır.

"Bir yöntem yalnızca mantıklı bir şekilde işleyebiliyorsa bir istisna yakalamalıdır." Bu, geliştiricilerin yayınlanmadan önce meydana gelebilecek her hatayı tahmin edebileceklerini veya karşılaşacaklarını ima eder. Bu bir üst düzey doğru olsaydı, uygulama istisnası işleyicisine ihtiyaç duyulmazdı ve Elastik Arama ve logstash için pazar olmazdı.

Bu yaklaşım aynı zamanda geliştiricilerin üretimde aralıklı sorunları bulmasını ve düzeltmesini sağlar! Üretimde hata ayıklayıcı olmadan hata ayıklamak ister misiniz? Yoksa üzgün kullanıcılardan çağrı alıp e-posta almayı mı tercih edersiniz? Bu, başkalarını bilmeden ve sorunu çözmek için gereken her şey orada olduğu için destekle e-posta, IM veya Slack'e gerek kalmadan sorunları düzeltmenize olanak tanır. Sorunların% 95'inin çoğaltılması gerekmez.

Düzgün çalışması için, ad alanının / modülün, sınıf adının, yöntemin, girdilerin ve hata iletisinin yakalanabileceği ve hangi yöntemin en başarısız olduğunu vurgulamak üzere toplanabilmesi için bir veritabanında depolanabilen merkezi günlük kaydı ile birleştirilmesi gerekir. önce sabit.

Bazen geliştiriciler, yığını bir bloktan istisnalar atmayı seçer, ancak bu yaklaşım, atmayan normal koddan 100 kat daha yavaştır. Günlüğe kaydetme ile yakalama ve bırakma tercih edilir.

Bu teknik, 2 yılda 12 Devs tarafından geliştirilen bir Fortune 500 şirketinde çoğu kullanıcı için her saat başarısız olan bir uygulamayı hızlı bir şekilde stabilize etmek için kullanıldı. Bu 3000 kullanılarak 4 ay içinde farklı istisnalar tanımlanmış, sabitlenmiş, test edilmiş ve dağıtılmıştır. Bu, ortalama olarak 4 ay boyunca her 15 dakikada bir düzeltmeye çıkar.

Kod enstrümanı için gerekli olan her şeyi yazmanın eğlenceli olmadığını kabul ediyorum ve tekrarlayan koda bakmamayı tercih ediyorum, ancak her yönteme 4 satır kod eklemek uzun vadede buna değer.


1
Her bloğu sarmak aşırıya kaçmış gibi görünüyor. Kodunuzu hızlı bir şekilde şişirir ve okumak acı verir. İstisnadan daha yüksek düzeylerde bir yığın izlemesinin kaydedilmesi, sorunun nerede oluştuğunu ve hatanın kendisiyle birleştirilmesinin genellikle devam etmek için yeterli bilgi olduğunu gösterir. Bunu yetersiz bulduğun yeri merak ediyorum. Başka birinin deneyimini kazanabilmem için.
user441521

1
"İstisnalar normal koddan 100 ila 1000 kat daha yavaştır ve hiçbir zaman tekrar gözden geçirilmemelidir" - bu ifade çoğu modern derleyici ve donanımda doğru değildir.
Mitch Wheat

Aşırıya kaçmış gibi görünüyor ve biraz yazmayı gerektiriyor, ancak önce üretimdeki aralıklı hatalar da dahil olmak üzere en büyük hataları bulmak ve düzeltmek için istisnalar üzerinde analiz yapmanın tek yolu. Catch bloğu gerektiğinde belirli hataları işler ve günlük tutan tek bir kod satırı içerir.
user2502917

Hayır, istisnalar çok yavaş. Alternatif, dönüş kodları, nesneler veya değişkenlerdir. Bu yığın taşma
yazısına

1

Yukarıdaki tavsiyenin yanı sıra, şahsen bazı try + catch + throw kullanıyorum; aşağıdaki nedenle:

  1. Farklı kodlayıcının sınırında, başkaları tarafından yazılan arayan için istisna yapılmadan önce, kendim tarafından yazılan kodda try + catch + throw kullanıyorum, bu bana kodumda meydana gelen bazı hata koşullarını öğrenme şansı veriyor ve Burası başlangıçta istisna atmak koduna çok daha yakın, daha yakın, nedeni bulmak daha kolay.
  2. Modüllerin sınırında, aynı modülüm farklı modül yazılabilse de.
  3. Öğrenme + Hata Ayıklama amacı, bu durumda C ++ 'da catch (...) ve C #' da catch (Exception ex) kullanıyorum, C ++ için standart kütüphane çok fazla istisna atmaz, bu nedenle bu durum C ++ 'da nadirdir. Ama C #, C # ortak bir yerde büyük bir kütüphane ve olgun bir istisna hiyerarşisi vardır, C # kütüphane kodu ton istisna atmak, teorik olarak ben (ve siz) aradığınız işlevden her istisna bilmeli ve nedenini / vakasını bilmelisiniz bu istisna atılır ve bunları nasıl ele alacağınızı bilir (yanından geçirin veya yerinde yakalayın ve ele alın). Ne yazık ki gerçekte, bir kod satırı yazmadan önce potansiyel istisnalar hakkında her şeyi bilmek çok zor. Bu yüzden hepsini yakalarım ve herhangi bir istisna gerçekten meydana geldiğinde (ürün ortamında) / onaylama iletişim kutusunu (geliştirme ortamında) kaydederek kodumun yüksek sesle konuşmasına izin verdim. Bu şekilde aşamalı olarak istisna işleme kodu eklerim. İyi bir tavsiye ile örtüştüğünü biliyorum ama gerçekte benim için çalışıyor ve bu sorun için daha iyi bir yol bilmiyorum.

1

Mike Wheat'ın cevabı ana noktaları oldukça iyi özetlese de başka bir cevap eklemek zorunda hissediyorum. Ben böyle düşünüyorum. Birden fazla şey yapan yöntemleriniz olduğunda, karmaşıklığı çoğaltırsınız, eklemezsiniz.

Başka bir deyişle, bir try catch içine sarılmış bir yöntemin iki olası sonucu vardır. İstisnai olmayan sonucunuz ve istisna sonucunuz var. Birçok yöntemle uğraşırken, bu katlanarak kavrayışın ötesine geçer.

Üstel olarak, eğer her yöntem iki farklı şekilde dallanırsa, başka bir yöntemi her çağırışınızda, önceki potansiyel sonuçların karesini alırsınız. Beş yöntem çağırdığınızda, en az 256 olası sonuç elde edersiniz. Bu karşılaştırın değil her yöntemde bir try / catch yapıyor ve sadece takip etmek tek yolu var.

Temelde ben böyle bakıyorum. Herhangi bir dallanma türünün aynı şeyi yaptığını iddia etmek cazip gelebilir, ancak deneme / yakalama özel bir durumdur, çünkü uygulamanın durumu temelde tanımsız hale gelir.

Kısacası, deneme / yakalama kodunu anlamak çok daha zor hale getirir.


-2

Kodunuzun her bölümünü içeride saklamanıza gerek yoktur try-catch. try-catchBloğun ana kullanımı hata işleme ve programınızda hatalar / istisnalar almaktır. Bazı kullanımları try-catch-

  1. Bir istisnayı işlemek istediğiniz yerde bu bloğu kullanabilirsiniz veya yazılı kod bloğunun bir istisna atabileceğini söyleyebilirsiniz.
  2. Nesnelerinizi kullanıldıktan hemen sonra imha etmek istiyorsanız, try-catchbloğu kullanabilirsiniz .

1
"Nesnelerinizi kullanımlarından hemen sonra imha etmek istiyorsanız, try-catch bloğunu kullanabilirsiniz." Bunu RAII / minimal nesne ömrünü teşvik etmek istediniz mi? Eğer öyleyse, try/ catchtamamen tamamlanmış / ortogonaldir. Nesneleri daha küçük bir kapsamda atmak istiyorsanız, sadece yeni bir şey açabilirsiniz { Block likeThis; /* <- that object is destroyed here -> */ }- elbette bir şeye ihtiyacınız olmadığı sürece try/ içine sarmanıza gerek yoktur . catchcatch
underscore_d

# 2 - Nesneleri (elle oluşturulan) istisna olarak atmak benim için garip görünüyor, bu şüphesiz bazı dillerde yararlı olabilir, ancak genellikle bunu bir try / nihayet "try / hariç blok içinde" yaparsınız ve özellikle dış blokta - nesnenin kendisi ilk etapta istisnanın nedeni olabilir ve bu nedenle başka bir istisna ve potansiyel olarak bir çökmeye neden olabilir.
TS
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.