Nasıl beklenen hataları işlemek gerekir?

7 Cevap php

Benim kod hata işleme parçaları dizayn nasıl anlamak için mücadele ediyorum. Geçenlerde ben returning server error codes to the user, eg. 404 errors hakkında gitmek gerektiği konusunda benzer bir soru sordu. Ben uygulamanın geçerli parçası içinde gelen hatayı işlemek gerektiğini öğrendim; yeter basit görünüyor.

Ben zincirinin mevcut bağlantıdan hata işleyemez Ancak, ben ne yapmalıyım? Örneğin, ben doğrulamayı yönetmek için kullanılan bir sınıf olabilir. Bu en yöntemlerden biri olabilir createUser($username, $password). Edit: Bu yöntem, bir kullanıcı kimliği veya kullanıcı nesnesi dönecektir. , o işlev içinde, kullanıcı adı zaten var olmadığını belirlemek gerekir. Eğer bu doğruysa, nasıl bu konuda arama kodu uyarmak gerekir? Yerine kullanıcı nesnesi null dönen bir yoludur. Ama nasıl sonra ne hataya neden biliyor musunuz?

How should I handle errors in such a way that calling code can easily find out what caused the error? Is there a design pattern commonly used for this kind of situation?

Edit: Ben söylemeyi unuttum: Ben PHP kullanıyorum.


Birçok kişi istisnalar bu durumda kullanılması gerektiğini iddia ederken Solved:, bunu en iyi çözüm olduğu sonucuna gelmiş.

Öncelikle, istisnalar basit, zarif bir alternatif var. (Ben dilinde yerleşik bir sistem olmadan mümkün olmadığını keşif ... istisnalar zaten yerleşik olan)

İkincisi, yanıt olarak "istisnalar sadece istisnai durumlar için kullanılması gerektiğini ve bu bir değil" argümanı: "When I call getFoo(), I actually expect to get a Foo. If I don't get it, it's by definition an exceptional event." (via, pkainulainen)

7 Cevap

Birkaç ortak desenler vardır:

1.. Bir exception atın.

2.. NULL veya YANLIŞ dönün ve bir hata referans geçti ayarlayın. Örneğin

function createUser($user, $password, &$error)
{
      //...
      // You could use any type of object here.  This is just a simple example.
      if(uniqueKeyFailure)
      {
          $error = new UserAlreadyExists();
          return NULL;
      }
      //..
}

Bu gibi denilebilir:

$userCreateError = NULL;
$res = createUser($user, $pass, $userCreateError);
if($res === NULL)
{
  // do something with $userCreateError
}

3.. NULL veya YANLIŞ dönün ve bir olsun son hatayı sağlamak (örneğin, curl_error).

Ben 1 veya 2 önerebilirim. Insanlar kullanıcı girişi gibi "sakatlıklar" hataları durumları önlemek temel nedeni performans. Böyle Performance of try-catch in php gibi bu tartışma adil bir miktar vardır.

Bu evresel değil gibi ben 3 önermiyoruz.

Ben sık sık (bir kullanıcı gibi), bazı etki alanı nesne içinde benim doğrulama kalarak şey bu tür işlemek.

Örneğin:

<?PHP
$user->name = 'Joe';
$user->password = 'secret';

//try to save the user.
if (! $user->save()){
   $errors = $user->getMessages();
   // ... do something with error messages
}else{
   //the user object set it's own ID.
   $id = $user->id;
}

Şimdi, bir sürü kullanıcı arkasında abstracted. Orada nesnelerin bütün evren olabilir, ama o size kalmış olabilir.

Burada büyük bir sorundur: dünyada bir kimlik doğrulama sınıfı create, bir kullanıcı olurdu Neden? Kullanıcı nesneleri oluşturma Doğrulama kapsamı dışında muhtemelen.

Bu tip 'kullanıcı' (sadece kimliği doğrulanmış kullanıcı temsil eder) authenticate($username,$password) return bir nesne gibi bazı yöntem olması mantıklı olabilir, ama bu bile biraz dağınık.

Bunun yerine gibi bir şey düşünün:

<?PHP
$auth = new AuthService();
$u = new User();
$u->username='Joe';
$u->password='secret';

$authResult = $auth->authenticate($user);

if ($authResult->success){
  //$user has properties set as a side effect.
}else{
  //find out why it failed.
  $errors = $authResult->getErrors();
}

Tabii ki, bu doldurmak ve geri dönmek için AuthService için sonuç-değer sınıfının çeşit :: kimlik doğrulaması () tanımlanmasını gerektirir. Ama en azından, vb bazen booleans dönmek ve bazen nesneleri döndürmek yöntemleri ile bitmiyor

Bu tür DUPLICATE_USER veya INVALID_PASSWORD veya ne olursa olsun, kullanım için uygun olduğu gibi adlarla bir genel başlık dosyasında tanımlanmış olan tamsayıları dönebilirsiniz. Sonra arayan işlevi kolayca hata oluştu, ne tür belirlemek için küresel başlık beyanları karşı bu dönüş kodları kontrol edebilirsiniz.

Bu şekilde aşağıdaki yapılması gerekir -

Onları, hata kodları ile hata metni ve hata attı yöntemi bir hata nesnesi oluşturun.

Geri hata nesnesini iletin.

Geri istisnalar atmak olabilir ama istisnalar pahalı

EDIT - OP'ın düzenleme dayanarak. Bu durumda geriye bir istisna nesneyi atmak olurdu.

Bir hata kodu ile istisna sınıfı, hata açıklaması, sınıf adı, yöntem adı oluşturun. Geri istisna.

Eğer yöntemin dönüş türünü kontrol ederseniz, aynı zamanda bir ErrorDescription özelliği ve bir Kullanıcı Kimliği veya Kullanıcı nesne özelliği olurdu bir OperationResult nesne gibi bir şey dönmek için imza değiştirebilirsiniz.

Başarısız olursa doğrulama geçtiyseniz Dönüş null ve hata iletisi: en kolay yolu. Error sınıflarını veya istisnalar yapmak ihtiyacını önler. Ayrıca performans için iyi.

örn.

function numeric($input) {
    if (!is_numeric($input)) return 'Must be numeric.';
    return NULL;
}

function usernameavailable($input) {
    //query database....
    if ($result) return 'Username already taken, please choose another one.';
    return NULL;
}

Siz de parametreleri ile işlevlerini kullanabilirsiniz:

function length($input, $min, $max) {
    if (strlen($input) < $min) return "Must be longer than $min characters.";
    if (strlen($input) > $max) return "Must be shorter than $max characters.";
    return NULL;
}

Tüm formunda her öğe doğrulanıyor sonra son derece kolaydır. Tüm elemanları üzerinde sadece döngü, o öğe için tüm doğrulama işlevleri çağırmak ve varsa hata dizeleri toplamak. Hiçbir hata dizeleri varsa, o zaman tüm kullanıcı girişi geçerlidir.

Ben kuvvetle diğer cevaplar biri tarafından yapılan önerileri vazgeçirmek. Geçersiz kullanıcı girişi Olağanüstü değildir ve bir özel durum veya hata gerektirmez. Bu sadece olabildiğince basit şekilde ele alınması gereken bir beklenen kullanım durumunda bulunuyor.

Bu yöntem ile, oldukça kolay bir Form sınıfı oluşturmak ve sadece argümanlar doğrulama işlevleri olmak elemanları örneğini. Ayrıca aynı PHP doğrulama fonksiyonları asenkron istekleri göndererek AJAX doğrulama eklemek için bu genişletebilirsiniz.

Zaman çerçevesinden Örnek:

$Form = new AjaxForm();
$Form->add(new TextBox('Username', 'usernameavailable|length[3,12]'));
$Form->add(new SubmitButton());

Sadece üç satır ile istemci tarafında ve sunucu tarafı doğrulama hem de tamamen işlevsel bir form oluşturduk. Tabii ki tüm ayrıntılar size kalmış ama ben yine de geçersiz kullanıcı girişi beklenen ve Olağanüstü olmamalıdır gerektiğine inanıyoruz.

Sen adı CREATEUSER () yöntemini çağırarak ÖNCESİ varlığının kontrol edilmesi bekleniyor. Bunu yapmazsanız, ya da bir şey () kontrol ve CREATEUSER denilen zaman arasında olursa, bir istisna atar. Olması için yapılmış olduğu gibi hiçbir yerde gibi pahalı yakındır.

Bunun bir maliyeti var mı? Evet. Fark kadar büyük mü? Büyük olasılıkla hayır.