何时重新抛出异常,何时返回FALSE?

时间:2008-12-03 13:19:20

标签: language-agnostic exception

我正在为第三方函数库开发一个包装器,它与一些特殊硬件连接。基本上,我想用连接和断开方法将dll函数(bool Connect()void Disconnect()等)封装在MyHardwareObject中。

来自dll的Connect函数可能会抛出一些特定的异常,例如当硬件不存在时。对于应用程序,有关connect方法失败原因的信息被认为是不重要的,因此不需要包含在异常中的附加信息。

处理这些异常的最佳方法是什么,返回false,或者在此处未处理异常并将其捕获到否则会处理connect方法返回false的事实? / p>

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}

相反
 bool MyHardwareObject.Connect() 
{
    ThirdPartyLibrary.Connect();
    return true;
}

(或者在第二种情况下更好void MyHardwareObject.Connect(),因为我们要么返回true,要么抛出异常?)

或者你还会做什么?最重要的是:为什么?

7 个答案:

答案 0 :(得分:9)

在我看来,第一种情况肯定比第二种情况要好。您想要您的硬件库以一种您的用户无需确切知道其中的内容的方式包装第三方库。
如果您在错误处理中需要更多详细信息,除了true或false之外,您可以考虑重新抛出自己的异常,将异常从第三方库转换为与您自己的代码更一致的内容。

答案 1 :(得分:7)

在例外和返回代码之间明智地选择是非常困难的。这取决于很多事情,以及如何在代码库的其余部分处理错误将是最重要的 - 保持一致。

最近,我更倾向于“如果它不值得,不要抛出异常”。我们的异常做了很多工作:它们记录东西,它们创建堆栈跟踪等。如果我只想将字符串转换为整数,如果输入字符串格式错误则抛出异常可能不值得。另一方面,如果无法使用正确的数据构造我在系统中根本不想要的对象,那么它们的构造函数会抛出异常。

如果代码库的其余部分没有给出任何关于如何操作的提示,我喜欢这样的经验法则:想象一下,抛出异常会让你的计算机发出响亮的哔哔声。只要你能忍受它,投掷就可以了。

答案 2 :(得分:6)

我会传递例外情况。如果不这样做,您将掩盖可能在以后有用的重要信息。我知道您现在没有使用它,但如果您决定将来根据错误类型以不同方式处理恢复,该怎么办?此时,您必须撤消已编写的所有代码以屏蔽异常。虽然我不同意@MadKeithV使其成为真/假,但我认为他有一个关于在你自己的异常中包装异常的观点,它可能会为你的应用程序提供更好的语义。

答案 3 :(得分:6)

阅读本文:http://www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html

简而言之:

调用者是否对返回值有用?它可以恢复或是世界末日的错误吗?如果这只是一个小问题,请使用返回码。如果各种状态经常发生(50%的失败时间,50%失效),请使用返回码,因为调用者无论如何都必须处理这种情况,并且异常无效。

你想传递更多信息(比如设置第三方的东西,以便有人有机会调试以后发生的事情)?使用例外。

答案 4 :(得分:3)

我会建议第二个。调用者负责处理异常并根据异常采取正确的操作。 假设Connect抛出AccountExpiredException,NetworkUnavailableException,InvalidCredentialsException等(这些只是示例)我可以提示用户“修复”异常(联系管理员,检查网络电缆,检查用户名/密码)。 我甚至建议删除返回值(指标)并使其无效。看看SqlConnection Open方法 - 它就像你连接 - 它没有返回值而是抛出异常。 像这样吞下例外

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}

恕我直言不是一个好主意。我建议你实现IDisposable模式。 我的2美分。

答案 5 :(得分:1)

程序运行是否需要第三方库,或者只是添加一些额外的功能,虽然很好,但不是必需的?此外,硬件可能会失败。最后,硬件可以为您提供多少种类型的异常?

如果您的程序实际上不需要运行库,那么您肯定需要在某个时刻捕获异常,但您可能希望在更高的位置执行此操作。

如果硬件可以抛出多种类型的异常,那么您更有可能想要重新抛出异常,因为简单地返回一个值会导致您丢失一些信息。但是,您确实说过客户端不关心为什么它失败了,只是确实如此,所以这应该不是问题。

最后,如果硬件故障很常见,那么您可能更愿意返回错误代码(在这种情况下为假),而不是失败是常见的。

我认为在你的情况下,它真的归结为第一个问题。如果您真的不需要这个库,则返回false并确保非常清楚地记录操作可能因完全任意原因而失败,并且需要检查返回值。如果您需要它可以工作,请重新抛出异常并让它传播到您可以优雅地退出的任何地方。

答案 6 :(得分:0)

我认为异常机制背后的原理是“快速失败”理论。

您希望客户的应用程序“快速失败”是否连接失败? 如果是,只需抛弃异常或将异常封装在您自己的应用程序例外中。

如果客户端忽略该异常,他的应用程序将停止。

返回false表示客户端可能会忽略该问题,他的应用程序可能仍会崩溃,但“稍后”...