例外vsエラーオブジェクトvs単なるfalse / nullを使用する場合


8

私はプラグインを作成中であり、エラー処理の異なるアプローチをいつ使用するかを判断しようとしています。

私が検討している3つの方法があります:

  • 例外のスロー(カスタムクラス)
  • エラーオブジェクトを返す(WP_Errorの拡張)
  • null / falseを返すだけ

私が考えているいくつかの状況

  • 存在しないレジストリに保存されているオプションを取得または設定しようとしています
  • メソッドに無効な値を渡す(まれなはずです)
  • クラスのオーバーローダーが解決できないメソッドを呼び出す

提案?WordPressプラグインの作成には特別な考慮事項があるため、これを一般的なPHPボードで質問する価値があるかどうかはわかりません。

回答:


5

このような選択は個人的な好みなので、ここで決定的な答えを出すことは不可能だと思います。

以下が私のアプローチであり、私はそれが正しいものであるとは思いません。

私が確かに言えることは、3番目のオプションを避けるべきだということです。

null / falseを返すだけ

これはさまざまな側面で悪いです:

  • 戻り型の一貫性
  • 関数の単体テストが難しくなります
  • 戻り値の型の条件チェックを強制する(if (! is_null($thing))...)コードを読みにくくする

私は、プラグインをコード化するためにOOPを使用することが多く、何かがうまくいかない場合、オブジェクトメソッドが例外をスローすることがよくあります。

そうすることで、私は:

  • 戻り型の一貫性を実現する
  • ユニットテストを簡単にするコード
  • 返された型の条件付きチェックは必要ありません

ただし、WordPressプラグインで例外をスローすると、例外がキャッチされ、特に本番環境では絶対に望ましくない致命的なエラーが発生します。

この問題を回避するために、私は通常、メインのプラグインファイルに「メインルーチン」を配置し、それをtry/ catchブロックでラップしています。これにより、本番環境で例外をキャッチし、致命的なエラーを防ぐことができます。

クラスの大まかな例:

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

そしてそれをメインのプラグインファイルから使用します:

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

もちろん、現実の世界では、さまざまな種類の例外をスローしてキャッチし、例外に応じて異なる動作をする場合がありますが、これにより方向性が示されるはずです。

私がよく使用するもう1つのオプション(あなたは言及していません)は、エラーが発生していないかどうかを確認するためにフラグを含むオブジェクトを返すことですが、戻り値の型の一貫性を保ちます。

これはそのようなオブジェクトの大まかな例です:

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

これで、プラグインの任意の場所から、次のことができます。

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

my_plugin_get_options()上記は常にOptionsクラスのインスタンスを返すことに注意してください。このようにして、常に戻り値を渡し、タイプヒントが使用されている他のオブジェクトにそれを注入して、タイプが異なることが心配になります。

関数がnull/ falseエラーを返した場合、それを渡す前に、戻り値が有効かどうかを確認する必要がありました。

同時に、オプションインスタンスに問題があることを明確に理解する方法があります。

これは、エラーがデフォルトまたは適切なものを使用して簡単に回復できる場合の良い解決策です。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.