Bazı diller için (yani C ++) Kaynak sızıntısı bir sebep olmamalıdır
C ++, RAII'ye dayanmaktadır.
Başarısız olabilecek, geri dönebilecek veya fırlatabilecek (yani, çoğu normal kod) kodunuz varsa, işaretçinizin akıllı bir işaretçinin içine sarılması gerekir ( nesnenizin yığın üzerinde oluşturulmaması için çok iyi bir nedeniniz olduğunu varsayarak ).
Dönüş kodları daha ayrıntılıdır
Bunlar ayrıntılıdır ve aşağıdaki gibi bir şeye dönüşme eğilimindedirler:
if(doSomething())
{
if(doSomethingElse())
{
if(doSomethingElseAgain())
{
// etc.
}
else
{
// react to failure of doSomethingElseAgain
}
}
else
{
// react to failure of doSomethingElse
}
}
else
{
// react to failure of doSomething
}
Sonunda, kodunuz tanımlanmış talimatların bir koleksiyonudur (bu tür bir kodu üretim kodunda gördüm).
Bu kod şu şekilde çevrilebilir:
try
{
doSomething() ;
doSomethingElse() ;
doSomethingElseAgain() ;
}
catch(const SomethingException & e)
{
// react to failure of doSomething
}
catch(const SomethingElseException & e)
{
// react to failure of doSomethingElse
}
catch(const SomethingElseAgainException & e)
{
// react to failure of doSomethingElseAgain
}
Hangi temiz ayrı bir kod ve hata işleme, olabilir bir olmak iyi bir şey.
Dönüş kodları daha kırılgandır
Bir derleyiciden gelen belirsiz bir uyarı değilse ("phjr" nin açıklamasına bakın), kolayca göz ardı edilebilirler.
Yukarıdaki örneklerle, birinin olası hatasını ele almayı unuttuğunu varsayın (bu olur ...). Hata "döndürüldüğünde" göz ardı edilir ve muhtemelen daha sonra patlayacaktır (yani bir NULL işaretçisi). Aynı sorun istisna ile olmaz.
Hata göz ardı edilmeyecek. Bazen, patlamamasını istersiniz, gerçi ... Bu yüzden dikkatli seçmelisiniz.
Dönüş Kodları bazen çevrilmelidir
Diyelim ki aşağıdaki işlevlere sahibiz:
- doSomething, NOT_FOUND_ERROR adlı bir int döndürebilir
- doSomethingElse, bool "false" döndürebilir (başarısız olduğu için)
- doSomethingElseAgain, bir Error nesnesi döndürebilir (hem __LINE__, __FILE__ hem de yığın değişkenlerinin yarısı ile.
- do TryToDoSomethingWithAllThisMess ki bu iyi ... Yukarıdaki işlevleri kullanın ve bir tür hata kodu döndürür ...
Çağrılan işlevlerinden biri başarısız olursa, do TryToDoSomethingWithAllThisMess'in dönüşünün türü nedir?
İade Kodları evrensel bir çözüm değildir
Operatörler bir hata kodu döndüremez. C ++ kurucuları da yapamaz.
Dönüş Kodları, ifadeleri zincirleyemeyeceğiniz anlamına gelir
Yukarıdaki noktanın doğal sonucu. Ya yazmak istersem:
CMyType o = add(a, multiply(b, c)) ;
Yapamam çünkü dönüş değeri zaten kullanılıyor (ve bazen değiştirilemez). Böylece dönüş değeri referans olarak gönderilen ilk parametre olur ... Veya değil.
İstisna yazılır
Her istisna türü için farklı sınıflar gönderebilirsiniz. Kaynak istisnaları (yani hafıza yetersizliği) hafif olmalıdır, ancak diğer her şey gerektiği kadar ağır olabilir (Java İstisnasının bana tüm yığını vermesini seviyorum).
Her yakalama daha sonra özelleştirilebilir.
Yeniden fırlatmadan asla yakalama (...) kullanmayın
Genellikle bir hatayı gizlememelisiniz. Yeniden atmazsanız, en azından, hatayı bir dosyaya kaydedin, bir mesaj kutusu açın, her neyse ...
İstisnalar ... NUKE
İstisnai sorun, aşırı kullanılmasının deneme / yakalama ile dolu kod üretmesidir. Ancak sorun başka bir yerde: STL konteynerini kullanarak kodunu kim yakalamaya çalışıyor? Yine de bu kaplar bir istisna gönderebilir.
Elbette, C ++ 'da, bir istisnanın yıkıcıdan çıkmasına asla izin vermeyin.
İstisnalar ... senkronize
İş parçacığınızı dizlerinin üzerine indirmeden veya Windows ileti döngünüzün içine yaymadan önce onları yakaladığınızdan emin olun.
Çözüm onları karıştırmak olabilir mi?
Sanırım Yani çözüm şey gerekirken atılmasıdır değil olur. Ve bir şey olduğunda, kullanıcının buna tepki vermesini sağlamak için bir dönüş kodu veya parametre kullanın.
Öyleyse, tek soru "olmaması gereken şey nedir?"
Görevinizin sözleşmesine bağlıdır. İşlev bir işaretçi kabul ederse, ancak işaretçinin NULL olmaması gerektiğini belirtirse, kullanıcı bir NULL işaretçi gönderdiğinde bir istisna atılması uygundur (soru, C ++ 'da, işlev yazarı bunun yerine referanslar kullanmadığında işaretçiler, ama ...)
Başka bir çözüm, hatayı göstermek olacaktır.
Bazen sorunun, hata istememektir. İstisnalar veya hata dönüş kodları kullanmak harika, ama ... Bunu bilmek istiyorsunuz.
İşimde bir tür "İddia" kullanıyoruz. Hata ayıklama / yayınlama derleme seçenekleri ne olursa olsun, bir yapılandırma dosyasının değerlerine bağlı olarak:
- hatayı günlüğe kaydet
- "Hey, bir sorunun var" yazan bir mesaj kutusu açın
- "Hey, bir sorunun var, hata ayıklamak istiyor musun" yazan bir mesaj kutusu açın
Hem geliştirme hem de testte, bu, kullanıcının problemi tam olarak tespit edildiğinde ve sonra değil (bazı kodlar dönüş değerini önemsediğinde veya bir yakalama içinde) tam olarak saptamasına olanak tanır.
Eski koda eklemek kolaydır. Örneğin:
void doSomething(CMyObject * p, int iRandomData)
{
// etc.
}
şuna benzer bir tür kod açar:
void doSomething(CMyObject * p, int iRandomData)
{
if(iRandomData < 32)
{
MY_RAISE_ERROR("Hey, iRandomData " << iRandomData << " is lesser than 32. Aborting processing") ;
return ;
}
if(p == NULL)
{
MY_RAISE_ERROR("Hey, p is NULL !\niRandomData is equal to " << iRandomData << ". Will throw.") ;
throw std::some_exception() ;
}
if(! p.is Ok())
{
MY_RAISE_ERROR("Hey, p is NOT Ok!\np is equal to " << p->toString() << ". Will try to continue anyway") ;
}
// etc.
}
(Yalnızca hata ayıklamada etkin olan benzer makrolarım var).
Üretimde konfigürasyon dosyasının mevcut olmadığını, dolayısıyla istemcinin bu makronun sonucunu asla görmediğini unutmayın ... Ancak gerektiğinde etkinleştirmek kolaydır.
Sonuç
Dönüş kodlarını kullanarak kod yazdığınızda, kendinizi başarısızlığa hazırlıyorsunuz ve test kalenizin yeterince güvenli olmasını umuyorsunuz.
İstisna kullanarak kod yazdığınızda, kodunuzun başarısız olabileceğini bilirsiniz ve genellikle kodunuzda seçilen stratejik konuma karşı ateş yakalama koyarsınız. Ancak genellikle, kodunuz daha çok "ne yapması gerektiği" ve sonra "ne olacağından korktuğum" ile ilgilidir.
Ancak kod yazdığınızda, emrinizde olan en iyi aracı kullanmanız gerekir ve bazen bu "Bir hatayı asla gizleme ve mümkün olan en kısa sürede gösterme" dir. Yukarıda bahsettiğim makro bu felsefeyi takip ediyor.