[英]When to rethrow an exception, when to return FALSE?
我正在为第三方函数库开发一个包装器,它与一些特殊硬件连接。 所以基本上,我想用连接和断开方法封装MyHardwareObject中的dll函数( bool Connect()
, void Disconnect()
等)。
来自dll的Connect函数可以抛出一些特定的异常,例如当硬件不存在时。 对于应用程序,有关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()
更好地void MyHardwareObject.Connect()
,因为我们要么返回true,要么抛出异常?)
或者你还会做什么? 最重要的是:为什么?
在我看来,第一种情况肯定比第二种情况好。 您希望您的硬件库以一种您的用户无需确切知道其中的内容的方式环绕第三方库。
如果您在错误处理中需要更多详细信息,除了true或false之外,您可以考虑重新抛出自己的异常,将异常从第三方库转换为与您自己的代码更一致的内容。
在例外和返回代码之间明智地选择是非常困难的。 这取决于很多事情,以及如何在代码库的其余部分处理错误将是最重要的 - 保持一致。
最近,我更倾向于“如果它不值得,就不要抛出异常”。 我们的异常做了很多工作:它们记录东西,它们创建堆栈跟踪等。如果我只想将字符串转换为整数,如果输入字符串格式错误则抛出异常可能不值得。 另一方面,如果无法使用正确的数据构造,我在系统中根本不需要这些对象,在这种情况下,它们的构造函数会抛出异常。
如果代码库的其余部分没有给你任何关于如何做的提示,我喜欢这个经验法则:想象一下,抛出异常会让你的计算机发出响亮的哔哔声。 只要你忍受它,投掷是好的。
我会传递例外情况。 如果不这样做,您将掩盖可能在以后有用的重要信息。 我知道您现在没有使用它,但如果您决定将来根据错误类型以不同方式处理恢复,该怎么办? 此时,您必须撤消已编写的所有代码以屏蔽异常。 虽然我不同意@MadKeithV使其成为真/假,但我认为他有一个重点在你自己的异常中包装异常,它可能会为你的应用程序提供更好的语义。
请阅读: http : //www.onjava.com/pub/a/onjava/2003/11/19/exceptions.html
简而言之:
调用者是否对返回值有用? 它可以恢复或是世界末日的错误吗? 如果这只是一个小问题,请使用返回码。 如果各种状态经常发生(50%的失败时间,50%失效),请使用返回码,因为调用者无论如何都必须处理这种情况,并且异常无济于事。
你想传递更多的信息(比如设置第三方的东西,所以有人有机会调试后来发生的事情)? 使用例外。
我建议第二个。 调用者负责处理异常并根据异常采取正确的操作。 假设Connect抛出AccountExpiredException,NetworkUnavailableException,InvalidCredentialsException等(这些只是示例)我可以提示用户“修复”异常(联系管理员,检查网络电缆,检查用户名/密码)。 我甚至建议删除返回值(指标)并使其无效。 看看SqlConnection Open方法 - 它就像你连接 - 它没有返回值而是抛出异常。 像这样吞下这个例外
bool MyHardwareObject.Connect()
{
try
{
ThirdPartyLibrary.Connect();
}
catch (SomeException)
{
return false;
}
return true;
}
恕我直言不是一个好主意。 我建议你实现IDisposable模式。 只需2美分。
这个程序是否需要运行第三方库,或者它只是添加了一些额外的功能,虽然很好,但不是必需的? 此外,硬件可能会失败。 最后,硬件可以为您提供多少种类型的异常?
如果程序实际上并不需要运行库,那么您肯定需要在某个时刻捕获异常,但您可能希望在更高的位置执行此操作。
如果硬件可以抛出多种类型的异常,那么您更有可能想要重新抛出异常,因为只返回一个值会导致丢失一些信息。 但是,你确实说过客户端不关心它失败的原因 ,只是确实如此,所以这应该不是问题。
最后,如果硬件故障很常见,那么您可能更愿意返回错误代码(在这种情况下为假),而不是失败是常见的。
我认为在你的情况下,它真的归结为第一个问题。 如果您真的不需要这个库,则返回false并确保非常清楚地记录操作可能因完全任意原因而失败,并且需要检查返回值。 如果您需要它可以工作,请重新抛出异常并让它传播到您可以优雅地退出的任何地方。
我认为异常机制背后的原理是“ 快速失败 ”理论。
您是否希望客户端的应用程序“快速失败”是否连接失败?
如果是,只需抛弃异常或将异常封装在您自己的应用程序例外中。
如果客户端忽略该异常,他的应用程序将停止。
返回false意味着客户端可能会忽略该问题,他的应用程序可能仍会崩溃,但“稍后”......
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.