2011-06-03 59 views
4

这更像是一个概念性问题。使用Try/catch和Do /虽然

它是aceptable /良好的编程混合做/同时用try/catch语句的循环?

例如:

<?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: 像其他人指出的那样,似乎是正确的做法是适当提高/处理异常。 由于大家似乎都同意这一点,我不知道谁给予“正确答案”打勾。 我会等几天,如果没有问题的话,可以给予更多选票。

+1

对不起,脱离主题,但在回路中“返回”不是一个好的选择。 – 2011-06-03 04:21:54

+0

不!如果建设性的话,所有的投入都很好。顺便说一句,为什么从循环返回不好?转到会更好吗? – Tivie 2011-06-03 04:45:18

+1

在你上面的例子中,它永远不会检查while()的条件,因为在do {}中之前都返回了一切。 – 2011-06-03 04:50:53

回答

3

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

但是您提供的示例在do/while等问题上的问题较少,并且在try/catch块中吞咽异常。

捕获基本的异常类型并吞服它在任何语言,PHP或其他语言中都是不好的做法。最好只捕获特定的异常类型,并让其余部分通过catch块。例如,如果你正在访问一个文件,并且发现了异常(如果PHP中有这样的事情),那就没问题了。

但是,如果你捕捉到所有的异常类型,那么你将会看到像OutOfMemoryException这样的东西。如果你正确地处理了它,并且确保它不会再次抛出,这将会很好。但就你而言,你可能不是“为那件事情做正确的事情”,所以你应该让它落空。

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

如果你吃了这个例外,你基本上就会抛弃那些用于调试的最有用的数据。

东西,让这个不太真实:

  • 有时顶级网页代码,你会想要赶上例外,记录它,然后吞下它,因此用户不会看到它(但回报从函数,所以你不要在一个错误的状态下执行更多的代码)。这使得用户看不到有关代码的信息(堆栈跟踪)。
  • 如果您正在进行异常处理的语言对异常的支持不足,并且没有派生异常类型。我对PHP没有太多了解,所以在这种语言中可能会也可能不会。
1

如果要吞下例外,只是报告故障,那么这是好的。你必须做类似

$failure &= bar(); 

虽然,否则你将失去foo()的失败条件。

如果您希望能够对调用堆栈进一步采取行动,那么最好让它独立,或者至少重新抛出它,以便您可以将其捕获到要处理它的位置。

+0

是的,我简化了代码并创建了一些没有任何意义的东西= P – Tivie 2011-06-03 04:18:39

1

没有通用的理由,以避免使用try /称为里面做的职责范围内赶上/ while循环。

取决于你实际上是在做什么,你有醒目的循环内的异常的选择内循环,并退出上的错误状态返回,或包裹整个while循环在try/catch块。

你应该决定如何根据什么异常意味着你的代码做任何特殊情况:

  • 可以例外地从收回?
  • 需要采取什么行动来应对抛出的异常?
  • 在抛出和处理特定异常之后,您的程序应保留在什么状态?

在您的示例中,即使foo()生成错误,也会执行bar()。这可能是也可能不是你想要的。在循环外捕获异常不会允许此选项。 此外,如果foo()随后返回true,则bar()返回false时,循环将不会终止 - 这可能是一个错误。捕捉循环外的任何异常意味着循环将在错误点处终止。再次,这可能会或可能不会取决于您的应用程序。

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

  • 确保你没有 误吞意外 例外,你并不想赶上。
  • 具有由相同的捕获 块处理多个不同的错误 场景(由投掷相同的自定义 例外为每个这些错误 场景)。
+0

是的,你可能是对的。该代码基于机器人在地板上沿着一条线并且不断向服务器提供反馈的RL情况。服务器处理很多信息,例如机器人的绝对位置,相对位置,到目标的距离等等,但仅用于过程检查。它给机器人的响应实际上是0或1,即继续或停止。因此,过程中抛出的任何异常都意味着数据不可行和/或不可恢复,并且过程必须重新开始,也就是说,机器人必须“重新思考”他在哪里以及如何达到目标。 – Tivie 2011-06-03 04:37:47

+0

这段代码是指文件上传和流式传输。如果由于某种原因切断了机器人的无线连接,则文件上传会中断,导致文件不完整/被破坏。由于数据是即时创建的,无法重新创建,所以我们不能要求“重试”(而且我们也不想要P =),所以我们无法从错误中恢复。机器人必须停下来,重新思考并要求允许再次移动。 – Tivie 2011-06-03 04:51:58

+1

是的,但请注意,由于您正在捕获基本Exception类型(而不是派生类型),因此您可能还会捕获整个过程无法从中恢复的异常(而不仅仅是当前阶段或迭代)。这就是为什么它总是能够更好地捕捉你可以优雅地处理的特定异常,并让其他人更上一层楼。我对我的答案做了一个小小的修改,强调了这一点。 – Ergwun 2011-06-03 06:29:15