在Do / While中使用Try / catch

时间:2011-06-03 04:03:46

标签: php

这更像是一个概念性问题。

是否可以使用try / catch来调用do / while循环?

例如:

<?php
function main() {

    $failure = 0;
    do {
       $failure += foo();
       $failure += bar();
       ...
       if ($failure) { return $failure; }
    } 
    while ($failure == 0);
}

function foo() {
    try {
        echo 'DO FOO STUFF<br />';
        return 0;
    } 
    catch (Exception $e) {
        return 1;
    }
}

function bar() {
    try {
        echo 'DO BAR STUFF<br />';
        return 0;
    } 
    catch (Exception $e) {
        return 1;
    }
}
?>

我问的原因是我在某处读到混合两者都是不好的做法。您应该创建自己的异常并“抛出”它们。但这不是一种矫枉过正吗?

编辑: 为了解释出现这个问题的场景,想象一下必须遵循一条线的机器人。每当他迈出一步并且将信息发送到服务器时,机器人计算其位置(X位置,Y位置,Z位置和“姿势”位置)。服务器双重检查此信息。如果发现任何异常,服务器会向机器人发送“停止”信号。机器人停止,重新计算其位置,重新发送信息并等待“开始”信号。

此循环示例基于从机器人接收的数据馈送。如果出现问题(如无线链路断开,障碍物或失误),机器人必须停下来以防止误入歧途,跌倒或任何事情。我们不知道出了什么问题,或者为什么出错了,只是它出错(或不出错)。 (这实际上是在代码的另一部分,而不是基于PHP的调试模块)。

编辑2: 像所有人一样指出,似乎正确的方法是正确地提出/处理异常。 既然每个人似乎都同意这一点,我不知道是谁给出了“正确答案”。 如果可以的话,我会等几天给更多选票的那个!

3 个答案:

答案 0 :(得分:3)

没有理由避免try/catchdo/while混合。

但是,您提供的示例与do/while的问题较少,而try/catch块中的吞咽例外情况较多。

在任何语言,PHP或其他语言中捕获基本异常类型并吞下它是一种不好的做法。最好只捕获特定的异常类型,让剩下的部分通过catch块。

例如,如果您正在访问一个文件,并且捕获了FileNotFound异常(如果在PHP中有这样的东西),那就没问题。

但是如果你捕获所有异常类型,那么你将会发现像OutOfMemoryException这样的东西。如果你妥善处理它,那就没关系,并确保它不会再扔了。但在你的情况下,你可能不会为这种情况“做正确的事”,所以你应该让它落空。

您不想吃异常(不记录它们)的原因是,如果代码进入锁定的生产环境,您将无法调试代码。如果捕获到异常,那么用户将看到错误的行为,并且将无法提交错误报告,该报告为您提供足够的信息来调试它。他们可能会给你repro步骤,但这是非常不可靠的。对于一个间歇性的问题,这也毫无价值。

如果您吃掉了异常,那么您基本上就会丢弃最有用的数据进行调试。

使这不那么真实的事情:

  • 有时在顶级Web代码中,您需要捕获异常,记录它,然后吞下它以便用户看不到它(但是从函数返回,因此您不能执行更多代码一个越野车的状态)。这使得用户看不到有关您的代码的显示信息(堆栈跟踪)。
  • 如果您正在进行异常处理的语言对异常的支持不足,并且没有派生的异常类型。我对PHP知之甚少,所以这种语言可能有也可能不对。

答案 1 :(得分:1)

如果您想吞下异常并报告失败,那么这没关系。你必须做像

这样的事情
   $failure &= bar();
但是,或者你将失去foo()的失败条件。

如果你希望能够在调用堆栈的后面进一步处理异常,那么你最好不要单独使用它,或者至少重新抛出它,这样你就可以把它捕获到你想要处理它的位置。

答案 2 :(得分:1)

没有一般的理由避免在do / while循环中调用的函数中使用try / catch。

根据您在循环中实际执行的操作,您可以选择在循环内捕获异常,并在返回错误条件时退出,或者将整个while循环包装在try / catch块中。

您应根据代码的例外含义决定如何在任何特定情况下执行此操作:

  • 可以从中恢复异常吗?
  • 响应抛出异常需要采取什么行动?
  • 抛出并处理特定异常后,您的程序应处于什么状态?

在您的示例中,即使bar()生成错误,也会执行foo()。这可能是也可能不是你想要的。捕获循环外的异常将不允许此选项。 此外,如果bar()随后返回falsefoo()返回true,则循环不会终止 - 这可能是一个错误。捕获循环外的任何异常将意味着循环将在错误点终止。同样,根据您的申请,这可能是也可能不合适。

此外,可能需要以不同方式处理不同的异常。重要的是,如果您捕获基本异常类型,而不是更具体的派生类型,则您将无法执行此操作。捕获更具体的异常(包括自定义异常)将对您有所帮助:

  • 确保你不是 意外地吞咽意外 你不想抓住的例外情况。
  • 有多个不同的错误 由同一个catch处理的场景 阻止(通过抛出相同的自定义 每个错误的异常 场景)。