代码之家  ›  专栏  ›  技术社区  ›  Ross

例外情况:这是一种好的做法吗?

  •  1
  • Ross  · 技术社区  · 17 年前

    这是用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异常只是一个错误页面编译器。

    我可能只是迂腐,但你认为这是报告错误的好方法吗?如果是这样,你能建议一种更好的写作方式吗?

    谢谢

    7 回复  |  直到 10 年前
        1
  •  9
  •   Jeremy Privett    17 年前

    您正在使用Exceptions进行页面逻辑,我个人认为这不是一件好事。异常应用于在发生不良或意外情况时发出信号,而不是控制错误页面的输出。如果您想基于Exceptions生成错误页面,请考虑使用 set_exception_handler 。任何未捕获的异常都会通过您指定的任何回调方法运行。请记住,这并不能阻止异常的“危险性”。在通过回调传递异常后,在任何未捕获的异常之后,执行将像正常情况一样停止。

        2
  •  2
  •   oglester    17 年前

    我想你最好不要筑巢。如果你期望有多个异常类型,那么就有多个捕获。

    try{
      Something();
    }
    catch( SpecificException se )
    {blah();}
    catch( AnotherException ae )
    {blah();}
    
        3
  •  2
  •   Steve Jessop    17 年前

    理想的情况是在能够处理异常的级别捕获异常。不是之前(浪费时间),也不是之后(失去上下文)。

    因此,如果$tpl和ERR_NOT_FOUND是仅在新的DM_Issue调用附近“已知”的信息,例如,因为您在其他地方创建DM_Issue并希望使用ERR_SOMETHING_ELSE,或者因为$tpl的值不同,那么您在正确的地方捕获了第一个异常。

    如何从那个地方走向死亡是另一个问题。另一种选择就是死在那里。但如果你这样做,那么在错误发生后但退出之前,干预代码就没有机会做任何事情(例如以某种方式清除某些内容或修改错误页面)。有明确的控制流也很好。所以我觉得你很好。

    我假设你的示例不是一个完整的应用程序——如果是的话,那么它可能是不必要的冗长,你可能会在DM_Exception catch子句中死亡。但对于一款真正的应用程序,我赞成这样一个原则,即不只是死在荒无人烟的地方。

        4
  •  0
  •   sgibbons    17 年前

    根据您的需要,这可能很好,但我通常对捕获异常、将消息包装在一个新的异常中并重新运行它非常犹豫,因为您在包装异常中丢失了原始异常的堆栈跟踪(以及可能的其他)信息。如果你是 当然 如果在检查包装异常时不需要这些信息,那么可能没问题。

        5
  •  0
  •   Anheledir    17 年前

    我对PHP不太确定,但在C#中,你可以有多个catch块,所以不需要嵌套的try/catch组合。

    一般来说,我认为用try/catch/finally处理错误总是常识,也用于“仅”显示错误页面。这是一种处理错误和避免崩溃时出现奇怪行为的干净方法。

        6
  •  0
  •   Aeon    17 年前

    我不会对未找到的问题抛出异常——这是应用程序的有效状态,您不需要堆栈跟踪来显示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.
    }
    
        7
  •  0
  •   user19302 user19302    17 年前

    只有在发生潜在的站点破坏事件时才应使用例外情况,例如数据库查询执行不正确或配置错误。一个很好的例子是,Apache进程无法写入缓存或日志目录。

    这里的想法是,作为开发人员,您可以停止可能破坏整个站点的代码,以便在部署之前修复它们。它们也是健全性检查,以确保如果环境发生变化(即有人更改了缓存文件夹的权限或更改了数据库方案),站点会在损坏任何东西之前停止。

    所以,没有;嵌套的捕获处理程序不是一个好主意。在我的页面中,我的index.php文件尝试包装了它的代码。..缓存块-如果发生了什么不好的事情,它会检查它是否在生产中;或者给我发电子邮件并显示一个通用错误页面,或者在屏幕上显示错误。

    记住:PHP不是C#。C#(ASP.net除外(呵呵,没有双关语:p))用于包含状态的应用程序,而PHP是一种无状态脚本语言。