Wann sind Ausnahmen gegen Fehlerobjekte gegen einfach falsch / null zu verwenden?

8

Ich bin gerade dabei, ein Plugin zu schreiben, und ich versuche zu beurteilen, wann verschiedene Ansätze zur Fehlerbehandlung verwendet werden sollen.

Ich denke über drei Methoden nach:

  • Auslösen einer Ausnahme (benutzerdefinierte Klasse)
  • Rückgabe eines Fehlerobjekts (Erweiterung von WP_Error)
  • Geben Sie einfach null / false zurück

Einige Situationen, die ich in Betracht ziehe

  • Es wird versucht, eine in der Registrierung gespeicherte Option abzurufen / festzulegen, die nicht vorhanden ist
  • Übergeben eines ungültigen Werts an eine Methode (was selten sein sollte)
  • Aufrufen einer Methode, in die der Overlader der Klasse nicht aufgelöst werden kann

Vorschläge? Da das Schreiben eines WordPress-Plugins einige spezielle Überlegungen enthält, bin ich mir nicht sicher, ob es sich lohnt, dies auf einem allgemeinen PHP-Board zu erfragen.

Doug Wollison
quelle

Antworten:

5

Ich denke, es ist unmöglich, hier eine endgültige Antwort zu geben, da Entscheidungen wie diese persönliche Vorlieben sind.

Bedenken Sie, dass das Folgende mein Ansatz ist und ich keine Vermutung habe, dass es der richtige ist .

Was ich mit Sicherheit sagen kann ist, dass Sie Ihre dritte Option vermeiden sollten:

Geben Sie einfach null / false zurück

Das ist unter verschiedenen Gesichtspunkten schlecht:

  • Rückgabekonsistenz
  • erschwert den Unit-Test
  • Erzwingen Sie eine bedingte Überprüfung des Rückgabetyps ( if (! is_null($thing))...), um das Lesen des Codes zu erschweren

Ich verwende mehr als oft OOP, um Plugins zu codieren, und meine Objektmethoden lösen oft Ausnahmen aus, wenn etwas schief geht.

Dabei mache ich:

  • Rückgabekonsistenz erreichen
  • Machen Sie den Code zum Unit-Test einfach
  • Der zurückgegebene Typ muss nicht bedingt überprüft werden

Allerdings Ausnahmen in einer Wordpress - Plugin zu werfen, bedeutet , dass nichts fangen sie in einem fatalen Fehler zu enden , die absolut ist nicht wünschenswert, expecially in der Produktion.

Um dieses Problem zu vermeiden, befindet sich normalerweise eine "Hauptroutine" in der Haupt-Plugin-Datei, die ich in einen try/ catch-Block einbinde. Dies gibt mir die Möglichkeit, die Ausnahme in der Produktion abzufangen und den schwerwiegenden Fehler zu verhindern.

Ein grobes Beispiel für eine Klasse:

# 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;
  }
}

und Verwendung aus der Haupt-Plugin-Datei:

# 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');

Natürlich können Sie in der realen Welt verschiedene Arten von Ausnahmen auslösen und abfangen und sich je nach Ausnahme unterschiedlich verhalten, aber dies sollte Ihnen eine Richtung geben.

Eine andere Option, die ich häufig verwende (und die Sie nicht erwähnt haben), besteht darin, Objekte zurückzugeben, die ein Flag enthalten, um zu überprüfen, ob kein Fehler auftritt, aber die Konsistenz des Rückgabetyps beizubehalten.

Dies ist ein grobes Beispiel für ein solches Objekt:

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;
   }
}

Jetzt können Sie von jedem Ort in Ihrem Plugin aus Folgendes tun:

/**
 * @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
}

Beachten Sie, dass my_plugin_get_options()oben immer eine Instanz einer OptionsKlasse zurückgegeben wird. Auf diese Weise können Sie den Rückgabewert immer weitergeben und ihn sogar an andere Objekte injizieren, die einen Typhinweis verwenden, und befürchten, dass der Typ anders ist.

Wenn die Funktion zurückgegeben wurde null/ falseim Fehlerfall, mussten Sie vor dem Weitergeben prüfen, ob der zurückgegebene Wert gültig ist.

Gleichzeitig haben Sie eine klare Möglichkeit zu verstehen, dass etwas mit der Optionsinstanz nicht stimmt.

Dies ist eine gute Lösung für den Fall, dass der Fehler leicht behoben werden kann, indem Standardeinstellungen verwendet werden oder was auch immer passt.

gmazzap
quelle