【问题标题】:When is best to use exceptions in PHP?什么时候最好在 PHP 中使用异常?
【发布时间】:2009-11-27 04:21:33
【问题描述】:

我通常通过返回 false 来指示方法中的错误,但它在语义上并不总是与我融为一体(取决于方法,false 可能是有效的返回)。

我研究了例外情况,想知道它们是一种万能的解决方案吗?我应该返回false吗?

可能完全忽略了这里的重点,所以请多多包涵。

// My old way
function getProductById($id) {

    if ( ! is_numeric($id)) {
         return false;     
    }

}

// My consideration
function getProductById($id) {

    if ( ! is_numeric($id)) {
         throw new Exception('The id must be numerical!');     
    }

}

【问题讨论】:

标签: php exception error-handling


【解决方案1】:

我的思路是这样的:

如果一段代码由于前置条件失败而无法完成工作,则抛出异常。

因此,如果您的 getProductById() 方法没有提供正确的值类型以能够执行其应有的操作,那么这就是引发异常的原因。

这使您可以更快地发现问题,因为“无结果”和“可能无效的状态”之间有明显的区别。如果您习惯在这种情况下抛出异常,它会让您高枕无忧,因为它会严重失败,而不是以未定义/意外的方式继续。

如果一切正常(如定义),我会返回 falsenull,但该过程只是没有找到匹配的产品。

P.S.:这也是为什么根据我的定义从输入验证中抛出异常是错误的。代码的全部目的是验证输入,因此无效输入是意料之中的,因此不会例外。

【讨论】:

    【解决方案2】:

    例外情况很棒!让您的错误处理代码远离错误代码。

    您是正确的,返回 false 可以是函数的有效答案。如果你抛出一个错误,你也可以捕获它并做一些更有用的事情。

    当我说它有助于让您的错误处理代码远离错误时,请考虑这一点

    try {    
        func1($a);  
        func2($b);  
        func3($c);  
    } catch (Exception $e) {  
        // error handling here  
    }  
    

    因此,您无需检查每个函数的错误返回并对其采取行动。

    【讨论】:

    • 没错,我大体上同意,但是您应该提到可能的性能劣势(例外成本)!
    【解决方案3】:

    我建议只使用一种样式,因此,如果到目前为止您已经通过返回 false 来编写应用程序,那么您应该考虑保持这种风格。

    但是,如果您想针对异常重写代码,请注意 PHP 中的异常非常耗费资源(包括 CPU 时间和内存)。我想通过例子来演示:想象有一个函数Product::getById($id)。如果您希望此函数在未找到 id 时引发异常,那么一切都很好。但是,如果您想在单个页面请求中多次调用该函数并收集所有不存在的 ID,您可能会首先考虑在循环中捕获异常。这导致了巨大的放缓。选项有:

    • 复制代码(创建一个名为Product::getByIdWithoutException()的函数)
    • 为此用例创建一个专用函数 (Product::getAllIds(array $ids))。这是最好的解决方案,但并不总是可行的(无需重写大量代码或拥有庞大的参数列表或违反软件工程的其他最佳实践等)。

    我终于切换到另一个模型,在其中我传递了一个参数来控制是否抛出异常。将默认值设置为 true 可以让我在不考虑此类错误情况的情况下懒惰地编程,并且我能够通过传递一个附加参数来交换异常以提高速度。如果在其他函数中抛出异常,这甚至可以工作,因为您可以传递该参数:

    function getById($id, $throwException = true) {
        if (!self::idExists($id)) {
            if ($throwException) {
                throw new IdNotFoundException();
            } else {
                return NULL;
            }
        }
        return self::getByWhereClause('id = ' . self::escape($id), $throwException);
    }
    

    觉得你可能会觉得这很有用。

    【讨论】:

    • 这是一个有趣的想法......我还不知道我是否想用它来弄乱我的参数列表。
    【解决方案4】:

    据 Joel Spolsky 所说,Exceptions shouldn't be used

    关于异常处理,我的一般经验法则是首先尝试为最终用户维护应用程序流,这可以通过在 PHP 中从不抛出异常来完成,但有时它们很有用。

    我倾向于根据可能导致触发问题的状态的条件来决定是抛出异常还是返回布尔值 false 或其他一些处理方法。

    这是执行特定代码块时的正常、合理的值或状态吗?如果是这样,那么您可能只想返回一个布尔值 false 或其他指示代码块到达故障点的值。

    如果您担心可能存在不正常的值或状态,或者该值或状态是有人忘记正确初始化代码中的变量的结果,那么异常可能是合适的,因为这会立即提供作为开发人员向您反馈。这里有几个示例是必须在对象构造函数中设置的必需属性,但未正确指定值,或者如果您有不应该在对象上调用方法的场景,您可能想要抛出异常如果它被调用。

    简而言之,我倾向于使用最适合的工具。如果我正在处理正常应用程序执行的一部分,那么我通常会返回一个值来指示失败。如果它发生了一些无效的情况,那么我会抛出一个异常以便我处理这个问题。

    我想你可以说我使用异常只是为了捕获那些应该真正停止最终用户执行应用程序的事情,但我在编写代码时考虑到通过适当的测试这些代码行都不应该在狂野的。

    【讨论】:

      猜你喜欢
      • 2011-05-25
      • 2020-01-28
      • 2012-05-24
      • 1970-01-01
      • 2021-11-06
      • 2010-09-12
      • 1970-01-01
      相关资源
      最近更新 更多