it-swarm.com.de

Verwendung von Ausnahmen vs nur false/null

Ich bin gerade dabei, ein Plugin zu schreiben und ich versuche zu beurteilen, wann verschiedene Ansätze zum Behandeln von Fehlern verwendet werden sollen.

Es gibt drei Methoden, über die ich nachdenke:

  • Eine Ausnahme auslösen (benutzerdefinierte Klasse)
  • Zurückgeben eines Fehlerobjekts (Erweiterung von WP_Error)
  • Gib 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
  • Übergabe eines ungültigen Wertes an eine Methode (was selten sein sollte)
  • Aufrufen einer Methode, in die der Überlader der Klasse nicht auflösen kann

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

8
Doug Wollison

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

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

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

Gib einfach null/false zurück

Das ist schlecht unter verschiedenen Aspekten:

  • rückgabetyp Konsistenz
  • erschwert den Komponententest von Funktionen
  • erzwinge eine bedingte Überprüfung des Rückgabetyps (if (! is_null($thing))...), wodurch der Code schwerer zu lesen ist

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

Dabei mache ich:

  • rückgabetyp Konsistenz erreichen
  • machen Sie den Code einfach zu Unit-Test
  • für den zurückgegebenen Typ ist keine bedingte Prüfung erforderlich

Das Auslösen von Exceptions in einem WordPress-Plugin bedeutet jedoch, dass nichts catch sie abfängt, was zu einem schwerwiegenden Fehler führt, der absolut nicht wünschenswert ist, insbesondere in der Produktion.

Um dieses Problem zu vermeiden, habe ich normalerweise eine "Hauptroutine" in der Haupt-Plugin-Datei, die ich in einen try/catch-Block einbaue. 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 benutze es 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 werfen und fangen und sich je nach Ausnahme anders verhalten, aber dies sollte Ihnen eine Richtung geben.

Eine andere Option, die ich häufig benutze (und die Sie nicht erwähnt haben), ist die Rückgabe von Objekten, die ein Flag enthalten, um zu überprüfen, ob kein Fehler aufgetreten ist, wobei jedoch die Konsistenz des Rückgabetyps beibehalten wird.

Dies ist ein grobes Beispiel für ein Objekt wie dieses:

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 der Klasse Options zurückgibt. Auf diese Weise können Sie den Rückgabewert immer weitergeben und sogar in andere Objekte einfügen, die den Typ-Hinweis verwenden, und sich jetzt Sorgen machen, dass der Typ unterschiedlich ist.

Wenn die Funktion im Fehlerfall null/false zurückgegeben hatte, mussten Sie vor der Weitergabe prüfen, ob der zurückgegebene Wert gültig ist.

Gleichzeitig haben Sie eine klare Vorstellung davon, dass mit der Optionsinstanz etwas 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.

5
gmazzap