Когда использовать Исключения против Объектов Ошибок против простого ложного /нулевого

Я в процессе написания плагина, и я пытаюсь оценить, когда использовать разные подходы к обработке ошибок.

Есть три метода, которые я рассматриваю:

  • Выбрасывание исключения (пользовательский класс)
  • Возврат объекта ошибки (расширение WP_Error)
  • Просто верните null /false

Некоторые ситуации, которые я рассматриваю

  • Попытка получить /установить опцию, хранящуюся в реестре, который не существует
  • Передача недопустимого значения методу (который должен быть редок)
  • Вызов метода, который перегружатель класса не может разрешить для

Предложения? Поскольку у написания плагина WordPress есть некоторые особые соображения, я не уверен, стоит ли спрашивать об этом на общей доске PHP.

8 голосов | спросил Doug Wollison 22 FebruaryEurope/MoscowbMon, 22 Feb 2016 00:08:14 +0300000000amMon, 22 Feb 2016 00:08:14 +030016 2016, 00:08:14

1 ответ


5

Я думаю, что здесь невозможно дать окончательный ответ, потому что подобный выбор является личным предпочтением.

Рассмотрим, что следующим является подход my , и у меня нет презумпции, что это правильный .

Что я могу сказать наверняка, так это то, что вам следует избегать третьего варианта:

  

Просто верните null /false

Это плохо в разных аспектах:

  • тип возвращаемого контингента
  • упрощает выполнение модульных тестов
  • принудительная проверка на возвращаемом типе (if (! is_null($thing))...), что делает код более трудным для чтения.

Я, чаще всего, использую OOP для кодовых модулей, и мои объектные методы часто генерируют исключение, когда что-то идет не так.

Выполняя это, я:

  • выполнить возврат типа consinstency
  • сделать код простым для модульного тестирования
  • не требуется условная проверка возвращаемого типа

Однако выброс исключений в плагине WordPress означает, что ничего не будет catch , в результате чего возникает фатальная ошибка, которая является абсолютно не желательной, особенно в производстве.

Чтобы избежать этой проблемы, у меня обычно есть «основная процедура», расположенная в основном файле плагина, которую я обертываю в 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');

Конечно, в реальном мире вы можете бросить и поймать различные виды исключений и вести себя по-другому в соответствии с исключением, но это должно дать вам направление.

Другим вариантом, который я часто использую (и вы не упомянули), является возврат объектов, содержащих флаг, чтобы проверить, не произошло ли ошибка, но сохраняя согласованность возвращаемого типа.

Это приблизительный пример такого объекта:

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 в случае ошибки, прежде чем передавать его, вы были вынуждены проверить, действительно ли верное значение.

В то же время у вас есть четкий способ понять, что что-то не так с экземпляром опции.

Это хорошее решение, если ошибка - это то, что можно легко восстановить, используя настройки по умолчанию или что-то подходящее.

ответил gmazzap 22 J0000006Europe/Moscow 2016, 18:04:46

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132