Hata işlemeyi gerçekleştirmenin modern yolu ...


118

Bu problemi bir süredir tartışıyorum ve sürekli olarak uyarılar ve çelişkiler bulurken kendimi sürekli buluyorum, bu yüzden birinin aşağıdakilere bir sonuç verebileceğini umuyorum:

Hata kodları üzerindeki istisnaları tercih etme

Bildiğim kadarıyla, dört yıldır sektörde çalışmaktan, kitap okumak, blog okumak, vb. Hataları düzeltmek için en iyi uygulama hata kodlarını döndürmek yerine istisnalar atmaktır (mutlaka bir hata kodu değil, fakat hatayı temsil eden tür).

Ama - Bana göre bu çelişkili görünüyor ...

Arayüzlere kodlama, uygulamalara değil

Birleşmeyi azaltmak için arayüzleri ve soyutlamaları kodlarız Bir arabirimin belirli bir türünü ve uygulamasını bilmiyoruz veya bilmek istiyoruz. Öyleyse, hangi istisnaları yakalamak istediğimizi nasıl bilebiliriz? Uygulama 10 farklı istisna atabilir veya hiçbirini atmayabilir. Kesinlikle bir istisna yakaladığımızda, uygulama hakkında varsayımlarda bulunuyoruz?

Tabi - arayüzde ...

İstisna özellikleri

Bazı diller, geliştiricilerin belirli yöntemlerin belirli istisnalar attığını belirtmelerine izin verir (örneğin, Java throwsanahtar kelimeyi kullanır .) Arama kodunun bakış açısına göre bu iyi görünüyor - hangi istisnaları yakalamamız gerekebileceğini açıkça biliyoruz.

Ancak - bu bir ...

Sızdıran soyutlama

Bir arabirim neden hangi istisnaların atılabileceğini belirtmelidir? Uygulamanın bir istisna atması gerekmiyorsa veya başka istisnalar atması gerekiyorsa? Bir uygulama düzeyinde, bir uygulamanın hangi istisnaları atmak isteyebileceğini bilmek mümkün değildir.

Yani...

Sonuçlandırmak

Yazılımın en iyi uygulamalarıyla çelişiyor gibi göründüğünde (gözlerimin içinde) neden istisnalar tercih ediliyor? Ve eğer hata kodları çok kötüyse (ve hata kodlarından başka birine satılmam gerekmiyor), başka bir alternatif var mı? Yukarıda ana hatları verilen en iyi uygulamaların gerekliliklerini karşılayan, ancak hata kodlarının dönüş değerini kontrol eden kod çağırmaya dayanmayan, hata yönetimi için mevcut durum (veya yakın zamanda) nedir?


12
Sızdıran soyutlamalar hakkındaki argümanınızı anlamıyorum. Belirli bir yöntem nedir istisna belirtilmesi olabilir atmak olduğunu arayüz özelliklerinin bir parçası . Dönen değerin türü, arayüz belirtiminin bir parçası olduğu gibi. İstisnalar sadece fonksiyonun "solundan çıkmaz" değildir, fakat bunlar hala arayüzün bir parçasıdır.
12'de

@deceze Bir arabirim bir uygulamanın ne atabileceğini nasıl belirtir? Tip sistemindeki tüm istisnaları atabilir! Ve birçok dil istisna özellikleri desteklemiyor, oldukça tehlikeli olduklarını gösteriyor
RichK

1
Kendisi başka yöntemler kullanıyorsa ve istisnalarını içeride yakalamazsa, bir yöntemin atabileceği tüm farklı istisnaları yönetmenin zor olacağına katılıyorum. Bunu söyledikten sonra, bu bir çelişki değildir.
12'de

1
Buradaki sızdıran varsayım, kodun arayüz sınırından çıktığında bir istisna işleyebileceğidir . Neyin yanlış gittiğini hakkında neredeyse yeterince şey bilmediği göz önüne alındığında, bu pek mümkün değildir. Tek bildiği bir şeyin yanlış gittiği ve arayüz uygulamasının bununla nasıl başa çıkacağını bilmediği. Daha iyi bir iş yapabilme olasılığı, raporlamanın ve programı sonlandırmanın ötesinde kötüdür. Arayüz uygun program çalışması için kritik değilse veya yoksayma. Arayüz sözleşmesinde kodlayamayacağınız ve kodlamayacağınız bir uygulama detayı.
Hans Passant

Yanıtlar:


31

Her şeyden önce, bu ifadeye katılmıyorum:

Hata kodları üzerindeki istisnaları tercih etme

Bu her zaman böyle değildir: örneğin, Objective-C'ye bir göz atın (Foundation çerçevesi ile). Burada, bir Java geliştiricisinin gerçek istisnalar olarak adlandırdığı şeyin varlığına rağmen, NSError hataları ele almanın tercih edilen yoludur: @try, @catch, @throw, NSException sınıfı, vb.

Ancak, birçok arayüzün soyutlamaları atılan istisnalarla sızdırdığı doğrudur. Benim inancım, bunun “istisna” tarzında bir hata üretme / kullanma tarzının hatası olmadığıdır. Genel olarak, hata işlemeyle ilgili en iyi tavsiyenin bu olduğuna inanıyorum:

Hata / istisna ile mümkün olan en düşük seviyede işlem yapın.

Sanırım biri bu kurallara sadık kalırsa, soyutlamalardan gelen "sızıntı" miktarı çok sınırlı ve içerilebilir.

Bir yöntem tarafından atılan istisnaların beyannamenin bir parçası olması gerekip gerekmediğine göre, inanıyorum ki: bunlar bu arayüz tarafından tanımlanan sözleşmenin bir parçası : Bu yöntem A yapıyor veya B veya C ile başarısız.

Örneğin, bir sınıf bir XML Ayrıştırıcı ise, tasarımının bir kısmı, sağlanan XML dosyasının tamamen yanlış olduğunu belirtmek olmalıdır. Java’da normalde, karşılaşmayı umduğunuz istisnaları bildirerek ve bunları throwsyöntem bildiriminin bir bölümüne ekleyerek yaparsınız . Öte yandan, ayrıştırma algoritmalarından biri başarısız olursa, bu istisnayı işlenmemiş olanın üstüne çıkarmak için hiçbir neden yoktur.

Hepsi tek bir şeyle kaynar: İyi arayüz tasarımı. Arayüzünüzü yeterince iyi tasarlarsanız, hiçbir istisnalar sizi rahatsız etmemelidir. Aksi takdirde, sadece sizi rahatsız edecek istisnalar değildir.

Ayrıca, Java yaratıcılarının bir yöntem bildirimi / tanımı istisnaları dahil etmek için çok güçlü güvenlik nedenleri olduğunu düşünüyorum.

Sonuncusu: Örneğin bazı diller, Eiffel gibi, hata işleme için başka mekanizmalara sahiptir ve atma yeteneklerini içermez. Orada, bir rutin için bir şart koşulu yerine getirilmediğinde bir "istisna" otomatik olarak ortaya çıkar.


12
"Hata kodları dışındaki istisnaları favoriye al" ı reddetmek için +1. İstisnaların kural ve kurallar olmadığı sürece, istisnaların iyi ve iyi olduğu öğretildi. Bir koşulun doğru olup olmadığına karar vermek için bir istisna atan bir yöntem aramak, son derece kötü bir uygulamadır.
Neil,

4
@JoshuaDrake: Kesinlikle yanlış. İstisnalar ve gotoçok farklı. Örneğin, istisnalar her zaman aynı yönde, çağrı yığından aşağı doğru gider. Eğer temizleme sağlamak için de ray kullanırsanız Ve ikinci olarak, sürpriz istisnalar kendinizi korumak o zaman içinde temizliği garanti altına, tam C ++ örneğin kuru-aynı uygulama olduğu tüm durumlarda, sadece istisna değil, aynı zamanda tüm normal kontrol akışını. Bu sonsuz daha güvenilir. try/finallybiraz benzer bir şey başarır. Temizliği doğru bir şekilde garanti ettiğinizde, istisnaları özel bir durum olarak düşünmeniz gerekmez.
DeadMG

4
@JoshuaDrake Üzgünüz, ama Joel yoldan çıktı. İstisnalar, goto ile aynı değildir, her zaman arama yığınında en az bir seviye yukarı gidersiniz. Ve yukarıdaki seviye derhal hata koduyla baş edemiyorsa ne yaparsınız? Başka bir hata kodu döndürülsün mü? Hatalı sorunun bir kısmı, görmezden gelinebilmeleridir, istisnaların atılmasından daha kötü sorunlara yol açarlar.
Andy

25
-1 çünkü "Hata / istisna ile mümkün olan en düşük seviyede ilgilen" konusuna tamamen katılmıyorum - bu yanlış. Hataları / istisnaları uygun seviyede ele alın. Oldukça sık, bu çok daha yüksek bir seviyedir ve bu durumda, hata kodları çok büyük bir acıdır. Hata kodları üzerindeki istisnaları tercih etmenin nedeni, aradaki seviyeleri etkilemeden, onlarla hangi seviyede başa çıkacağınızı özgürce seçmenize izin vermeleridir.
Michael Borgwardt

2
@Giorgio: bkz. Artima.com/intv/handcuffs.html - özellikle sayfa 2 ve 3
Michael Borgwardt

27

Sadece istisnaların ve hata kodlarının, hatalarla ve alternatif kod yollarıyla baş etmenin tek yolu olmadığını belirtmek isterim.

Aklın tepesinden, Haskell'in aldığı hatalara benzer bir yaklaşıma sahip olabilirsiniz; burada hatalar birden fazla kurucu ile soyut veri türleri (işaretli ayırımlar veya boş işaretçiler, ancak yazı tipi güvencesi ve sözdizimi ekleme olasılığı ile) kod akışının iyi görünmesini sağlamak için şeker veya yardımcı işlevler).

func x = do
    a <- operationThatMightFail 10
    b <- operationThatMightFail 20
    c <- operationThatMightFail 30
    return (a + b + c)

operationThatMightfail, Belki de içine sarılmış bir değer döndüren bir işlevdir. Boş bir işaretçi gibi çalışır, ancak gösterim, a, b veya c'nin herhangi birinin başarısız olması durumunda her şeyin boş olduğunu değerlendirir. (ve derleyici sizi yanlışlıkla NullPointerException yapmaktan korur)

Diğer bir olasılık, bir hata işleyici nesnesini, çağırdığınız her işleve ekstra bir argüman olarak geçirmektir. Bu hata işleyicisi, her bir olası "istisna" için, onu ilettiğiniz işlev tarafından işaretlenebilen ve bu işlev tarafından, istisnalar dışında yığını geri sarmak zorunda kalmadan istisnaları tedavi etmek için kullanılabilecek bir yönteme sahiptir.

Yaygın LISP bunu yapar ve sözdizimi desteğine (örtük argümanlar) dayanarak ve yerleşik işlevlerin bu protokolü izlemesini mümkün kılar.


1
Bu gerçekten temiz. Alternatiflerle ilgili bölüme cevap verdiğiniz için teşekkür ederiz :)
RichK

1
BTW, istisnalar, modern zorunlu dillerin en işlevsel kısımlarından biridir. İstisnalar bir monad oluşturur. İstisnalar, bilmece eşleştirmesini kullanır. İstisnalar, gerçekte ne Maybeolduğunu öğrenmeden uygulama stilini taklit etmeye yardımcı olur.
9000

Son zamanlarda SML hakkında bir kitap okuyordum. Seçenek tipleri, istisnalar (ve sürekliliklerden) bahsetti. Tavsiye, tanımlanmamış vakanın oldukça sık gerçekleşmesi beklenen seçenek türlerini kullanmak ve tanımlanmamış vaka çok nadir meydana geldiğinde istisnalar kullanmaktı.
Giorgio

8

Evet, istisnalar sızdıran soyutlamalara neden olabilir. Ancak bu konuda hata kodları daha da kötü değil mi?

Bu problemin üstesinden gelmenin bir yolu, arayüzün hangi şartlar altında hangi istisnaların atılabileceğini tam olarak belirlemesini sağlamak ve gerekli olduğunda istisnaları yakalamak, dönüştürmek ve tekrar fırlatmak suretiyle uygulamaların kendi istisna modellerini bu şartnameye eşlemesi gerektiğini beyan etmektir. Bir "kaymakam" arayüzü istiyorsanız, bu şekilde gitmek.

Uygulamada, genellikle arayüzün mantıksal bir parçası olan ve bir müşterinin hakkında bir şeyler yakalamak ve yapmak isteyebileceği istisnalar belirlemek yeterlidir. Genellikle düşük seviyeli hatalar oluştuğunda veya bir hata tezahür ettiğinde ve bir müşterinin yalnızca bir hata mesajı göstererek ve / veya uygulamayı kapatarak yapabileceği başka istisnalar olabileceği anlaşılmaktadır. En azından istisna, sorunu teşhis etmeye yardımcı olan bilgileri hala içerebilir.

Aslında, hata kodları ile hemen hemen aynı şey, sadece daha örtük bir biçimde ve bitmek üzere olan bilgilerin kaybolması ve uygulamanın tutarsız bir durumda sonuçlanmasıyla sonuçlanır.


1
Neden bir hata kodunun sızdıran bir soyutlamaya neden olabileceğini anlamıyorum. Normal bir dönüş değeri yerine bir hata kodu döndürülürse ve bu davranış fonksiyonun / yöntemin tarifinde açıklanırsa, IMO'da kaçak olmaz. Yoksa bir şeye mi bakıyorum?
Giorgio

API'nin uygulama-agnostik olması beklenirken hata kodunun uygulamaya özgü olması durumunda, hata kodunun belirtilmesi ve iadesi istenmeyen uygulama detaylarını sızdırıyor. Tipik bir örnek: dosya tabanlı ve DB tabanlı bir uygulamaya sahip olan günlük kaydı API'si, burada eski bir "disk dolu" hatası olabilir ve ikincisi "ana bilgisayar tarafından reddedilen" DB bağlantısı "hatası olabilir.
Michael Borgwardt

Ne demek istediğini anlıyorum. Uygulamaya özel hataları bildirmek istiyorsanız, API uygulama agnostik olamaz (ne hata kodlarıyla ne de istisnalarla). Sanırım tek çözüm, "kaynak mevcut değil" gibi bir uygulama-agnostik hata kodu tanımlamak veya API'nin uygulama-agnostik olmadığına karar vermek olacaktır.
Giorgio

1
@Giorgio: Evet, uygulamaya özel hataların bildirilmesi, uygulama-agnostik bir API ile zor. Yine de, istisnalar dışında bunu yapabilirsiniz, çünkü (hata kodlarından farklı olarak) birden fazla alana sahip olabilirler. Bu nedenle, genel hata bilgilerini (ResourceMissingException) sağlamak için istisna türünü kullanabilir ve bir alana özgü uygulamaya özgü hata kodu / mesajı ekleyebilirsiniz. Her iki dünyanın en iyisi :-).
sleske

Ve BTW, bu sadece java.lang.SQLException ne yapar. Bu sahiptir getSQLState(jenerik) ve getErrorCode(satıcıyı özgü). Şimdi ... doğru alt sınıfları tam olması durumunda
sleske

5

Burada birçok güzel şey var, sadece normal kontrol akışının bir parçası olarak istisnalar kullanan kodlara karşı dikkatli olmamız gerektiğini eklemek isterim. Bazen insanlar, olağan dava olmayan her şeyin bir istisna haline geldiği tuzağa girerler. Bir döngü sonlandırma koşulu olarak kullanılan bir istisna bile gördüm.

İstisnalar, "burada idare edemeyeceğim bir şey oldu, ne yapılacağını bulmak için başkasına gitmem gerek" anlamına geliyor. Geçersiz giriş yazan bir kullanıcı bir istisna değildir (bu, tekrar sorarak vb. Tarafından yerel olarak ele alınması gerekir).

Gördüğüm bir başka istisnai durum örneği de, ilk yanıtı "istisna atmak" olan insanlar. Bu neredeyse her zaman mandal yazmadan yapılır (temel kural: önce mandalı, sonra throw ifadesini yazın). Büyük uygulamalarda, yakalanmamış bir istisna ağ bölgelerinden toplanıp programı havaya uçurduğunda sorunlu hale gelir.

İstisnalar haricinde değilim, ancak birkaç yıl önceki tekillere benziyorlar: çok sık ve uygunsuz olarak kullanıldılar. Amaçlanan kullanım için mükemmeller, ancak bu dava sanılan kadar geniş değil.


4

Sızdıran soyutlama

Bir arabirim neden hangi istisnaların atılabileceğini belirtmelidir? Uygulamanın bir istisna atması gerekmiyorsa veya başka istisnalar atması gerekiyorsa? Bir uygulama düzeyinde, bir uygulamanın hangi istisnaları atmak isteyebileceğini bilmek mümkün değildir.

Hayır! İstisna özellikleri, return ve argüman tipleri ile aynı kovadadır - bunlar arayüzün bir parçasıdır. Bu şartnameye uyamıyorsanız, arayüzü uygulamayın. Asla atmazsan, sorun değil. Bir arabirimde istisnalar belirtme konusunda sızan bir şey yok.

Hata kodları kötü değil. Berbatlar. Her arama için her seferinde onları kontrol edip çoğaltmayı elle hatırlamanız gerekir. Bu, bir başlangıç ​​için DRY'yi ihlal eder ve hata işleme kodunuzu büyük ölçüde hızlandırır. Bu tekrarlama, istisnaların karşılaştığından çok daha büyük bir sorundur. Bir istisnayı asla sessizce görmezden gelemezsiniz, ancak insanlar dönüş kodlarını sessizce görmezden gelebilir - kesinlikle kötü bir şey.


Yine de iyi sözdizimsel şeker veya yardımcı yöntemlerin varsa, hata kodlarının kullanımı daha kolay olabilir ve bazı dillerde derleyici ve tip sistemlerini bir hata koduyla işlemeyi asla unutmayacağınızı garanti altına alabilirsiniz. İstisna arayüzü bölümünde ise, Java’nın kontrolündeki istisnaların kötü ünlülüğünü düşünüyordu. İlk bakışta oldukça makul bir fikir gibi görünseler de, pratikte çok acı verici küçük sorunlara neden oluyorlar.
hugomg

@missingno: Çünkü her zamanki gibi, Java istisnalar doğası gereği kötü olmadığından değil, korkunç bir uygulamasına sahiptir.
DeadMG

1
@missingno: Kontrol edilen istisnalar ne tür sorunlara neden olabilir?
Giorgio

@Giorgio: Bir yöntemin ortaya koyabileceği her türlü istisnayı öngörmek çok zordur, çünkü bunun henüz yazılmamış olan diğer alt sınıfları ve kodları dikkate alması gerekir. Uygulamada insanlar, her şey için bir sistem istisna sınıfını yeniden kullanmak veya iç istisnaları sık sık yakalamak ve tekrar atmak zorunda kalmak gibi bilgileri çöpe atan çirkin geçici çözümlerle karşılaşırlar. Ayrıca, işaretli istisnaların dile isimsiz işlevler eklemeye çalışırken büyük bir engel olduğunu da duydum.
hugomg

@missingno: Java'daki AFAIK anonim işlevleri, yalnızca bir yöntemle anonim iç sınıflar için sözdizimsel bir şekerdir, bu nedenle kontrol edilen istisnaların neden bir sorun olacağını bilmiyorum (ancak konu hakkında pek bir şey bilmediğimi kabul etmiyorum). Evet, bir yöntemin hangi istisnaları ortaya koyacağını tahmin etmek zor, bu nedenle IMO'nun istisnaları kontrol etmenin faydalı olabileceğini, böylece tahminde bulunmak zorunda kalmazsınız. Tabii ki, bunları işlemek için zayıf kod yazabilirsiniz, ancak bu, denetlenmeyen istisnalar dışında da yapılabilir. Ancak, tartışmanın oldukça karmaşık olduğunu ve dürüst olmak gerekirse, her iki tarafın da artılarını ve eksilerini görüyorum.
Giorgio

2

İstisna işleme yönetimi kendi arayüz uygulamalarına sahip olabilir. Atılan istisnanın türüne bağlı olarak, istenen adımları uygulayın.

Tasarım probleminizin çözümü iki arayüz / soyutlama uygulamasına sahip olmaktır. Biri işlevsellik, diğeri istisna işlemesi için. İstisna türüne bağlı olarak, uygun istisna tip sınıfını arayın.

Hata kodlarının uygulanması, istisnai durumların ortodoks bir yoludur. String vs. string builder kullanımı gibidir.


4
Başka bir deyişle: uygulamalar, api'de tanımlanan istisnaların alt sınıflarını atar.
Andrew

2

IM-very-HO istisnaları duruma göre değerlendirilecektir, çünkü kontrol akışını kırarak kodunuzun gerçek ve algılanan karmaşıklığını artıracak, çoğu durumda gereksiz yere. İşlevlerinize istisnalar atma ile ilgili tartışmayı bir kenara koymak - ki bu aslında çağrı akışını kullanarak istisnalar atmak için kontrol sınırlamanızı artırabilir: Aşağıdakileri göz önünde bulundurun:

Bir callee'nin kontrol akışınızı kırmasına izin vermek herhangi bir gerçek fayda sağlamayabilir ve istisna ile baş etmek için anlamlı bir yol olmayabilir. Direkt bir örnek için, eğer Gözlenebilir bir model uyguluyorsa (her yerde olayların olduğu throwsve tanımda açık olmayan C # gibi bir dilde ), Gözlemcinin çarpması durumunda kontrol akışınızı kırmasına izin vermek için gerçek bir sebep yoktur ve Eşyalarıyla uğraşmanın anlamlı bir yolu yok (elbette, iyi bir komşu gözlem yaparken atmamalı, ama hiç kimse mükemmel değildir).

Yukarıdaki gözlem, gevşek bir şekilde bağlanmış herhangi bir arayüze (belirttiğiniz gibi) genişletilebilir; Aslında 3-6 yığın çerçevesini oluşturduktan sonra, yakalanmamış bir istisnadan birinin ya da kodun bir bölümünde bitmesi muhtemel bir norm olduğunu düşünüyorum:

  • istisnanın kendisi kaydedilmiş olsa bile, istisnayı anlamlı bir şekilde ele almak için çok soyut;
  • genel bir işlev gerçekleştiriyor (neden bir ileti pompası ya da gözlemlenebilir gibi başarısız olduğunuzu daha az önemsemiyorsunuz);
  • belirli, ancak farklı bir sorumlulukla ve gerçekten endişelenmemeli;

Yukarıdakileri göz önüne alarak, throwsanlamsallık ile arayüzleri dekore etmek sadece marjinal bir işlevsel kazanımdır, çünkü arayüz sözleşmeleri yapan birçok arayan, sadece başarısız olmanız durumunda, neden olmasın umurunda olur.

O zaman bunun bir zevk ve rahatlık meselesi haline geldiğini söyleyeceğim: öncelikli odak noktanız, bir “istisna” dan sonra hem arayan hem de arayanda durumunuzu zarif bir şekilde kurtarmaktır; Bir C arka plandan) veya istisnaların kötüye dönebileceği bir ortamda çalışıyorsanız (C ++), etrafınıza bir şeyler atmanın, eski, güvenemeyeceğiniz güzel ve temiz OOP için çok önemli olduğuna inanmıyorum. eğer rahatsız olursanız kalıplar. Özellikle de SoC’yu kırmaya yol açarsa.

Teorik bir bakış açısına göre, bir SoC-koşer istisnaları ele alma yolunun doğrudan doğrudan arayanın çoğu zaman neden başarısız olduğunuzu umursamadığı yönündeki gözlemden elde edilebileceğini düşünüyorum. Callee fırlar, çok yakın biri (2-3 kare) yukarıdan yükseltilmiş bir versiyonunu yakalar ve asıl istisna her zaman özel bir hata işleyicisine batırılır (sadece izlese bile) - bu AOP'ın kullanışlı olacağı yer, çünkü bu işleyiciler yatay olması muhtemeldir.


1

Hata kodları üzerindeki istisnaları tercih etme

  • Her ikisi de bir arada olmalı.

  • Belirli bir davranış öngördüğünde hata kodunu döndür.

  • Bazı davranışlar beklemiyorsanız istisna döndürün.

  • İstisna tipi kaldığında hata kodları normal olarak tek bir mesajla ilişkilendirilir, ancak mesaj değişebilir

  • İstisna, hata kodu olmadığında yığın izine sahiptir. Bozuk sistemde hata ayıklamak için hata kodları kullanmıyorum.

Uygulamalara değil arayüzlere kodlama

Bu JAVA'ya özgü olabilir, ancak arayüzlerimi ilan ettiğimde, bu arayüzün bir uygulaması tarafından hangi istisnaların atılabileceğini belirtmiyorum, sadece mantıklı gelmiyor.

Kesinlikle bir istisna yakaladığımızda, uygulama hakkında varsayımlarda bulunuyoruz?

Bu tamamen size kalmış. Çok özel bir istisna türü deneyebilir ve sonra daha genel bir durum yakalayabilirsiniz Exception. Neden istisnanın yığını ilerletip sonra kullanmasına izin vermiyorsun? Alternatif olarak, istisna işlemenin "takılabilir" bir görünüme dönüştüğü görünüş programlamasına bakabilirsiniz.

Uygulamanın bir istisna atması gerekmiyorsa veya başka istisnalar atması gerekiyorsa?

Neden senin için bir sorun olduğunu anlamıyorum. Evet, istisnaları hiçbir zaman başarısız olmayan veya istisnalar ortaya koyan bir uygulamanız olabilir ve istisnasız olarak sürekli başarısız olan ve atanan farklı bir uygulamanız olabilir. Bu durumda, arabirimde herhangi bir istisna belirtmeyin ve sorununuz çözüldü.

Bir istisna yerine uygulamanızın bir sonuç nesnesi döndürmesi bir şeyleri değiştirir mi? Bu nesne, eyleminizdeki sonuçları ve varsa hata / başarısızlıkları içerir. Daha sonra bu nesneyi sorgulayabilirsiniz.


1

Sızdıran soyutlama

Bir arabirim neden hangi istisnaların atılabileceğini belirtmelidir? Uygulamanın bir istisna atması gerekmiyorsa veya başka istisnalar atması gerekiyorsa? Bir uygulama düzeyinde, bir uygulamanın hangi istisnaları atmak isteyebileceğini bilmek mümkün değildir.

Tecrübelerime göre, hatayı alan kod (istisna, hata kodu veya başka herhangi bir şey yoluyla olabilir) normalde hatanın kesin sebebini dikkate almaz - aynı şekilde, herhangi bir arızaya aynı şekilde tepki verirdi; error (bir hata diyalogu veya bir günlük kaydı olabilir); ve bu raporlama, başarısızlık prosedürü olarak adlandırılan koda ortogonal olarak yapılacaktır. Örneğin, bu kod, hatayı belirli hataların nasıl bildirileceğini bilen başka bir kod parçasına iletebilir (örneğin, bir mesaj dizesini biçimlendirme gibi), muhtemelen bazı bağlam bilgilerini ekleyebilir.

Tabii ki, bazı durumlarda olduğu hatalara özgü semantiğini takmak için gerekli ve farklı hata oluştu hangi dayalı tepki. Bu gibi durumlar arayüz şartnamesinde belgelenmelidir. Bununla birlikte, arayüz özel bir anlamı olmayan başka istisnalar hariç tutma hakkını saklı tutar.


1

İstisnaların, hataların raporlanması ve ele alınması için daha yapısal ve özlü bir kod yazılmasına izin verdiğini tespit ediyorum: hata kodlarını kullanmak, her aramadan sonra dönüş değerlerini kontrol etmeyi ve beklenmeyen bir sonuç durumunda ne yapılacağına karar vermeyi gerektirir.

Öte yandan, istisnaların, bir arayüzü çağıran koda saklanması gereken uygulama detaylarını ortaya koyduğunu kabul ediyorum. Hangi kod parçasının hangi istisnaları (Java'daki yöntem imzasında belirtilmediği sürece) hangi istisnaları atabileceğini bilmek mümkün olmadığından, istisnaları kullanarak, kodun farklı kısımları arasında çok karmaşık örtük bağımlılıklar getiriyoruz. bağımlılıkların en aza indirilmesi ilkesine karşı.

Özetleme:

  • Bence istisnalar daha temiz bir koda izin verir ve test ve hata ayıklamaya daha agresif bir yaklaşım sağlar çünkü yakalanmamış istisnalar hata kodlarından çok daha görünür ve göz ardı edilmek zordur (yakında başarısız olur).
  • Öte yandan, test sırasında keşfedilmemiş yakalanmamış istisna hataları üretim ortamında bir çarpışma şeklinde görünebilir. Bazı durumlarda bu davranış kabul edilebilir değildir ve bu durumda hata kodlarının kullanılmasının daha sağlam bir yaklaşım olduğunu düşünüyorum.

1
Katılmıyorum. Evet, yakalanmamış istisnalar bir uygulamayı çökertebilir, ancak denetlenmeyen hata kodları da olabilir - bu bir yıkamadır. İstisnaları doğru kullanırsanız, sadece yakalanmamış olanlar ölümcül olanlardır (OutOfMemory gibi) ve bunlar için hemen çökmek en iyisini yapabilir.
sleske,

Hata kodu arayan m1 ile aranan m2 arasındaki sözleşmenin bir parçasıdır: olası hata kodları sadece m2 arayüzünde tanımlanmıştır. İstisnalar dışında (Java kullanmıyorsanız ve atılan tüm istisnaları yöntem imzalarında belirtmezseniz) m1 arayanı ile m2 tarafından tekrar tekrar çağırılabilecek tüm yöntemler arasında gizli bir sözleşmeniz olur. Elbette, iade edilen bir hata kodunu kontrol etmemek bir hatadır, ancak bunu yapmak her zaman mümkündür. Öte yandan, nasıl uygulandığını bilmiyorsanız, bir yöntem tarafından atılan tüm istisnaları kontrol etmek her zaman mümkün değildir.
Giorgio

İlk olarak: Tüm istisnaları kontrol edebilirsiniz - sadece "Pokemon istisna yönetimi" yapın (hepsini yakalamanız gerekir - yani catch Exceptionhatta Throwableeşdeğer).
sleske

1
Uygulamada, eğer API uygun şekilde tasarlanmışsa, müşterinin anlamlı bir şekilde işleyebileceği tüm istisnaları belirleyecektir - bunların özel olarak yakalanması gerekir. Bunlar hata kodlarının eşdeğerleridir). Başka bir istisna, "iç hata" anlamına gelir ve uygulamanın ilgili alt sistemi kapatması veya en azından kapatması gerekir. İsterseniz bunları yakalayabilirsiniz (yukarıya bakın), ancak genellikle onların kabarmalarına izin vermelisiniz. Bu "köpürme" istisnalar kullanmanın temel avantajıdır. İhtiyaca bağlı olarak onları daha da uzaklaştırabilir veya yakalayamazsınız.
sleske

-1

Her ikisi de sağ taraflı.

Görmezden gelinemez, ele alınması gerekir, tamamen şeffaftır. Doğru solak hata tipini kullanırsanız, java istisnası ile aynı bilgileri iletir.

Dezavantaj? Hata işleme uygun kod iğrenç görünüyor (tüm mekanizmalar için geçerlidir).


Bu, önceki 10 cevapta verilen ve açıklanan önemli noktalar üzerinde önemli bir şey sunmuyor gibi görünüyor. Neden böyle şeylerle iki yaşında soruyu çarpma
sivrisineği

Burada hiç kimse hariç, haklı bir önyargı da yoktu. hugomg, haskell hakkında konuşmaktan daha da yakınlaştı, ancak belki de bir hata hatası işleyicisidir, çünkü hatanın neden oluştuğu ya da geri kazanılması gereken herhangi bir doğrudan yöntem ve geri aramalar, kontrol akışı tasarımındaki en büyük günahlardan biridir. Ve bu soru google'da ortaya çıktı.
Keynan
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.