2009-11-27 91 views
3

我通常通过返回false来指示方法中的错误,但它并不总是以我的语义凝聚(取决于方法,false可能是有效的返回)。什么时候最好在PHP中使用异常?

我研究过异常,我想知道他们是一种万能的解决方案吗?我应该返回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!');  
    } 

} 
+1

我回答了一个类似的问题,那里的答案可能也有用:http://stackoverflow.com/questions/1069617/would-i-want-to-throw-an-exception-or-an-error -in-this-php-script/1069640 – soulmerge 2009-11-27 06:13:48

回答

1

例外非常好!让你保持你的错误处理代码远离你的错误代码。

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

当我说这有助于让你的错误处理代码从你的错误远认为这

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

所以你并不需要检查每个功能上面有虚假回报和行为。

+0

的确,我一般都认同,但是你应该提到可能的性能劣势(例外成本)! – Sk8erPeter 2012-03-31 16:21:05

0

我会建议只使用一种样式,所以如果您已经通过返回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); 
} 

也许你会觉得有用。

+0

这是一个有趣的想法......我不知道是否我想用它混淆我的参数列表。 – alex 2009-11-27 05:41:51

0

根据Joel Spolsky的说法,Exceptions shouldn't be used

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

我倾向于根据可能导致触发问题的状态来判断是否抛出异常与返回布尔型false或其他处理方法有关的决定。

当特定的代码块被执行时,这是一个正常的,合理的值或状态吗?如果是这样,那么你可能只是想返回一个布尔型的假或其他值,表示代码块到达了失败点。

如果您担心可能存在非正常值或状态,或者值或状态是忘记在代码中正确初始化变量的结果,则可能会出现异常,因为这会提供作为开发人员即时向您反馈。这里有两个例子是必须在对象构造函数中设置的属性,但是值没有被正确指定,或者如果你有一个方法不应该在对象上调用,你可能想抛出一个异常如果它被调用。

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

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

2

我的思路是这样的:

如果一段代码不能做的工作,因为前置条件失败,抛出异常。

因此,如果您的getProductById()方法没有提供正确类型的值以便能够做到应有的功能,那就是抛出异常的原因。

由于“无结果”和“潜在无效状态”之间的明显区别,这使您可以更快地发现问题。如果你习惯于在这种情况下抛出一个异常,它会让你放心,因为它会以一种不确定/意外的方式失败,而不是以一种不确定的方式进行。

如果所有事情都按照应有的规定进行(如定义),但我还是会返回falsenull,但该过程并未找到匹配的产品。

P.S .:这也是为什么根据我的定义从输入验证中抛出异常是错误的。代码的全部目的是验证输入,所以无效输入是可预期的,因此不是特例。

相关问题