Hata işleme - Bir program hatalarda başarısız olursa veya sessizce yoksayarsa


20

Bir ağ üzerinden MIDI iletmek için basit bir küçük program yazıyorum. Programın iletim sorunları ve / veya tahmin edemeyeceğim diğer istisna durumları ile karşılaşacağını biliyorum.

İstisna yönetimi için iki yaklaşım görüyorum. Programı yazmalı mıyım ki:

  • bir şeyler ters gittiğinde patlama ile başarısız olur veya
  • sadece hatayı yoksaymalı ve veri bütünlüğü pahasına devam etmeli mi?

Bir kullanıcı makul olarak hangi yaklaşımı bekler?
İstisnaları ele almanın daha iyi bir yolu var mı?

Ayrıca, istisnaları ele alma konusundaki kararım, bir ağ bağlantısıyla (örneğin, sorunların ortaya çıkmasını beklediğim bir şey) ilgilenip ilgilenmememden etkilenmeli mi?


1
@ GlenH7 İleri ödeyin ... :)
gnat

Düzenlemeleri + 1'lemenin bir yolu var mı? ;) Oh, bekle, seni takip ediyorum. Elbette, yapacak :)
Arlen Beiler

2
"Kullanıcı hangi yaklaşımı makul bir şekilde bekler?". Kullanıcılarınızdan birine sormayı denediniz mi? Koridor kullanılabilirlik testi oldukça etkili olabilir. Bkz. Blog.openhallway.com/?p=146
Bryan Oakley

Hiç kullanıcım yok :)
Arlen Beiler

Yanıtlar:


34

Programınızın karşılaştığı bir hatayı asla görmezden gelmemelisiniz. En azından, bildirim için bir dosyaya veya başka bir mekanizmaya kaydetmelisiniz. Orada olabilir bir hata görmezden ama isteyeceksiniz ara sıra durumlar olabilir bunu belgelemek! catchNeden boş olduğunu açıklayan herhangi bir yorum yapmadan boş bir blok yazmayın .

Programın başarısız olup olmayacağı duruma çok bağlıdır. Hatayı incelikle işleyebiliyorsanız, devam edin. Beklenmedik bir hataysa, programınız çökecektir. Bu istisna işlemenin temelini oluşturuyor.


18
-1'i garanti etmek için yeterli değildir, ancak "asla" güçlü bir kelimedir ve hataları görmezden gelmenin doğru eylem şekli olduğu durumlar vardır. Örneğin, yayın HDTV yayınlarının kodunu çözmek için yazılım. Sıklıkla karşılaşacağınız bazı hatalarla karşılaştığınızda, tek yapmanız gereken onu görmezden gelmek ve daha sonra gelenleri çözmektir.
whatsisname

1
@whatsisname: true, ancak bunu neden yok saydığınızı açıkça belgelemeniz gerekir. Yorumunuzu dikkate almak için cevap güncellendi.
marco-fiset

1
@ marco-fiset katılmıyorum. Tüm programın çökmesi, yalnızca yeniden başlatmanın sorunu çözeceği bir durumsa çözümdür. Bu her zaman böyle değildir, bu yüzden çökmek genellikle anlamsızdır ve davranışların salak aptal olduğunu varsaymaktadır. Yerelleştirilmiş bir hata nedeniyle tüm işleminizi neden askıya almak istersiniz? Bu hiç mantıklı değil. Çoğu uygulama bunu yapar ve bazı nedenlerden dolayı, programcılar bununla tamamen iyi durumdadır.
MaiaVictor

@Dokkat: önemli olan yanlış değerlerle devam etmemek, yanlış bir çözüm (çöp içeri, çöp dışarı) verecek. Çökme sorunu
çözer

1
@whatsisname Bu durumda "hata" tanımınızı düşünmek isteyebileceğinizi düşünüyorum. Alınan verilerdeki hatalar, bir yazılım programının yapısında ve yürütülmesindeki hatalarla aynı şey değildir.
joshin4colours

18

Hataları asla göz ardı etmemelisiniz, çünkü programınız doğru gitmeden önce giden her şeye dolaylı olarak bağlı olan bir dizi eylem üzerine kurulmuştur. 3. adımda bir şeyler ters giderse ve 4. adıma geçmeye çalışırsanız, 4. adım geçersiz varsayımlara dayanarak başlar, bu da hataya neden olma olasılığını artırır. (Bunu da görmezden gelirseniz, 5. adım bir hata atar ve işler oradan kartopuna başlar.)

Sorun şu ki, hatalar biriktikçe, sonunda görmezden gelemeyeceğiniz kadar büyük bir hatayla karşılaşacaksınız, çünkü kullanıcıya verilen bir şeyden oluşacak ve bir şey tamamen yanlış olacak. Ardından, programınızın düzgün çalışmadığı konusunda size şikayet eden kullanıcılarınız var ve bunu düzeltmeniz gerekiyor. Ve "kullanıcıya bir şeyler ver" bölümü 28. adımda ise ve tüm bu karışıklığa neden olan orijinal hatanın 3. adımda olduğu hakkında hiçbir fikriniz yoksa, 3. adımdaki hatayı görmezden geldiyseniz, sorun hata ayıklama bir zaman heck!

Öte yandan, 3. adımdaki bu hata her şeyi kullanıcının yüzüne patlatırsa ve SOMETHING WENT BADLY WRONG IN STEP 3!(veya teknik eşdeğeri, bir yığın izlemesi) diyerek bir hata oluşturursa , sonuç aynıdır - kullanıcı size şikayet ediyor program düzgün çalışmıyor - ancak bu sefer düzeltmeye gittiğinizde nereye bakmaya başlayacağınızı tam olarak biliyorsunuz .

DÜZENLEME: Yorumlara yanıt olarak, tahmin ettiğiniz ve nasıl başa çıkacağınızı bildiğiniz bir şeyler ters giderse, bu farklıdır. Örneğin, hatalı biçimlendirilmiş bir ileti alınması durumunda, bu bir program hatası değildir; "kullanıcı, doğrulama başarısız olan hatalı girdi sağladı." Uygun yanıt, kullanıcıya size geçersiz girdi verdiğini, yaptığınız gibi göründüğünü söylemektir. Böyle bir durumda çökmeye ve yığın izlemesi oluşturmaya gerek yoktur.


Bilinen son iyi konuma geri dönmeye veya bir alıcı döngü söz konusu olduğunda, bu iletiyi bırakıp bir sonrakine gitmeye ne dersiniz?
Arlen Beiler

@Arlen: Bu bile kötü bir fikir olabilir. Hatalar , kodlama sırasında tahmin etmediğiniz bir şey olduğu için oluşur . Bu, tüm varsayımlarınızın pencereden çıktığı anlamına gelir. Bazı "veri yapısını değiştirerek yarı yolda olsaydınız ve şimdi tutarsız bir durumdaysanız," son bilinen iyi konum "artık iyi olmayabilir.
Mason Wheeler

Sürdürülebilirliği önleyen bozuk iletiler gibi, ne bekliyorsam. Bazı durumlarda, istisnayı serileştirdim ve tel üzerinden geri gönderdim. Orada, soruya ilişkin düzenlememi görün.
Arlen Beiler

@ Arlen: Bunu önceden tahmin ettiyseniz ve hatanın etkilerinin ne olduğunu ve bunların doğru bir şekilde içerildiğini bildiğinizden eminseniz, bu farklıdır. Hatayı ele aldığınız ve uygun şekilde yanıtladığınız, görmezden gelmediğiniz gibi bana geliyor. Beklenmedik hataları görmezden gelmeye çalışıyordum .
Mason Wheeler

16

"Üfleme" ve "yoksay" arasında başka seçenekler de vardır.

Hata tahmin edilebilir ve önlenebilirse, tasarımınızı değiştirin veya önlemek için kodunuzu yeniden düzenleyin.

Hata tahmin edilebilir ancak önlenemezse, ancak gerçekleştiğinde ne yapacağınızı biliyorsanız, hatayı yakalayın ve durumu ele alın. Ancak akış kontrolü olarak istisnaları kullanmaktan kaçınmaya dikkat edin. Ve bu noktada bir uyarı kaydetmek ve gelecekte bu durumdan kaçınmak için yapabilecekleri bir eylem varsa kullanıcıyı bilgilendirmek isteyebilirsiniz.

Hata tahmin edilebilir, kaçınılmazsa ve gerçekleştiğinde, veri bütünlüğünü garanti edecek hiçbir şey yapmazsanız, hatayı günlüğe kaydetmeniz ve güvenli bir duruma geri dönmeniz gerekir (diğerlerinin söylediği gibi çökme anlamına gelebilir).

Hata beklediğiniz bir şey değilse, o zaman gerçekten güvenli bir duruma geri dönebileceğinizden emin olamazsınız, bu yüzden sadece günlüğe kaydetmek ve çökmek en iyisi olabilir.

Genel bir kural olarak, sadece günlüğe kaydetmeyi ve yeniden düşünmeyi planlamazsanız, hiçbir şey yapamayacağınız istisnaları yakalamayın. Ve bir try-catch-ignore'un kaçınılmaz olduğu nadir durumlarda, en azından nedenini açıklamak için catch bloğunuza bir yorum ekleyin.

Bkz Eric Lippert mükemmel durum işleme makale kategorize ve durumları işleme konusunda daha fazla öneriler için.


1
Bence en iyi cevap.
thursdaysgeek

6

Bunlar benim soru hakkındaki görüşlerim:

İyi bir başlangıç ​​prensibi hızlı başarısız olmaktır. Özellikle, kesin sebebini bilmediğiniz bir hata için asla hata işleme kodu yazmamalısınız.

Bu ilkeyi uyguladıktan sonra, karşılaştığınız belirli hata durumları için kurtarma kodu ekleyebilirsiniz. Ayrıca geri dönmek için birkaç "güvenli durum" da tanıtabilirsiniz. Bir programı iptal etmek çoğunlukla güvenlidir, ancak bazen bilinen başka bir iyi duruma geri dönmek isteyebilirsiniz. Bir örnek, modern bir işletim sisteminin rahatsız edici bir programı nasıl ele aldığıdır. Sadece işletim sistemini kapatır, tüm işletim sistemini değil.

Hızlı ve yavaş bir şekilde daha fazla ve daha spesifik hata koşullarını kapatarak veri bütünlüğünden asla ödün vermez ve sürekli olarak daha kararlı bir programa geçemezsiniz.

Hataları yutmak, yani kesin sebebini bilmediğiniz ve bu nedenle belirli bir kurtarma stratejisi olmayan hataları planlamaya çalışmak, yalnızca programınızda hata atlama ve atlayan kodun miktarının artmasına neden olur. Önceki verilerin doğru bir şekilde işlendiğine güvenemeyeceğinden, yanlış veya eksik veriler için yayılmış kontroller görmeye başlayacaksınız. Siklomatik karmaşıklığınız elden çıkacak ve büyük bir çamur topu ile sonuçlanacaksınız.

Arıza durumlarının farkında olup olmamanız daha az önemlidir. Ancak, örneğin belirli bir sayıda hata durumunu bildiğiniz bir ağ bağlantısıyla uğraşıyorsanız, kurtarma kodu da ekleyene kadar hata işlemeyi erteleyin. Bu, yukarıda belirtilen ilkelere uygundur.


6

Sen asla sessizce hataları görmezden. Ve özellikle veri bütünlüğü pahasına değil .

Program bir şeyler yapmaya çalışıyor. Başarısız olursa, gerçekle yüzleşmeli ve bu konuda bir şeyler yapmalısınız. Bir şeyin ne olacağı pek çok şeye bağlıdır.

Sonunda kullanıcı programdan bir şey yapmasını istedi ve programın başarılı olamadığını söylemelidir. Bunu yapmanın birçok yolu vardır. Hemen durdurulabilir, hatta zaten tamamlanmış adımları geri alabilir veya diğer taraftan devam edebileceği ve tamamlayabileceği tüm adımları tamamlayabilir ve daha sonra kullanıcıya bu adımların başarılı olduğunu ve diğerlerinin başarısız olduğunu söyleyebilir.

Hangi yolu seçeceğiniz, adımların ne kadar yakından ilişkili olduğuna ve hatanın gelecekteki tüm adımlar için tekrarlanıp oluşmayacağına bağlıdır ve bu da tam hataya bağlı olabilir. Güçlü veri bütünlüğü gerekiyorsa, son tutarlı duruma geri dönmeniz gerekir. Sadece bir grup dosyayı kopyalıyorsanız, bazılarını atlayabilir ve sonunda kullanıcıya bu dosyaların kopyalanamayacağını söyleyebilirsiniz. Sessizce dosyaları atlamamalı ve kullanıcıya hiçbir şey söylememelisiniz.

Reklam düzenleme, tek fark, ağdan tekrar denediğinizde yeniden oluşmayacak geçici hatalara sahip olması muhtemel olduğundan, vazgeçmeden ve kullanıcıya çalışmadığını söylemeden önce birkaç kez yeniden denemeyi düşünmenizdir.


Gerçekten ilk satırın sonuna soru işareti koymak mı istediniz?
CVn

@ MichaelKjörling: Hayır. Kopyala-yapıştır hatası (formülasyonu sorudan kopyaladı ve soru işaretini yanlışlıkla ekledi).
Jan Hudec

4

Hataları görmezden gelmenin doğru bir şey olduğu bir durum sınıfı vardır: Durum hakkında yapılabilecek hiçbir şey olmadığında ve kötü ve muhtemelen yanlış sonuçların sonuçlardan daha iyi olduğu durumlarda.

HDMI akışının görüntüleme amaçları için deşifre edilmesi durumu böyle bir durumdur. Akış kötü ise, kötü, onu bağırmak sihirli bir şekilde düzeltmez. Görüntülemek için elinizden geleni yaparsınız ve izleyicinin tolere edilebilir olup olmadığına karar vermesine izin verirsiniz.


1

Bir programın, bir sorunla karşılaştığında sessizce yok sayması veya hasara neden olması gerektiğine inanmıyorum.

Şirketim için yazdığım dahili yazılımla ne yapıyorum ...

Hataya bağlıdır, MySQL'e veri giren kritik bir işlevse, kullanıcının başarısız olduğunu bildirmesi gerektiğini söyleyelim. Hata işleyici, çok fazla bilgi toplamaya çalışmalı ve kullanıcıya verileri kaydedebilmeleri için hatanın nasıl düzeltileceği hakkında bir fikir vermelidir. Ayrıca, sessizce bize kaydetmeye çalıştıkları bilgileri göndermenin bir yolunu sağlamak istiyorum, böylece daha kötüsü kötüleşirse, hata düzeltildikten sonra manuel olarak girebiliriz.

Kritik bir işlev değilse, hata yapabilecek ve elde etmeye çalıştıkları şeyin nihai sonucunu etkilemeyen bir şey değilse, onlara bir hata mesajı göstermeyebilirim, ancak otomatik olarak hata izleme yazılımımıza ekleyen bir e-posta göndermesini isteyin veya şirketteki tüm programcıları uyaran ve kullanıcı olmasa bile hatanın farkında olmamız için bir e-posta dağıtım grubudur. Bu, ön uçta kimse ne olduğunu bilmiyorken arka ucu sabitlememizi sağlar.

Kaçınmaya çalıştığım en büyük şeylerden biri, hatadan sonra programın çökmesini sağlamaktır - kurtarılamamak. Her zaman kullanıcıya uygulamayı kapatmadan devam etme seçeneği vermeye çalışırım.

Kimse hatayı bilmiyorsa inanıyorum - bu asla düzeltilmeyecek. Ayrıca, bir hata keşfedildikten sonra uygulamanın çalışmaya devam etmesini sağlayan hata işleme konusunda sağlam bir inançlıyım.

Hata ağ ile ilgiliyse - ilk etapta hatayı önlemek için fonksiyonlar çalıştırılmadan önce fonksiyonlar neden basit bir ağ iletişim testi yapmıyor? O zaman sadece bir bağlantının mevcut olmadığına dair kullanıcıyı uyarmak için lütfen internetinizi vb. Doğrulayın ve tekrar deneyin.


1
Tamamen anlamadığım ve ayrıntılı bilgi döndüren yararlı hata işleme sağlayamadığım hataları sınırlamaya çalışmak için kritik işlevleri çalıştırmadan önce kişisel olarak çok fazla doğrulama yapıyorum. Zamanın% 100'ü işe yaramıyor, ama son saatlerde beni saatlerce kaybettiren bir hatayı aldığımı hatırlayamıyorum.
Jeff

1

Benim stratejim kodlama hataları (hatalar) ve çalışma zamanı hataları arasında ayrım yapmak ve mümkün olduğunca kodlama hatalarının oluşturulmasını zorlaştırmak.

Hataların en kısa sürede düzeltilmesi gerekir, bu nedenle Sözleşmeye Göre Tasarım yaklaşımı uygundur. C ++, ben mümkün olan en kısa sürede hata tespit etmek ve bir hata ayıklayıcı eklemek ve hata düzeltmek kolaylaştırmak için fonksiyonun üstündeki iddiaları ile tüm önkoşulları (girişler) kontrol etmek istiyorum. Geliştirici veya test cihazı bunun yerine programı çalıştırmaya devam etmeyi seçerse, veri bütünlüğü kaybı sorun haline gelir.

Ve ilk etapta hatayı önlemenin yollarını bulun. Const-doğruluk ile sıkı olmak ve tutacağı veriler için uygun veri türlerini seçmek, hata oluşturmayı zorlaştırmanın iki yoludur. Fail-Fast , kurtarma için bir yol gerektiren güvenlik açısından kritik kod dışında da iyidir.

İçin çalışma zamanı hataları bu tür bir ağ veya seri iletişim arızaları veya eksik veya bozuk dosyaları gibi muhtemelen hata içermeyen kod ile olabilirdi:

  1. Hatayı günlüğe kaydedin.
  2. (İsteğe bağlı) İşlemi sessizce yeniden denemeyi veya başka bir şekilde kurtarmayı deneyin.
  3. İşlem başarısız olmaya devam ederse veya kurtarılamazsa, hatayı kullanıcıya görünür şekilde bildirin. Daha sonra yukarıdaki gibi, kullanıcı ne yapacağına karar verebilir. En Küçük Şaşkınlık İlkesini hatırlayın , çünkü önceden uyarmadıkça veri bütünlüğü kaybı kullanıcı için şaşırtıcıdır.

0

Programın genel durumunun kararsız olduğunu ve bundan sonra çalışmasına izin verirseniz kötü bir şey olduğunu düşünmek için nedenleriniz olduğunda başarısızlık doğru seçenektir. Biraz "yok saymak" (yani, diğerlerinin işaret ettiği gibi, bir yere giriş yapmak veya kullanıcıya bir hata mesajı görüntülemek, sonra devam etmek), geçerli işlemin gerçekleştirilemeyeceğini bildiğinizde tamamdır, ancak program Koşmaya devam et.

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.