Language agnostic 何时重新引发异常,何时返回FALSE?

Language agnostic 何时重新引发异常,何时返回FALSE?,language-agnostic,exception,Language Agnostic,Exception,我正在为第三方函数库开发一个包装器,它与一些特殊的硬件接口。因此,基本上,我想用连接和断开方法将dll函数(boolconnect(),voiddisconnect()等)封装在MyHardwareObject中 dll中的Connect函数可以引发一些特定的异常,例如,当硬件不存在时。对于应用程序,有关连接方法失败原因的信息被认为不重要,因此不需要异常中包含的附加信息 处理这些异常的最佳方法是什么,返回false,或者在此处不处理异常,并在处理connect方法返回false这一事实的级别上捕

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

dll中的Connect函数可以引发一些特定的异常,例如,当硬件不存在时。对于应用程序,有关连接方法失败原因的信息被认为不重要,因此不需要异常中包含的附加信息

处理这些异常的最佳方法是什么,返回
false
,或者在此处不处理异常,并在处理connect方法返回
false
这一事实的级别上捕获它

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

 bool MyHardwareObject.Connect() 
{
    ThirdPartyLibrary.Connect();
    return true;
}
(或者在第二种情况下,最好
void MyHardwareObject.Connect()
,因为我们要么返回true,要么抛出异常?)


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

在我看来,第一种情况肯定比第二种好。您希望您的硬件库以一种用户不必确切知道第三方库中包含哪些内容的方式围绕第三方库进行封装。

如果您在错误处理中需要更多的细节,除了true或false,您可以考虑重新抛出自己的异常,将异常从第三方库转换为与您自己的代码更一致的内容。

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

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


如果代码库的其余部分没有给你任何提示,我喜欢这个经验法则:假设抛出一个异常会让你的计算机发出一声响亮的哔哔声。只要你能忍受,抛出就可以了。

我会传递例外情况。如果你不这样做,你就掩盖了可能在以后有用的潜在重要信息。我知道您现在没有使用它,但是如果您决定在将来根据错误类型以不同的方式处理恢复,该怎么办呢。在这一点上,您将不得不撤消您为掩盖异常而编写的所有代码。虽然我不同意@MadKeithV将其设置为真/假,但我认为他有一个观点,那就是将异常包装在您自己的异常中,这可能对您的应用程序具有更好的语义。

我相信异常机制背后的原理是“快速失效”理论

如果连接不成功,是否希望客户端的应用程序“快速失败”?
如果是,只需抛出异常或将异常封装在自己的应用程序异常中

如果客户端忽略该异常,则其应用程序将停止


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

您的程序运行需要这个第三方库,还是只是添加了一点额外的功能,虽然很好,但并不需要这些功能?此外,硬件可能会出现故障。最后,硬件可以向您抛出多少类型的异常

如果程序运行实际上不需要该库,那么您肯定需要在某个时候捕获异常,但您可能希望在更高的级别上执行

如果硬件可以抛出多种类型的异常,那么您很可能希望重新抛出异常,因为简单地返回一个值将导致您丢失一些信息。但是,您确实说过客户不关心它失败的原因,只是它在乎,所以这不应该是一个问题

最后,如果硬件故障是常见的,那么与常见故障相比,您可能更希望返回错误代码(在本例中为false)


我认为,就你的情况而言,这实际上可以归结为第一个问题。如果您真的不需要这个库,请返回false,并确保非常清楚地记录了操作可能由于完全任意的原因而失败,并且他们需要检查返回值。如果您需要它工作,请重新显示异常,并让它传播到您可以正常退出的任何位置。

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

 bool MyHardwareObject.Connect()
{
    try
    {
        ThirdPartyLibrary.Connect();
    }
    catch (SomeException)
    {
        return false;
    }
    return true;
}
这不是个好主意。我建议您实现IDisposable模式。 只要我的2美分。

读一下:

简言之:

调用者对返回值有任何用处吗?它能恢复吗?还是一个错误就是世界末日?如果只是一个小问题,请使用返回码。如果各种状态发生的频率相同(50%的情况下失败,50%的情况下有效),请使用返回码,因为调用方无论如何都必须处理这种情况,而异常也无济于事

你想放弃这个广告吗