Quando utilizzare Eccezioni vs Oggetti di errore o semplicemente false / null


8

Sto scrivendo un plugin e sto provando a valutare quando utilizzare diversi approcci per la gestione degli errori.

Ci sono tre metodi che sto prendendo in considerazione:

  • Generazione di un'eccezione (classe personalizzata)
  • Restituzione di un oggetto errore (estensione di WP_Error)
  • Restituisce solo null / false

Alcune situazioni che sto prendendo in considerazione

  • Tentativo di ottenere / impostare un'opzione memorizzata nel registro che non esiste
  • Passare un valore non valido a un metodo (che dovrebbe essere raro)
  • Chiamare un metodo che il sovraccarico della classe non può risolvere

Suggerimenti? Dato che scrivere un plugin per WordPress ha alcune considerazioni speciali, non sono sicuro se varrebbe la pena chiederlo su una scheda PHP generale.

Risposte:


5

Penso che sia impossibile dare una risposta definitiva qui, perché scelte come questa sono preferenze personali.

Considera che ciò che segue è il mio approccio e non ho alcuna presunzione che sia quello giusto .

Quello che posso dire con certezza è che dovresti evitare la tua terza opzione:

Restituisce solo null / false

Questo è negativo sotto diversi aspetti:

  • ritorno tipo di coerenza
  • rende le funzioni più difficili per il test unitario
  • impone il controllo condizionale sul tipo restituito ( if (! is_null($thing))...) rendendo il codice più difficile da leggere

Io, più spesso, uso OOP per codificare plugin, e i miei metodi di oggetti spesso generano eccezioni quando qualcosa va storto.

In questo modo, io:

  • realizzare la coerenza del tipo di ritorno
  • rendere il codice semplice per unit test
  • non è necessario un controllo condizionale sul tipo restituito

Tuttavia, gettando le eccezioni in un plugin per WordPress, significa che nulla si cattura di loro, finendo in un errore fatale che è assolutamente non auspicabile, soprattutto nella produzione.

Per evitare questo problema, normalmente ho una "routine principale" che si trova nel file del plugin principale, che avvolgo in un blocco try/ catch. Questo mi dà la possibilità di cogliere l'eccezione nella produzione e prevenire l'errore fatale.

Un esempio approssimativo di una classe:

# myplugin/src/Foo.php

namespace MyPlugin;

class Foo {

  /**
   * @return bool
   */
  public function doSomething() {
     if ( ! get_option('my_plugin_everything_ok') ) {
        throw new SomethingWentWrongException('Something went wrong.');
     }

     // stuff here...

     return true;
  }
}

e usandolo dal file del plugin principale:

# myplugin/main-plugin-file.php

namespace MyPlugin;

function initialize() {

   try {

       $foo = new Foo();
       $foo->doSomething();      

   } catch(SomethingWentWrongException $e) {

       // on debug is better to notice when bad things happen
       if (defined('WP_DEBUG') && WP_DEBUG) {
          throw $e;
       }

       // on production just fire an action, making exception accessible e.g. for logging
       do_action('my_plugin_error_shit_happened', $e);
   }
}

add_action('wp_loaded', 'MyPlugin\\initialize');

Naturalmente, nel mondo reale puoi lanciare e catturare diversi tipi di eccezione e comportarti in modo diverso a seconda dell'eccezione, ma questo dovrebbe darti una direzione.

Un'altra opzione che uso spesso (e non hai menzionato) è quella di restituire oggetti che contengono un flag per verificare se non si verificano errori, ma mantenendo la coerenza del tipo restituito.

Questo è un esempio approssimativo di un oggetto del genere:

namespace MyPlugin;

class Options {

   private $options = [];
   private $ok = false;

   public function __construct($key)
   {
      $options = is_string($key) ? get_option($key) : false;
      if (is_array($options) && $options) {
         $this->options = $options;
         $this->ok = true;
      }
   }

   public function isOk()
   {
     return $this->ok;
   }
}

Ora, da qualsiasi posto nel tuo plugin, puoi fare:

/**
 * @return MyPlugin\Options
 */
function my_plugin_get_options() {
  return new MyPlugin\Options('my_plugin_options');
}

$options = my_plugin_get_options();
if ($options->isOk()) {
  // do stuff
}

Nota come my_plugin_get_options()sopra restituisce sempre un'istanza di Optionsclasse, in questo modo puoi sempre passare il valore restituito e persino iniettarlo in altri oggetti che usano il suggerimento del tipo con le preoccupazioni ora che il tipo è diverso.

Se la funzione era stata restituita null/ falsein caso di errore, prima di passarla in giro era stata costretta a verificare se il valore restituito è valido.

Allo stesso tempo, hai un modo chiaro per capire se qualcosa non va nell'istanza dell'opzione.

Questa è una buona soluzione nel caso in cui l'errore sia qualcosa che può essere facilmente recuperato, usando i valori predefiniti o qualunque cosa si adatti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.