You*_*nse 7 php exception-handling goto try-catch
最近有很多人指责我只提一个字 - "goto".
这让我很奇怪,为什么它被认为是一个令人讨厌的词.
我知道之前有几个关于这个主题的讨论,但它并没有让我信服 - 答案只是说"它很糟糕"甚至没有尝试解释,有些带来理由,与PHP,IMO等脚本语言无关.
无论如何,我将问一个非常特别的问题:
让我们进行比较goto和throw陈述.
在我看来,两者都做同样的事情:避免基于某些条件执行某些代码.
如果是这样 - throw与goto有同样的缺点吗?(如果有的话)?
如果不是 - 那就是惠特.
任何经验丰富的人,谁能说出以下两个代码片段的代码结构之间的基本概念差异?
关于这些非常的代码片段,不是"在理论上"或"一般"或"这里是一个不错的XKCD漫画!".
为什么第一个被认为是辉煌的而后一个被认为是最致命的罪?
#$a=1;
#$b=2;
/* SNIPPET #1 */
try {
if (!isset($a)) {
throw new Exception('$a is not set');
}
if (!isset($b)) {
throw new Exception('$b is not set');
}
echo '$a + $b = '.($a + $b)."<br>\n";
} catch (Exception $e) {
echo 'Caught exception: ', $e->getMessage(), "<br>\n";
}
/* SNIPPET #2 */
if (!isset($a)) {
$message = '$a is not set';
goto end;
}
if (!isset($b)) {
$message = '$b is not set';
goto end;
}
echo '$a + $b = '.($a + $b)."<br>\n";
end:
if (!empty($message)) {
echo 'Caught exception: ', $message, "<br>\n";
}
Run Code Online (Sandbox Code Playgroud)
请注意,我知道投掷在制作意大利面条时更加强大和灵活.它对我来说并不是主要的区别.这是使用问题,而不是概念.
编辑
很多人都告诉我,第一个例子应该是新用的.
原因:异常应仅用于处理错误,而不是用于实现业务逻辑.
它看起来很明智.
因此,停止无用的代码执行的唯一方法是转到(更不用说一些替代品,例如while,return等,这些是同样但更难实现的)?
goto hard codes the execution path into the code. Exceptions on the other hand allow the execution path to be determined at runtime.
例如,假设您有一个数据库类,它会在出错时引发异常。除了例外,您可以捕获该错误,并在呈现错误页面之前执行其他操作(例如清理分配的资源,或者如果您使用非事务性数据库类型,则“回滚”先前的更改。如果您使用 goto,您将不会没有机会这样做,因为 goto 会呈现错误页面。
请记住,保持代码的可重用性和灵活性。 goto是两者的对立面……
在您的示例中,实际上没有区别,因为您正在检查错误条件并引发异常或goto在条件失败时进行调用.您的示例可以重新编码,以消除对任一构造的需要.
例外情形是有用的是你要拨打的可能有错误状态,但无法处理自己为以下伪代码说明方法:
try
{
$c = add($a, $b);
echo '$a + $b = '.($c)."<br>\n";
}
catch (Exception $e)
{
echo 'Caught exception: ', $e->getMessage(), "<br>\n";
}
Run Code Online (Sandbox Code Playgroud)
该add方法执行错误检查:
if (!isset($a))
{
throw new Exception('$a is not set');
}
if (!isset($b))
{
throw new Exception('$b is not set');
}
Run Code Online (Sandbox Code Playgroud)
然后返回添加的结果.
这意味着您的主代码流显示了程序的预期路径.
由于还没有人对这个问题提供 OP 认为可以接受的答案,我将投身其中。
…以下两个代码片段的代码结构之间的根本概念差异是什么?
您提供的两个代码片段之间根本没有概念上的区别。在这两种情况下都会测试条件,如果满足,则会将消息抛出到程序的另一部分进行处理。
为什么第一个被认为是辉煌的,而后一个被认为是最致命的罪恶?
感谢斯拉普内尔上校为下面的咆哮打开了大门。
<咆哮>
每个编程结构都有被滥用的可能性。这种教条式的迫害goto让我想起了对PHP的类似抨击。PHP 会导致不良的编程习惯。比较:Goto 导致意大利面条式代码。
简而言之:goto是“邪恶的”,因为 Edsger Dijkstra 这么说,而 Niklaus Wirth 也对此表示认可。;-p
</咆哮>
为了您的阅读乐趣:http://en.wikipedia.org/wiki/Goto
对 GOTO 最著名的批评可能是 Edsger Dijkstra 1968 年写的一封信,名为《Go To 声明被认为是有害的》。Dijkstra 在那封信中指出,应该从高级语言中废除不受限制的 GOTO 语句,因为它们使分析和验证程序(特别是涉及循环的程序)正确性的任务变得复杂。Donald Knuth 的带有 go to 语句的结构化编程提出了另一种观点,该观点分析了许多常见的编程任务,并发现在其中一些任务中 GOTO 是最适合使用的语言结构。
它接着说,
一些程序员,例如 Linux 内核设计师和编码员 Linus Torvalds 或软件工程师和书籍作者 Steve McConnell 也反对 Dijkstra 的观点,认为 GOTO 可以成为一种有用的语言功能,可以提高程序速度、大小和代码清晰度,但前提是由相对明智的程序员以合理的方式使用。
也就是说,自 Commodore BASIC 以来,我个人还没有发现 GOTO 的实际用途,但这既不存在也不存在。:-)