Khi nào nên sử dụng Ngoại lệ và Đối tượng Lỗi so với chỉ sai / null


8

Tôi đang trong quá trình viết một plugin và tôi đang cố gắng đánh giá khi nào nên sử dụng các cách tiếp cận khác nhau để xử lý lỗi.

Có ba phương pháp tôi đang xem xét:

  • Ném một ngoại lệ (lớp tùy chỉnh)
  • Trả về một đối tượng lỗi (phần mở rộng của WP_Error)
  • Chỉ cần trả về null / false

Một số tình huống mà tôi đang xem xét

  • Cố gắng nhận / đặt tùy chọn được lưu trữ trong Sổ đăng ký không tồn tại
  • Truyền một giá trị không hợp lệ cho một phương thức (điều này rất hiếm)
  • Gọi một phương thức mà bộ nạp chồng của lớp không thể giải quyết

Gợi ý? Vì việc viết một plugin WordPress có một số cân nhắc đặc biệt, tôi không chắc liệu nó có đáng để hỏi điều này trên một bảng PHP chung hay không.

Câu trả lời:


5

Tôi nghĩ rằng không thể đưa ra một câu trả lời dứt khoát ở đây, bởi vì những lựa chọn như thế này là sở thích cá nhân.

Hãy xem xét rằng những gì tiếp theo là cách tiếp cận của tôi , và tôi không có giả định rằng đó là cách tiếp cận đúng .

Điều tôi có thể nói chắc chắn là bạn nên tránh lựa chọn thứ ba của mình:

Chỉ cần trả về null / false

Điều này là xấu dưới khía cạnh khác nhau:

  • trả lại loại liên tục
  • làm cho các chức năng khó hơn để kiểm tra đơn vị
  • buộc kiểm tra có điều kiện về kiểu trả về ( if (! is_null($thing))...) làm cho mã khó đọc hơn

Tôi, thường xuyên hơn, sử dụng OOP để mã trình cắm và các phương thức đối tượng của tôi thường ném ngoại lệ khi có sự cố.

Làm điều đó, tôi:

  • hoàn thành sự đồng thuận
  • làm cho mã đơn giản để kiểm tra đơn vị
  • không cần kiểm tra có điều kiện về loại trả lại

Tuy nhiên, ném ngoại lệ vào một plugin WordPress, có nghĩa là sẽ không có gì bắt được chúng, kết thúc bằng một lỗi nghiêm trọng hoàn toàn không mong muốn, đặc biệt là trong sản xuất.

Để tránh vấn đề này, tôi thường có một "thói quen chính" nằm trong tệp plugin chính, mà tôi gói trong một khối try/ catch. Điều này cho tôi cơ hội để bắt ngoại lệ trong sản xuất và ngăn ngừa lỗi nghiêm trọng.

Một ví dụ sơ bộ của một lớp:

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

và sử dụng nó từ tệp plugin chính:

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

Tất nhiên, trong thế giới thực, bạn có thể ném và bắt các loại ngoại lệ khác nhau và hành xử khác nhau theo ngoại lệ, nhưng điều này sẽ cho bạn một hướng đi.

Một tùy chọn khác mà tôi thường sử dụng (và bạn không đề cập) là trả về các đối tượng có chứa cờ để xác minh nếu không có lỗi xảy ra, nhưng vẫn giữ tính nhất quán của kiểu trả về.

Đây là một ví dụ sơ bộ về một đối tượng như thế:

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

Bây giờ, từ bất kỳ nơi nào trong plugin của bạn, bạn có thể làm:

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

Lưu ý làm thế nào my_plugin_get_options()ở trên luôn trả về một thể hiện của Optionslớp, theo cách này, bạn luôn có thể chuyển giá trị trả về xung quanh và thậm chí tiêm nó cho các đối tượng khác sử dụng gợi ý kiểu mà bây giờ lo lắng rằng kiểu này khác.

Nếu hàm đã trả về null/ falsetrong trường hợp có lỗi, trước khi chuyển nó xung quanh bạn đã buộc phải kiểm tra xem giá trị trả về có hợp lệ không.

Đồng thời, bạn có một cách rõ ràng để hiểu là có gì đó không đúng với thể hiện tùy chọn.

Đây là một giải pháp tốt trong trường hợp lỗi là thứ có thể dễ dàng phục hồi, sử dụng mặc định hoặc bất cứ điều gì phù hợp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.