Google'ın Go dilinin bir tasarım seçeneği olarak istisnası yoktur ve Linux'un şöhreti Linus istisnalar saçmalığı olarak adlandırmıştır. Neden?
Google'ın Go dilinin bir tasarım seçeneği olarak istisnası yoktur ve Linux'un şöhreti Linus istisnalar saçmalığı olarak adlandırmıştır. Neden?
Yanıtlar:
İstisnalar, atılan bir istisnanın değişmezleri kıracağı ve nesneleri tutarsız bir durumda bırakacağı durumlarda kod yazmayı gerçekten kolaylaştırır. Esasen, yaptığınız her ifadenin çoğunun potansiyel olarak atabileceğini ve bunu doğru şekilde ele alabileceğini hatırlamaya zorlar. Bunu yapmak aldatıcı ve mantıksız olabilir.
Bunun gibi bir şeyi basit bir örnek olarak düşünün:
class Frobber
{
int m_NumberOfFrobs;
FrobManager m_FrobManager;
public:
void Frob()
{
m_NumberOfFrobs++;
m_FrobManager.HandleFrob(new FrobObject());
}
};
Varsayarsak FrobManager
olacak doğru, bu bakışlar OK? Ya da belki ... sonra hayal edin ya değil ya bir istisna atar. Bu örnekte, artış değeri geri alınmaz. Bu nedenle, bu örneğini kullanan herkesin muhtemelen bozuk bir nesnesi olacaktır.delete
FrobObject
FrobManager::HandleFrob()
operator new
m_NumberOfFrobs
Frobber
Bu örnek aptalca görünebilir (tamam, bir tane oluşturmak için kendimi biraz esnetmek zorunda kaldım :-)), ancak çıkarım, eğer bir programcı sürekli olarak istisnaları düşünmüyorsa ve durumun her permütasyonunun yuvarlanmasını sağlamaktır. ne zaman atış olursa, bu şekilde başınız belaya giriyor.
Örnek olarak, muteksleri düşündüğünüz gibi düşünebilirsiniz. Kritik bir bölümün içinde, veri yapılarının bozuk olmadığından ve diğer iş parçacıklarının ara değerlerinizi göremediğinden emin olmak için birkaç ifadeye güvenirsiniz. Bu ifadelerden herhangi biri rastgele bir şekilde çalışmazsa, acı dolu bir dünyaya girersiniz. Şimdi kilitleri ve eşzamanlılığı ortadan kaldırın ve her yöntemi bunun gibi düşünün. İsterseniz, her yöntemi nesne durumundaki permütasyonların bir işlemi olarak düşünün. Yöntem çağrınızın başlangıcında, nesne temiz durumda olmalı ve sonunda da temiz bir durum olmalıdır. Arada, değişken foo
ile tutarsız olabilirbar
, ancak kodunuz sonunda bunu düzeltir. İstisnaların anlamı, ifadelerinizden herhangi birinin herhangi bir zamanda sizi rahatsız edebilmesidir. Her bir yöntemde, bunu düzeltmek ve bu olduğunda geri almak veya işlemlerinizi, nesnenin durumunu etkilemeyecek şekilde sıralamak için sorumluluk size aittir. Yanlış anlarsanız (ve bu tür bir hatayı yapmak kolaysa), arayan kişi ara değerlerinizi görmeye başlar.
C ++ programcılarının bu soruna nihai çözüm olarak bahsetmeyi sevdikleri RAII gibi yöntemler, buna karşı korunmak için uzun bir yol kat ediyor. Ama sihirli değnek değiller. Kaynakları bir atışta serbest bırakmanızı sağlar, ancak sizi nesne durumundaki bozulma ve ara değerleri gören arayanlar hakkında düşünme zorunluluğundan kurtarmaz. Bu nedenle, birçok insan için, istisnasız bir kodlama stiline göre söylemek daha kolay . Yazdığınız kod türünü kısıtlarsanız, bu hataları ortaya çıkarmak daha zordur. Eğer yapmazsanız, hata yapmak oldukça kolaydır.
C ++ 'ta istisnai güvenli kodlama hakkında tüm kitaplar yazılmıştır. Pek çok uzman yanlış anladı. Gerçekten bu kadar karmaşıksa ve çok fazla nüansı varsa, bu özelliği görmezden gelmeniz gerektiğine dair iyi bir işaret olabilir. :-)
Go'nun istisnalara sahip olmamasının nedeni Go dili tasarımı SSS bölümünde açıklanmıştır:
İstisnalar benzer bir hikaye. İstisnalar için bir dizi tasarım önerilmiştir, ancak her biri dile ve çalışma süresine önemli ölçüde karmaşıklık katmaktadır. Doğası gereği, istisnalar işlevleri ve hatta belki de gorutinleri kapsar; geniş kapsamlı çıkarımları vardır. Ayrıca kütüphaneler üzerinde yaratacağı etki konusunda da endişeler var. Tanımı gereği istisnaidirler, ancak onları destekleyen diğer dillerle ilgili deneyimler, kitaplık ve arayüz özellikleri üzerinde derin etkileri olduğunu gösterir. Genel hataları her programcının telafi etmesini gerektiren özel kontrol akışına dönüşmeye teşvik etmeden gerçekten istisnai olmalarına izin veren bir tasarım bulmak güzel olurdu.
Jenerik ilaçlar gibi istisnalar da açık bir sorun olmaya devam ediyor.
Başka bir deyişle, Go'daki istisnaları tatmin edici buldukları bir şekilde nasıl destekleyeceklerini henüz çözemediler. Onlar İstisnalar kötü olduğunu söylemiyoruz se başına ;
GÜNCELLEME - Mayıs 2012
Go tasarımcıları şimdi çitin üzerinden aşağı indi. SSS'leri şimdi şunu söylüyor:
Try-catch-nihayet deyiminde olduğu gibi bir kontrol yapısına istisnaların birleştirilmesinin kıvrımlı kodla sonuçlandığına inanıyoruz. Ayrıca, programcıları, bir dosyayı açamama gibi çok fazla sıradan hatayı istisnai olarak etiketlemeye teşvik etme eğilimindedir.
Go farklı bir yaklaşım sergiliyor. Düz hata işleme için Go'nun çoklu değer dönüşleri, dönüş değerini aşırı yüklemeden bir hatayı bildirmeyi kolaylaştırır. Go'nun diğer özellikleriyle birlikte kanonik bir hata türü, hata işlemeyi keyifli hale getirir, ancak diğer dillerdekinden oldukça farklıdır.
Go ayrıca, gerçekten istisnai koşullardan sinyal almak ve kurtarmak için birkaç yerleşik işleve sahiptir. Kurtarma mekanizması, yalnızca bir hatadan sonra yıkılan bir işlevin durumunun bir parçası olarak yürütülür; bu, felaketi ele almak için yeterlidir, ancak ekstra kontrol yapıları gerektirmez ve iyi kullanıldığında temiz hata işleme koduyla sonuçlanabilir.
Ayrıntılar için Defer, Panic ve Recover makalesine bakın.
Dolayısıyla kısa cevap, bunu çok değerli getiri kullanarak farklı şekilde yapabilecekleridir. (Ve yine de bir tür istisna işleme şekli var.)
... ve Linux'un ünlü Linus'u istisnalar saçmalığı olarak adlandırdı.
Linus'un neden istisnaların saçmalık olduğunu düşündüğünü bilmek istiyorsanız, en iyisi konuyla ilgili yazılarına bakmaktır. Şimdiye kadar izlediğim tek şey , C ++ üzerindeki birkaç e-postaya gömülü olan bu alıntı :
"Tüm C ++ istisna işleme olayı temelden bozuldu. Özellikle çekirdekler için bozuk."
Özellikle C ++ istisnalarından bahsettiğini ve genel olarak istisnalardan bahsetmediğini fark edeceksiniz. (Ve C ++ istisnalarının , doğru şekilde kullanılmalarını zorlaştıran bazı sorunları var.)
Benim sonucum, Linus'un istisnaları (genel olarak) "saçmalık" olarak adlandırmadığıdır!
İstisnalar kendi başına kötü değildir, ancak çok olacaklarını biliyorsanız, performans açısından pahalı olabilirler.
Temel kural, istisnaların istisnai koşulları işaretlemesi ve bunları program akışının kontrolü için kullanmamanız gerektiğidir.
"Yalnızca istisnai durumlarda istisnalar atın" fikrine katılmıyorum. Genel olarak doğru olsa da yanıltıcıdır. İstisnalar hata içindir durumları içindir (yürütme hataları).
Bağımsız olarak kullanmak dilin, bir kopyasını almak Çerçeve Tasarım Rehberi Yeniden kullanılabilir NET Kütüphaneleri (2nd Edition) için Sözleşmeleri, Deyimler ve Kalıpları:. İstisna atma ile ilgili bölüm emsalsizdir. İlk baskıdan bazı alıntılar (ikincisi işimde):
İstisnaların yararları (API tutarlılığı, hata işleme kodunun konumu seçimi, geliştirilmiş sağlamlık, vb.) Hakkında not sayfaları vardır. Performansla ilgili birkaç model içeren bir bölüm vardır (Tester-Doer, Try-Parse).
İstisnalar ve istisna yönetimi fena değil . Diğer herhangi bir özellik gibi, kötüye kullanılabilirler.
Golang açısından bakıldığında, istisna işlemeye sahip olmamanın derleme sürecini basit ve güvenli tuttuğunu tahmin ediyorum.
Linus'un bakış açısından, çekirdek kodunun TÜM köşe durumlarla ilgili olduğunu anlıyorum. Bu nedenle istisnaları reddetmek mantıklıdır.
Mevcut görevi yere bırakmanın sorun olmadığı ve ortak durum kodunun hata işlemeden daha önemli olduğu durumlarda kodda istisnalar anlamlıdır. Ancak derleyiciden kod üretmeyi gerektirirler.
Örneğin, web ve masaüstü uygulama kodu gibi çoğu üst düzey, kullanıcıya dönük kodda iyidirler.
İstisnalar kendi içlerinde "kötü" değildir, bazen kötü olma eğiliminde olan istisnaların ele alınma şeklidir. Bu sorunlardan bazılarının hafifletilmesine yardımcı olmak için istisnaları ele alırken uygulanabilecek birkaç kılavuz vardır. Bunlardan bazıları şunları içerir (ancak bunlarla sınırlı değildir):
Option<T>
yerine bir döndürerek çözer null
. Örneğin, Guava'dan (ve diğerlerinden) bir ipucu alarak Java 8'de yeni tanıtıldı.
Tipik argümanlar, belirli bir kod parçasından (dile bağlı olarak) hangi istisnaların çıkacağını söylemenin bir yolu olmadığı ve çok fazla goto
s gibi olduklarından, yürütmeyi zihinsel olarak izlemeyi zorlaştırdığıdır.
http://www.joelonsoftware.com/items/2003/10/13.html
Bu konuda kesinlikle bir fikir birliği yok. Linus gibi sert çekirdekli bir C programcısının bakış açısından, istisnaların kesinlikle kötü bir fikir olduğunu söyleyebilirim. Yine de tipik bir Java programcısı çok farklı bir durumdadır.
setjmp
/ longjmp
şeyler de var .
İstisnalar fena değil. C ++ 'ın en zarif özelliği olan C ++' ın RAII modeli ile uyumludurlar. Zaten istisnai güvenli olmayan bir sürü kodunuz varsa, bu bağlamda kötüler. Linux işletim sistemi gibi gerçekten düşük seviyeli bir yazılım yazıyorsanız, o zaman kötüler. Kodunuzu bir dizi hata dönüş kontrolüyle doldurmaktan hoşlanıyorsanız, o zaman yardımcı olmazlar. Bir istisna atıldığında (C ++ yıkıcılarının sağladığı) kaynak kontrolü için bir planınız yoksa, o zaman kötüdür.
Bu nedenle istisnalar için harika bir kullanım durumu ...
Bir projede olduğunuzu ve her denetleyicinin (yaklaşık 20 farklı ana denetleyici) bir eylem yöntemiyle tek bir üst sınıf denetleyiciyi genişlettiğini varsayalım. Sonra her denetleyici, bir durumda B, C, D nesnelerini ve başka bir durumda F, G, D nesnelerini çağırarak birbirinden farklı bir dizi şey yapar. Burada, tonlarca dönüş kodunun olduğu ve HER denetleyicinin bunu farklı şekilde ele aldığı birçok durumda istisnalar kurtarmaya geliyor. Tüm bu kodu kırdım, "D" den uygun istisnayı attım, onu süper sınıf denetleyici eylem yönteminde yakaladım ve şimdi tüm denetleyicilerimiz tutarlı. Daha önce D, son kullanıcıya anlatmak istediğimiz ancak yapamadığımız MULTIPLE farklı hata durumu için boş döndürüyordu ve ben yapmadım '
evet, her seviye ve herhangi bir kaynak temizliği / sızıntısı hakkında endişelenmemiz gerekiyor, ancak genel olarak denetleyicilerimizin hiçbirinin sonradan temizleyecek kaynakları yoktu.
Tanrıya şükür istisnalarımız vardı ya da büyük bir yeniden düzenleme yapmak zorunda kalırdım ve basit bir programlama sorunu olması gereken bir şey için çok fazla zaman harcardım.
Teorik olarak gerçekten kötüler. Kusursuz matematik dünyasında istisnai durumlar elde edemezsiniz. İşlevsel dillere bakın, yan etkileri yoktur, bu nedenle istisnai durumlar için neredeyse kaynakları yoktur.
Ancak gerçeklik başka bir hikaye. Her zaman "beklenmedik" durumlara sahibiz. Bu nedenle istisnalara ihtiyacımız var.
ExceptionSituationObserver için sözdizimi şekeri olarak istisnaları düşünebileceğimizi düşünüyorum. Sadece istisnalarla ilgili bildirimler alırsınız. Daha fazlası yok.
Go ile "beklenmedik" durumlarla başa çıkacak bir şey getireceklerini düşünüyorum. İstisnalar olarak daha az yıkıcı ve uygulama mantığı olarak daha fazla ses çıkarmaya çalışacaklarını tahmin edebilirim. Ama bu sadece benim tahminim.
C ++ 'ın istisna işleme paradigması, Java'nınki için kısmi bir temel oluşturur ve buna karşılık .net, bazı iyi kavramlar sunar, ancak aynı zamanda bazı ciddi sınırlamalara sahiptir. İstisna işlemenin temel tasarım amaçlarından biri, yöntemlerin kendi son koşullarını karşılamalarını veya bir istisna atmalarını sağlamalarına izin vermek ve ayrıca bir yöntem çıkmadan önce yapılması gereken herhangi bir temizliğin gerçekleşmesini sağlamaktır. Ne yazık ki, C ++, Java ve .net'in istisna işleme paradigmalarının tümü, beklenmedik faktörlerin beklenen temizliğin gerçekleştirilmesini engellediği durumda durumu ele almak için iyi bir yol sağlamada başarısız olur. Bu da, beklenmedik bir şey olursa, birinin her şeyin çığlık atarak durma riskini alması gerektiği anlamına gelir (bir istisnayı ele almaya yönelik C ++ yaklaşımı, yığın çözme sırasında oluşur),
İstisna işleme genel olarak iyi olsa bile, diğer sorunlardan sonra temizlik yaparken ortaya çıkan sorunları ele almak için iyi bir yol sağlamayan bir istisna işleme paradigmasını kabul edilemez olarak görmek mantıksız değildir. Bu, çoklu hata senaryolarında bile mantıklı davranışlar sağlayabilecek bir istisna işleme paradigmasıyla bir çerçeve tasarlanamayacağı anlamına gelmez, ancak en iyi dillerin veya çerçevelerin hiçbiri henüz bunu yapamaz.
Diğer tüm cevapları okumadım, bu yüzden bu maddeden daha önce bahsedilmişti, ancak bir eleştiri, programların uzun zincirler halinde kırılmasına neden olarak kodda hata ayıklarken hataları bulmayı zorlaştırmasıdır. Örneğin, Foo (), ToString () 'i çağıran Wah ()' ı çağıran Bar () 'ı çağırırsa, yanlışlıkla yanlış verileri ToString ()' e itmek, neredeyse tamamen alakasız bir işlev olan Foo () 'da bir hata gibi görünmeye başlar.
Tamam, sıkıcı cevap burada. Sanırım bu gerçekten dile bağlı. Bir istisnanın tahsis edilen kaynakları geride bırakabileceği durumlarda, bunlardan kaçınılmalıdır. Komut dosyası yazma dillerinde, uygulama akışının bazı kısımlarını atlarlar veya aşarlar. Bu kendi başına sevimsizdir, ancak istisnalar dışında neredeyse ölümcül hatalardan kaçmak kabul edilebilir bir fikirdir.
Hata sinyallemesi için genellikle hata sinyallerini tercih ederim. Her şey API'ye, kullanım durumuna ve önem derecesine veya günlük tutmanın yeterli olup olmadığına bağlıdır. Ayrıca davranışı yeniden tanımlamaya çalışıyorum ve throw Phonebooks()
bunun yerine. "İstisnaların" genellikle çıkmazlar olduğu fikri, ancak bir "Telefon Rehberi" hata kurtarma veya alternatif yürütme yolları hakkında yararlı bilgiler içerir. (Henüz iyi bir kullanım alanı bulamadık ama denemeye devam edin.)
Benim için sorun çok basit. Birçok programcı, istisna işleyiciyi uygunsuz bir şekilde kullanır. Daha fazla dil kaynağı daha iyidir. İstisnaları idare edebilmek iyidir. Kötü kullanımın bir örneği, tamsayı olması gereken, doğrulanmayan bir değerdir veya bölünebilen ve sıfıra bölme için kontrol edilmeyen başka bir girdi ... istisna işleme, daha fazla işten ve zor düşünmeden kaçınmanın kolay bir yolu olabilir, programcı kirli bir kısayol yapmak ve bir istisna işleme uygulamak isteyebilir ... Algoritma tarafından işlenen sorunlardan bazıları kendi doğası gereği belirsizse, "profesyonel bir kod ASLA başarısız olmaz" ifadesi yanıltıcı olabilir. Belki de doğası gereği bilinmeyen durumlarda istisna işleyicisi devreye girer. İyi programlama uygulamaları tartışma konusudur.