Benim tüm PHP kodu yakalamak, ya da mümkün olduğunca spesifik - denemek için iyi bir uygulama mı?

8 Cevap php

I do not have many kinds of Exceptions in my project.
Right now,(we use MVC) I have the try catch encompassing my entire code:

try{
   fronController::dispatch($somthing...);
}catch(Exception $E){
  //handle errors
}

Ben mümkün olduğu kadar mümkün yolu olarak özel olarak try-catch bloğu kullanmak ya da şimdi olduğu gibi sadece genel tutmak için iyi bir neden var acaba?

8 Cevap

Genellikle, yerel atmak bir istisna işleyicisi yerel idare bu durumda bir işleve özel sürece küresel yakalamak.

 class fooException extends Exception{}

 // DB CLASS

 public function Open(){
    // open DB connection
    ...
    if ($this->Conn->connect_errno) 
      throw new fooException("Could not connect: " . $this->Conn->connect_error);
  }

 // MAIN CLASS

 public final function Main(){
    try{
      // do stuff
    }
    catch(fooException $ex){
       //handle fooExceptions
    }
 }

Bir fonksiyonu özel değerlerine dönmek zorunda kalmadan başarısızlık rapor böylece bir istisna fikirdir. Siz eski PHP, bir fonksiyonu bunu söyleyebiliriz tek yolu bir sorun false veya -1 gibi bazı özel değer dönerek vardı. Bu hoş değil. Örneğin,) ben file_get_contents bir varyantını (yazıyorum varsayalım.

Pozitif bir tamsayı tarafından temsil - Tipik dönüş değeri bir kolu olduğunu. Eğer belirtilen dosya bulunamadı veya belirtilen dosya okunabilir değildi: Ancak, ben karşılaşma iki temel sorun vardır. Kolları olumlu çünkü - - bir hata belirtmek için ben negatif bir sayı döndürür olabilir hata belirli bir neden ilişkilendirir. Adlı dosya yoktu ve -2 dosya okunabilir değildi anlamına gelir ki -1 diyelim.

Şimdi bir sorun var -1 ve -2 yapamaz doğal olarak mean anything kodunu okuma birisi. Bunu düzeltmek için biz küresel sabitleri file_not_found ve FILE_NOT_READABLE tanıtmak. Biraz çıkan kodu görelim.

<?php

define('FILE_NOT_FOUND', -1);
define('FILE_NOT_READABLE', -2);

function my_file_get_contents($file) {
    // blah blah blah
}

$friendListFile = getDefaultFriendListFile();

$result = my_file_get_contents($friendListFile);

if ($result == FILE_NOT_FOUND) {
    deleteFriendListFromMenu();
} elseif ($result == FILE_NOT_READABLE) {
    alertUserAboutPermissionProblem();
} else {
    useFriendList($result);
}

Biz act accordingly sorun gerçekten ne olabilir, farklı hata kodları alarak. Bu işlevsellik iyi ve güzel olduğunu. Sorun purely kod okur nasıl olduğunu.

$result bir horrible değişken adıdır. Değişken isimleri $friendListFile gibi, açıklayıcı ve belirgin olmalıdır. Için gerçek adı $result, sadece çok uzun, biz iki anlamı olan tek bir değişken yüklenme nasıl examplifies $fileContentsOrErrorCode hangi olmasıdır. Sen, hiç, aynı veri iki şey demek istiyorum asla. Biz istiyoruz, ayrı bir $errorCode ve $fileContents!

Peki bu soruna alabilirim? Bazı PHP kütüphaneleri kullanmış biri değil-gerçekten-bir-bir çözüm bir sorunla karşılaşırsanız eğer onların my_file_get_contents() gibi fonksiyonlar false return sahip olmaktır. Sorun aslında biz bunun yerine diyoruz ne oldu disambiguate my_file_get_contents_getError(). Bu almost çalışır.

define('FILE_OKAY', 0);
define('FILE_NOT_FOUND', -1);
define('FILE_NOT_READABLE', -2);

$my_file_get_contents_error = FILE_OKAY;

function my_file_get_contents_getError() {
    // blah blah blah
}

function my_file_get_contents($file) {
    global $my_file_get_contents_error;
    // blah blah blah
    // whoa, an error? return false and store the error code in
    // $my_file_get_contents_error
    // no error? set $my_file_get_contents_error to FILE_OKAY
}

$friendListFile = getDefaultFriendListFile();

$result = my_file_get_contents($friendListFile);

if (my_file_get_contents_getError() == FILE_NOT_FOUND) {
    deleteFriendListFromMenu();
} elseif (my_file_get_contents_getError() == FILE_NOT_READABLE) {
    alertUserAboutPermissionProblem();
} elseif (my_file_get_contents_getError() == FILE_OKAY) {
    useFriendList($result);
} else {
    die('I have no idea what happened. my_file_get_contents_getError() returns '
        . my_file_get_contents_getError()
    );
}

Bir not olarak, evet, biz bir global değişken ve diğer bu tür ufak tefek kaçınarak çok daha iyi bir iş yapabilirsiniz. Bu fındık-ve-cıvata gösteri düşünün.

Biz still $fileContentsOrFalseIfError daha $result bir şey diyemem. Bu sorun sabit olmamıştır.

Ben şimdi önceki örnekte fark olabilir bir sorunu pekiştirmiştir. Bizde ne varsa hata kodlarının tümünü kapsayacak değil mi? Bir programcı -3 kod olması gerektiğine karar verirse biz aslında bunu tespit değildi! Biz $result emin bir hata kodu değildi yapmak için bir dize ise teslim olabilirdi, ama biz doğru, gerçekten PHP türleri hakkında bakım gerekiyordu değil mi? Şimdi biz my_file_get_contents_getError() bir başarı kodu dahil etmek hiç sorun değil, ikinci bir dönüş değeri yararlanabilirler.

Ortaya çıkan yepyeni bir problem var. Birini düzeltmek ve eh üç tane daha bulmak? Yeni bir sorun, yalnızca en-son hata kodu muhafaza edilebilir olmasıdır. Bu terribly kırılgan! Başka bir şey aramalar my_file_get_contents() Eğer hata kodu ile anlaşma önce ise, kendi kod senin üzerine yazılır!

Gah, şimdi biz size my_file_get_contents_getError () dan dönüş değeri ile anlaşma önce aramak için güvenli olmayan fonksiyonların bir listesini tutmak gerekir. Bunu yapmazsanız, size her zaman size ait hata kodu kurtarmak için my_file_get_contents() hemen sonra my_file_get_contents_getError() çağrı bir ad-hoc kodlama kongre olarak tutmak zorunda o gizemli yazılır önce.

Bekle! Neden sadece bizim arayanlar için tanımlayıcı dağıtmak değil mi? Kullanmak için my_file_get_contents() şimdi tüm diğer arayanlar ile disambiguate bazı dizi için create_my_file_get_contents_handle() sormak gerekir. Şimdi my_file_get_contents($myHandle, $myFile) arayabilir ve hata kodu sadece sizin için özel bir yerde saklanabilir. Şimdi my_file_get_contents_getError($myHandle) sen, o özel bir yere ulaşmak için hata kodunu almak ve hiç kimse senin ayak bastı gelmiştir olabilir çağırdığınızda.

Birçok arayanlar varsa Er, ama biz zillions etrafta gereksiz hata kodları sahip istemiyorum. Bu yüzden bazı bellek özgür olabilir biz daha onlar bitince destroy_my_file_get_contents_handle($myHandle) aramak için kullanıcılara sormak vardı.

Ben bu ey eski PHP mantralar için very tanıdık duygu umuyoruz.

This is all so crazy, just make it simple, please!

language hataları tepki daha iyi bir mekanizma desteklenen eğer ne demek istiyorsunuz? Açıkçası, mevcut araçları ile bazı çözüm oluşturmak için çalışıyoruz, kafa karıştırıcı, iğrenç ve hata eğilimli.

Istisnalarını girin!

<?php

class FileNotFoundException extends Exception {}
class FileNotReadableException extends Exception {}

function my_file_get_contents($file) {
    if (!is_file($file)) {
        throw new FileNotFoundException($file);
    } elseif (!is_readable($file)) {
        throw new FileNotReadableException($file);
    } else {
        // blah blah blah
    }
}

$friendListFile = getDefaultFriendListFile();

try {
    $fileContents = my_file_get_contents($friendListFile);
    useFriendList($fileContents);
} catch (FileNotFoundException $e) {
    deleteFriendListFromMenu();
} catch (FileNotReadableException $e) {
    alertUserAboutPermissionProblem();
}

Özel dönüş değerleri ve kolları ve kodlama sözleşmeler ani bizim eski baş ağrısı tüm tedavi edilmiştir!

Biz şimdi gerçekten $result $fileContents için yeniden adlandırabilirsiniz. my_file_get_contents() bir sorunu varsa, atama tamamen durduruldu ve biz sağ aşağı uygun catch bloğuna atlayacak. Only if there is no error biz bile $fileContents bir değer vererek ya da useFriendList() arama hakkında düşünüyorum.

Artık biz birbirimizin hata kodları ile ilgili adım birden arayanlar tarafından boğulmuş! Hata ortaya çıkarsa my_file_get_contents her () çağrısı, kendi istisnalarını örneğini.

Hafıza problemleri yok! Çöp toplayıcı mutlulukla bunu düşünmeden, artık kullanılan istisna nesneleri temizlemek olacaktır. Ye elle kolu yok hatırlamak zorunda eski kolu sistemini kullanarak diye bellekte sonsuza pusuda var.

Istisnalar birçok diğer faydaları ve özellikleri vardır. Ben şiddetle bu konuda bilgi edinmek için diğer kaynaklara bakarak öneririz. Özellikle ilginç bazı arayan onları nasıl kabarcık kadar yürütme yığın yakalayabilirsiniz kadar. Ayrıca ilginç Eğer, bir özel durum yakalamak sorunu çözmek için deneyin ve sonra durum eğer değil rethrow nasıl olduğunu. Istisnalar nesneler olduğunu unutmayın! Bununla elde edilecek esneklik yükler vardır. Kimse yakalamak olduğunu istisnalar için, istisna işleyici içine bakmak.

Soruyu cevaplamak benim niyet biz istisnaları neden ihtiyaç göstermekti. Bunu yaparak, bunu biz onlarla çözebiliriz ne sorunlar anlaması kolaydır umuyoruz.

Tüm kod için bir try bloğu kullanıyorsanız, siz de (bkz: the docs) varsayılan bir istisna eylemcisi tanımlayabilirsiniz.

Bunun dışında, try'ın boyutu sizin hata olmak işleme istiyorum nasıl ince bağlıdır, size kalmış. Eğer istisnalar herhangi kurtarmak yapamıyorsanız belirli (ama istisna ve yığın izlemesi mesajı büyük olasılıkla yeterli olacaktır) hata iletileri günlüğe istediğiniz sürece, belirli olması için hiçbir sebep, gerçekten var.

Eğer kod hataları yakalamak mümkün olduğunca spesifik olmalıdır. Belirli hataları yakalamak uygun, kod sürdürülebilirliğini artırır kod yapılandırılmış ve organize yapar.

Daha sonra takım tabanlı projeler üzerinde çalışmak ve kod bakarak tek değiliz, özellikle eğer, bir kongre olarak da iyi bir uygulamadır.

Şahsen bir try catch bloğunun içine her şeyi atma code smell gibi görünüyor.

Sizin bir genel catch ile hataları her işleme bir hata occour yaptığında asgari bildirim ve seçenekleri alırsınız, bu gelişim sırasında iyi olabilir ama onun ön saflarda size sorunların sonu neden olabilir zaman.

Spesifik olun ve geribildirim gerekli ve recoverablity mümkün olduğunu üsleri tamamını kapsayacak.

Farklı hatalar farklı yanıtlar gerektirebilir.

Ortaya çıkabilecek her türlü soruna cevaben bir uçaktan atlamak olmaz. Yapar mısın?

Eh, bu app ne yapıyor bulunuyor.

Bir istisna tutulabilir ve uygulama çalışmaya devam olabilecek durumlar vardır. Daha büyük olasılıkla, app farklı farklı durumlarda istisna aynı sınıfa cevap gerekebilir. Belki bir işlevi bir I / O istisna zararlı değil ama başka öyle.

Istisnalar istisnai durumlar için olduğunu unutmayın. Bunu anlamak gibi hata sizin kontrolünüz dışında olduğu zaman, olur. Örneğin, geçersiz parametreler sıfıra kamu API işlevi, bölünme geçirilen, 'kayıp ağ bağlantısı' gibi durumlar, 'dosya bulunamadı' ... bu tür şeyler.

Genel bir kural olarak, bunu nasıl ele bilmiyorsanız, o başarısız izin vermek daha iyidir hata kurtarma, vb gibi, hata oturum ve onu yaymak, sen nasıl işleneceğini biliyor durumları yakalamak gerekir. Aksi takdirde uygulama istemeyebilirsiniz bir hata durumunda olabilir.

Her istisna (sessizce yutma kötü bir fikirdir) onunla ne yapacağını biliyorum sadece ele alınmalıdır beri yüzden soruyu cevaplarken, mümkün olduğunca spesifik olmak daha iyidir. Sadece özel bir şey yanlış gitmiş kullanıcıya bildirmek izin değilse. Yoksa, hata oturum ve rethrow için istisnayı yakalamak istiyorsanız.

Orada here C + + için iyi bir tartışma var, ama genel kavramlar geçerlidir. Ben java tutorials on exceptions de çok iyi buldum.

Spesifik olun ve uygun spesifik hataları işlemek.