Özel yöntemlerden argüman istisnası veya argümannullexception atıyor musunuz?


20

Ben sadece bir süre önce yazdım bazı kod gözden geçiriyordu ve yöntemler parametreleri ile ilgili sorunlar varsa argumentnullexceptions ve / veya argumentexceptions atmak özel yöntemler birkaç olduğunu görebilirsiniz.

Gerekçem, eğer biri gelecekte yöntemi "kötüye kullanmaya" çalışırsa uygulamayı gelecekte kanıtlamaya yardımcı olacağını düşünüyorum. Ancak, özel bir yöntem olduğu ve bu yöntemi çağıracak kişilerin ilişkili yorumları ve kodu görebildiği için, bunu atmak gereksizdir. Karmaşıklık katmasına rağmen, onlara sahip olmak kesinlikle zarar vermez.

Benim düşüncem, bu istisnaların genel olarak kamuya açıklanacak bir API gibi bir şeyde daha yararlı olduğu yönündedir.

Yanıtlar:


22

Normalde, özel yöntemler için, yazdığınız için istisna atmazsınız, geliştiricinin yöntemi nasıl ve nereden çağırdığını bilmesi gerekir. Bu nedenle, özel yönteme parametre olarak iletilen değişkenler yöntemin dışında, yani çağrılmadan önce kontrol edilmelidir. "InvalidArgumentException" ve benzeri istisnaları atmak, genel yöntemler için iyi bir uygulama olarak kabul edilir ("API" yazıyor olsanız da olmasanız da).

"InvalidArgumentException" atmak istediğiniz durumlarda, Assert1.1.2 sürümünden bu yana Java için Spring API'de bir sınıf bulunduğunu belirtmek gerekir . En azından benim için kontroller yapmak için daha az kod yazarken çok yardımcı oldu.

Ancak, özel yöntemlerde parametreleri kontrol etmek için "ekler" kullanabilirsiniz. Bu onların gerçek amaçlarından biri. Bunları kullanmanın daha fazla nedeni, eklerin ne zaman ve istisnaların ne zaman kullanılacağını da açıklayan aşağıdaki bağlantıya göz atın. Ekler üretim koduna dahil edilmemelidir ve derleyici bunları varsayılan olarak kaldırır. Aradığın şey bunlar: geliştiricilere yardım etmek, kullanıcılar için görünmez. Java'da derleyiciye iddiaları etkinleştirmesini bildirmek için özel bir bayrak ("-ea") kullanmanız gerekir. Onları "hata ayıklama" arkadaşları olarak düşünebilirsiniz.

Eklerin nasıl kullanılacağı aşağıda açıklanmıştır:


1
Apache Commons ayrıca Spring's Assert sınıfına benzer şekilde çalışan bir Validate sınıfına sahiptir
Rosa Richter

@cantido evet ve ben de Google'ın Guava'sında aynı şekilde çalışan Preconditions sınıfını da ekleyeceğim. Bilgi için teşekkürler :-)
Jalayn

2

Diğer her şey gibi ...

Genel yöntemler özel yöntemi çağıran basit sarmalayıcılarsa (özel bir aşırı yüklenmiş yöntemin satırları boyunca), her genel olanı denetlemek yerine özel yöntemde bir istisna atmak mantıklı olabilir.

Genellikle yukarıdaki tanımı karşılamıyorsa, genellikle argümanları kontrol etmem / özel bir yönteme bir istisna atmam. Diğer durumlar olsa da, genellikle, argümanlar geçersizse kısmen başarısız olabilecek bazı pahalı işlemleri gerçekleştirmeden önce özel bir yöntemle yapıyorum.


2

Sorunun dil etiketi olmasa da, muhtemelen “kahve dilleri” nden dolaylı olarak bahsettiğinin farkındayım. Ama sadece bütünlük uğruna, C ++ dünyasında biraz farklı görünen fikir birliğinden bahsetmek istiyorum.

C ++ programcılarının ilgilendiği üç şey vardır:

  • Optimize edilmiş yapılarda sıfır ek yükü olacak mı? (Yani, “derlenebilir”?)
  • Hatanın tespit edildiği noktada bir hata ayıklayıcıya sıkışmak için kullanabilir miyim?
  • Bildirilen işlevlerden gelen sorunları bildirmek için kullanabilir miyim noexcept?

Geçmişte, ilk soruna şöyle kod yazarak yaklaştım

int
factorial(const int n)
{
  if (CHECK_ARGS)
    {
      if (n < 0)
        throw std::invalid_argument {"n < 0"};
    }
  int fac = 1;
  for (int i = 2; i <= n; ++i)
    fac *= i;
  return fac;
}

burada CHECK_ARGSbir #definederleyici tamamen tüm bağımsız değişken kontrol kodu ortadan kaldırabilir, böylece bir derleme sabitine d optimize oluşturur. (Çekleri derlemenin genel olarak iyi bir şey olduğunu söylemiyorum ama bir kullanıcının bunları derleme seçeneğine sahip .)

Hala bu çözüm hakkında argüman kontrol kodu açıkça birlikte gruplandırılmış görünür gibi if. Ancak, ikinci ve üçüncü konu bununla çözülmez. Bu nedenle, şimdi tekrar daha çokassert argüman kontrolü için makro .

Standartları kodlama Boost buna katılıyor:

Programcı Hataları Nedir?

Bir geliştirici olarak, kullandığım bir kütüphanenin önkoşulunu ihlal etsem, yığın gevşemesini istemiyorum. Ne istiyorum bir çekirdek dökümü ya da eşdeğer - programın durumunu sorunun tam olarak tespit edildiği noktada incelemek için bir yoldur. Bu genellikle assert()bunun gibi bir şey anlamına gelir .

John Lakos tarafından CppCon'14'te Savunma Programlama Tamamlandı başlıklı çok ilginç bir konuşma yapıldı ( bölüm 1 , bölüm 2) ) . Konuşmasının ilk bölümünde sözleşme teorisi ve tanımlanmamış davranış tartışıyor. İkinci bölümde, sistematik argüman kontrolü için çok iyi bir teklif olarak gördüğümü sunar. Özünde, kullanıcının bir bütçenin ne kadarını (CPU kullanımı açısından) argüman kontrolü için kütüphaneye bağışlamak istediğini seçmesine izin veren iddia makroları önermekte ve kütüphanenin bu bütçeyi akıllıca kullanmasını sağlamıştır. Buna ek olarak, kullanıcı, kırık bir sözleşme tespit edilmesi durumunda çağrılacak olan genel bir hata işleme fonksiyonu da kurabilir.

Bir fonksiyonun özel olduğu yönüyle ilgili olarak, bunun argümanlarını asla kontrol etmememiz gerektiği anlamına gelmez . Dahili bir fonksiyonun sözleşmesini ihlal etmemek için kendi kodumuza daha fazla güvenebiliriz, ancak aynı zamanda mükemmel olmadığımızı da biliyoruz. Dahili işlevlerde bağımsız değişken denetimi, kendi hatalarımızı algılamak için, istemci kodundaki hataları algılamak için genel işlevlerde olduğu gibi yardımcı olur.


1

Aşağıdaki yapıyı düşünün:

  1. Dahili mantık: Bu fonksiyonun doğru parametrelerle çağrıldığı varsayılır ve bu nedenle dahili mantığınızı kontrol etmek için önkoşulları, sonkoşulları ve değişmezleri doğrulamak için varsayımlar kullanır.

  2. Kullanıcı arayüzü sarıcı: Bu fonksiyon, iç işlevini sarar ve InvalidArgumentExceptions yanlış değerlerini işlemek için ve onun girişlerini düzeltmek için kullanıcı anlatmak için kullanır: Assert(x).hasLength(4);, Assume(y).isAlphanumeric();, Assert(z).isZipCode();, Assume(mailAdress).matchesRegex(regex_MailAdress);, Reject(x).ifEmpty();, vb

  3. Toplu arabirim sarmalayıcısı: Bu işlev dahili işlevi sarar ve uzun süren bazı görevleri kesintiye uğratmadan yanlış değerleri işlemek için günlük, geçerlilik işaretleri ve istatistikleri kullanır. İşaretler daha sonra sonuç veritabanını kontrol eden ve temizleyen biri tarafından kullanılabilir.

  4. Komut satırı arabirimi sarıcısı: Bu işlev dahili işlevi sarar ve tekrar son girişi ister.

Farklı görevler için farklı yöntemlerde hem varsayımlar hem de istisnalar kullanmalısınız. Dahili mantığı parametre kontrolünden ayırmalısınız. Model, Görünüm, Kontrolör ayırımı ile karşılaştırın.


0

Boş referans denetiminden kaçınmanın daha iyi yolları vardır: denetimi sizin için yapmak için kod sözleşmesi veya bir AOP çerçevesi kullanın. Google "c # kod sözleşmesi" veya "mesaj paylaşımı".


Sanırım sorum da kod sözleşmelerine kadar uzanacaktı. Özel bir yöntemde yöntem önkoşullarını kontrol etmeye ihtiyaç var mı (örneğin, gelecekteki yazım denetimleri için veya kendinizi ayağınızı çekmekten alıkoymak için)?
Bay Moose
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.