提问人:Ross 提问时间:9/20/2008 最后编辑:John SlegersRoss 更新时间:1/12/2016 访问量:1504
例外情况:这是一种好的做法吗?
Exceptions: Is this a good practice?
问:
这是用PHP编写的,但它确实与语言无关。
try
{
try
{
$issue = new DM_Issue($core->db->escape_string($_GET['issue']));
}
catch(DM_Exception $e)
{
throw new Error_Page($tpl, ERR_NOT_FOUND, $e->getMessage());
}
}
catch(Error_Page $e)
{
die($e);
}
嵌套的 try, catch 块是一个值得遵循的好做法吗?仅对于错误页面来说,这似乎有点笨重 - 但是,如果发生错误,我的问题数据管理器会抛出异常,我认为这是一种很好的错误检测方法。
Error_Page异常只是一个错误页编译器。
我可能只是迂腐,但你认为这是报告错误的好方法吗,如果是这样,你能建议一个更好的方法来写这个吗?
谢谢
答:
我想你最好不要筑巢。如果需要多种异常类型,请具有多个捕获。
try{
Something();
}
catch( SpecificException se )
{blah();}
catch( AnotherException ae )
{blah();}
评论
根据您的需要,这可能很好,但我通常非常犹豫是否要捕获异常,将消息包装在新的异常中,然后重新抛出它,因为您丢失了包装异常中原始异常的堆栈跟踪(以及可能的其他)信息。如果您确定在检查包装异常时不需要该信息,那么它可能没问题。
评论
您正在将 Exceptions 用于页面逻辑,我个人认为这不是一件好事。异常应用于在发生不良或意外情况时发出信号,而不是控制错误页面的输出。如果要基于异常生成错误页面,请考虑使用 set_exception_handler。任何未捕获的异常都将通过您指定的任何回调方法运行。请记住,这并不能阻止异常的“致命性”。通过回调传递异常后,执行将像正常一样在任何未捕获的异常后停止。
我不确定 PHP,但在例如 C# 中,您可以有多个 catch-Block,因此不需要嵌套的 try/catch-combinations。
一般来说,我相信使用 try/catch/finally 进行错误处理始终是常识性的,也用于显示“仅”错误页面。这是一种处理错误和避免崩溃时出现奇怪行为的干净方法。
评论
理想的情况是在可以处理异常的级别捕获异常。不是之前(浪费时间),也不是之后(你失去上下文)。
因此,如果 $tpl 和 ERR_NOT_FOUND 是仅在新DM_Issue调用附近“已知”的信息,例如,因为您在其他地方创建了DM_Issue并希望ERR_SOMETHING_ELSE,或者因为$tpl的值不同,那么您将在正确的位置捕获第一个异常。
如何从那个地方到死亡是另一个问题。另一种选择是死在那里。但是,如果你这样做,那么干预代码就没有机会在错误发生后但在退出之前做任何事情(例如以某种方式清除某些内容或修改错误页面)。拥有明确的控制流也很好。所以我觉得你很好。
我假设您的示例不是一个完整的应用程序 - 如果是,那么它可能是不必要的冗长,您可能会死在DM_Exception捕获子句中。但对于一个真正的应用程序,我赞成不只是在茫茫人海中死去的原则。
我不会在未找到问题时抛出异常 - 这是应用程序的有效状态,您不需要堆栈跟踪来显示 404。
您需要捕获的是意外的失败,例如 sql 错误 - 这时异常处理就派上用场了。我会将您的代码更改为更像这样:
try {
$issue = DM_Issue::fetch($core->db->escape_string($_GET['issue']));
}
catch (SQLException $e) {
log_error('SQL Error: DM_Issue::fetch()', $e->get_message());
}
catch (Exception $e) {
log_error('Exception: DM_Issue::fetch()', $e->get_message());
}
if(!$issue) {
display_error_page($tpl, ERR_NOT_FOUND);
}
else
{
// ... do stuff with $issue object.
}
仅当存在潜在的站点中断事件(例如数据库查询未正确执行或某些内容配置错误)时,才应使用异常。一个很好的例子是,Apache 进程无法写入缓存或日志目录。
这里的想法是,例外情况是针对开发人员的,用于停止可能破坏整个站点的代码,以便您可以在部署之前修复它们。它们也是健全性检查,以确保如果环境发生变化(即有人更改缓存文件夹的权限或更改数据库方案),则站点在损坏任何内容之前停止。
所以,不;嵌套捕获处理程序不是一个好主意。在我的页面中,我的 index.php 文件将其代码包装在尝试中...缓存块 - 如果发生不好的事情,它会检查它是否在生产中;然后给我发电子邮件并显示一般错误页面,或者直接在屏幕上显示错误。
请记住:PHP 不是 C#。C# 是(除了 ASP.net 的双关语(呵呵,没有双关语的:p))用于包含状态的应用程序 - 而 PHP 是一种无状态脚本语言。
评论