Yeniden düzenleme bir istisnayı soyutlama sızdırıyor mu?


12

Belgelerde belirli bir istisna türü atacağını bildiren bir arabirim yöntemi var. Bu yöntemin uygulanması, istisna oluşturan bir şey kullanır. Dahili istisna yakalanır ve arayüz sözleşmesi tarafından beyan edilen istisna atılır. İşte daha iyi açıklamak için küçük bir kod örneği. PHP ile yazılmış ama takip etmek oldukça basit.

// in the interface

/**
 * @return This method returns a doohickey to use when you need to foo
 * @throws DoohickeyDisasterException
 */
public function getThatDoohickey();

// in the implementation

public function getThatDoohickey() {

    try {
        $SomethingInTheClass->doSomethingThatThrowsAnException();
    } catch (Exception $Exc) {
        throw new DoohickeyDisasterException('Message about doohickey failure');
    }

    // other code may return the doohickey

}

Bu yöntemi soyutlamanın sızmasını önlemek için kullanıyorum.

Sorularım şunlardır: Önceki istisna olarak atılan iç istisnayı geçmek soyutlamayı sızdırıyor mu? Değilse, bir önceki istisnanın mesajını tekrar kullanmak uygun olur mu? Eğer soyutlamayı sızdıracaksa, neden düşündüğüne dair bir rehberlik sağlayabilir misiniz?

Sadece açıklığa kavuşturmak gerekirse, sorum şu kod satırına geçmeyi içerecekti

throw new DoohickeyDisasterException($Exc->getMessage(), null, $Exc);

İstisnalar hakkında olmalıdır nedenleri hakkında değil onları atar kim . Kodunuzda bir varsa, a file_not_foundatmalıdır file_not_found_exception. İstisnalar gerektiğini değil kütüphane spesifik olun.
Mooing Duck

Yanıtlar:


11

Sorularım şunlardır: Önceki istisna olarak atılan iç istisnayı geçmek soyutlamayı sızdırıyor mu? Değilse, bir önceki istisnanın mesajını tekrar kullanmak uygun olur mu?

Cevap, duruma bağlı".

Özellikle, istisnaya ve ne anlama geldiğine bağlıdır. Özünde, yeniden yazmak, bunu arayüzünüze eklediğiniz anlamına gelir. Kendiniz çağırdığınız kodu yazdıysanız bunu yapar mıydınız yoksa bu sadece istisnayı yeniden markalamaktan kaçınmak için mi?

İstisnanız kök nedene kadar bir iz içeriyorsa, çağrılan kodda, soyutlamanın dışında veri sızdırabilir - ancak genel olarak bunun kabul edilebilir olduğunu düşünüyorum, çünkü istisna ya arayan tarafından işlenir (ve kimse nerede umursamıyor gelen) veya kullanıcıya gösterilir (ve hata ayıklama için temel nedeni bilmek istersiniz.)

Bununla birlikte, sık sık, istisnanın geçmesine izin vermek, soyutlama sorunu değil, çok makul bir uygulama seçimidir. Sadece sormak "Eğer çağırıyorum kod vermedi eğer bunu atmak?"


8

'İç' istisna bir uygulama işleyişiyle ilgili bir şey söylerse Doğruyu söylemek gerekirse, sen edilir sızıntı. Bu yüzden teknik olarak, her zaman her şeyi yakalamalı ve kendi istisna türünüzü atmalısınız.

FAKAT.

Buna karşı birkaç önemli argüman yapılabilir . En önemlisi:

  • İstisnalar istisnai şeylerdir ; zaten 'normal çalışma' kurallarını birçok yönden ihlal ediyorlar, bu yüzden kapsülleme ve arayüz düzeyinde soyutlamayı da ihlal edebilirler.
  • Anlamlı bir yığın izleme ve nokta hata bilgisine sahip olmanın yararı , UI bariyerini (bilgi ifşası gibi) geçmeden dahili program bilgilerini sızdırmazsanız, genellikle OOP doğruluğundan ağır basar.
  • Her bir iç istisnanın uygun bir dış istisna tipinde sarılması , istisnaların tüm amacını yenen çok sayıda yararsız kazan plakası koduna yol açabilir (yani, hata işleme kazan plakası ile normal kod akışını kirletmeden hata işlemeyi uygulayın).

Yani istisnalar yakalayıp sarma dedi sıklıkla yaptığı mantıklı Günlüklerinizdeki ek bilgi eklemek için, ya da son kullanıcıya dahili bilgileri sızdıran önlemek için yalnızca. Hata işleme hala bir sanat formudur ve birkaç genel kurala göre kaynatmak zordur. Bazı istisnalar köpürmeli, diğerleri olmamalı ve karar da bağlama bağlıdır. Bir kullanıcı arayüzünü kodluyorsanız, kullanıcının filtrelenmemiş bir şeye geçmesine izin vermek istemezsiniz; ancak bazı ağ protokollerini uygulayan bir kitaplığı kodluyorsanız, belirli istisnaları köpürmek muhtemelen doğru olan şeydir (sonuçta, ağ kapalıysa, bilgileri geliştirmek veya kurtarmak ve devam etmek için yapabileceğiniz çok az şey vardır) ; tercüme NetworkDownExceptionetmek FoobarNetworkDownException) sadece anlamsız, cruft olduğunu.


6

Her şeyden önce, burada yaptığınız şey bir istisna yeniden değil. Yeniden değerlendirme, tam olarak aynı istisnayı şu şekilde atmak olacaktır:

try {
    $SomethingInTheClass->doSomethingThatThrowsAnException();
} catch (Exception $Exc) {
    throw $Exc;
}

Açıkçası, bu biraz anlamsız. Yeniden değerlendirme, bazı kaynakları serbest bırakmak veya istisnayı ya da yapmak istediklerinizi günlüğe kaydetmek istediğiniz durumlar içindir.

Yaptığınız şey, nedeni ne olursa olsun, tüm istisnaları bir DoohickeyDisasterException ile değiştirmektir. Hangi yapmak istediğinizi olabilir veya olmayabilir. Ama bunu öneririm herhangi önerdiğiniz ve bir iç istisna olarak orijinal istisna geçerken Bunu sefer, ayrıca yığın izleme yararlıdır ihtimale karşı yapmalıdır.

Ama bu sızdıran soyutlamalarla ilgili değil, bu başka bir mesele.

Yeniden yapılandırılmış bir istisnanın (veya gerçekten yakalanmamış bir istisnanın) sızdıran bir soyutlama olup olmadığı sorusunu cevaplamak için, bunun arama kodunuza bağlı olduğunu söyleyebilirim. Bu kod soyutlanmış çerçevenin bilgisini gerektiriyorsa, o zaman sızdıran bir soyutlamadır, çünkü bu çerçeveyi başka bir çerçeveyle değiştirirseniz, soyutlamanızın dışındaki kodu değiştirmeniz gerekir.

Örneğin, DoohickeyDisasterException çerçeveden bir sınıfsa ve arama kodunuz şöyle görünüyorsa, sızdıran bir soyutlamanız vardır:

try {
    $wrapper->getThatDoohickey();
} catch (DoohickeyDisasterException $Exc) {
    echo "The Doohickey is all wrong!";
    echo $Exc->getMessage();
    gotoAHappyPlaceAndSingHappySongs();
}

Üçüncü taraf çerçevenizi farklı bir istisna adı kullanan başka bir çerçeveyle değiştirirseniz ve tüm bu başvuruları bulup değiştirmeniz gerekir. Kendi Exception sınıfınızı oluşturmak ve çerçeve istisnasını içine sarmak daha iyidir.

Öte yandan, DoohickeyDisasterException kendi yapımlarınızdan biri ise, soyutlamalardan sızmıyorsanız, ilk noktam ile daha fazla ilgilenmelisiniz.


2

Geçmeye çalıştığım kural: neden olduysanız sarın. Benzer şekilde, bir çalışma zamanı istisnası nedeniyle bir hata oluşturulacaksa, bunun bir tür DoHickeyException veya MyApplicationException olması gerekir.

Bunun anlamı, hatanın nedeni kodunuzun dışında bir şeyse ve hata yapmasını beklemiyorsanız, o zaman zarif bir şekilde başarısız olur ve yeniden atar. Benzer şekilde, kodunuzla ilgili bir sorun varsa, kodu (potansiyel olarak) özel bir istisnaya sarın.

Örneğin, bir dosya halinde, beklenen diskte olması, veya bir hizmet olduğu beklenen kullanılabilir olması, daha sonra incelikle ele ve bu kaynağın neden kullanılamadığını kodunuzun tüketici anlamaya böylece hatayı yeniden atmak. Bir tür için çok fazla veri oluşturduysanız, sarmak ve atmak sizin hatanızdır.

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.