Farklı yazılım mühendisliği disiplinlerinde, kütüphanelerin hatalarla veya diğer istisnai koşullarla nasıl başa çıkması gerektiği konusunda birçok felsefe vardır. Gördüğüm birkaç örnek:
- Sonuç bir işaretçi bağımsız değişkeni tarafından döndürülen bir hata kodu döndürün. PETSc bunu yapar.
- Hataları sentinel değerine göre döndür. Örneğin, malloc bellek ayıramadıysa NULL döndürür,
sqrt
negatif bir sayı geçerseniz vb. NaN döndürür. Bu yaklaşım birçok libc işlevinde kullanılır. - İstisnalar atın. Satışta kullanılır. II, Trilinos, vb.
- Bir varyant türü döndürün; örneğin
Result
, düzgün çalıştığında veError
nasıl başarısız olabileceğini tanımlamak için bir tür kullanan bir nesne döndüren bir C ++ işlevistd::variant<Error, Result>
. - Onay ve kilitlenme kullanın. P4est ve igraph'ın bazı kısımlarında kullanılır.
Her yaklaşımla ilgili sorunlar:
- Her hatayı kontrol etmek fazladan kod getirir. Bir sonucun kaydedileceği değerlerin her zaman önce bildirilmesi gerekir ve yalnızca bir kez kullanılabilecek çok sayıda geçici değişken getirilir. Bu yaklaşım hangi hatanın meydana geldiğini açıklar, ancak neden veya derin bir çağrı yığını için nerede olduğunu belirlemek zor olabilir.
- Hata durumu göz ardı edilir. Bunun da ötesinde, tüm çıktı türleri aralığı makul bir sonuçsa, birçok fonksiyon anlamlı bir sentinel değerine bile sahip olamaz. # 1 ile aynı sorunların çoğu.
- Sadece C ++, Python, vb. İle mümkündür, C veya Fortran ile mümkün değildir. C setjmp / longjmp büyücülük veya libunwind kullanılarak taklit edilebilir .
- Sadece C ++, Rust, OCaml, vb. Mümkün, C veya Fortran değil. Makro büyücülük kullanarak C taklit edilebilir.
- Muhtemelen en bilgilendirici. Ancak, daha sonra bir Python sarıcı yazdığınız bir C kütüphanesi için bu yaklaşımı benimserseniz, bir diziye sınırların ötesinde bir dizinin geçirilmesi gibi aptalca bir hata Python yorumlayıcısının çökmesine neden olur.
İnternette hata yönetimi ile ilgili tavsiyelerin çoğu, işletim sistemleri, yerleşik geliştirme veya web uygulamaları açısından yazılmıştır. Çökmeler kabul edilemez ve güvenlik konusunda endişelenmeniz gerekir. Bilimsel uygulamalarda bu sorunlar hemen hemen aynı ölçüde yoktur.
Başka bir husus, ne tür hataların düzeltilebilir veya düzeltilemez olduğudur. Bir malloc hatası kurtarılamaz ve her durumda, OS bellek yetersiz katili sizden önce ona ulaşacaktır. Dizi boyutu için sınırların dışındaki bir dizin de kurtarılamaz. Kullanıcı olarak benim için bir kütüphanenin yapabileceği en güzel şey bilgilendirici bir hata mesajı ile çökmektir. Öte yandan, mesela, yinelemeli bir yinelemeli doğrusal çözücünün başarısızlığı, doğrudan çarpanlara ayırma çözücüsü kullanılarak giderilebilir.
Bilimsel kütüphaneler hataları nasıl raporlamalı ve ele alınmasını beklemelidir? Tabii ki bunun kütüphanenin hangi dilde uygulandığına bağlı olduğunu anlıyorum. Ama yeterince faydalı herhangi bir kütüphane için insanlar onu uyguladığı dilden başka bir dilde aramak isteyeceklerdir.
Bir yana, genel bir iddiası işleyici işlev işaretçisini genel API'nin bir parçası olarak tanımlarsa, yaklaşım # 5'in bir C kütüphanesi için önemli ölçüde geliştirilebileceğini düşünüyorum. Onaylama işleyicisi varsayılan olarak dosya / satır numarasını bildirme ve kilitlenmeyi önler. Bu kitaplık için C ++ bağlamaları, bunun yerine bir C ++ istisnası atan yeni bir onaylama işleyicisi tanımlar. Benzer şekilde, Python bağlamaları bir Python istisnası atmak için CPython API'sini kullanan bir onaylama işleyicisi tanımlar. Ama bu yaklaşımı benimseyen hiçbir örnek bilmiyorum.