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

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

  •  15
  • Treb  · 技术社区  · 16 年前

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

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

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

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

    与...相反

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

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

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

    7 回复  |  直到 16 年前
        1
  •  7
  •   Carl Seleborg    16 年前

    在我看来,第一种情况肯定比第二种情况好。你 您的硬件库可以以一种用户不必确切知道其中包含什么的方式围绕第三方库。
    如果除了true或false之外,您还需要更多错误处理的细节,可以考虑重新生成自己的异常,将第三方库中的异常转换为与您自己的代码更一致的异常。

        2
  •  9
  •   Joris Timmermans    16 年前

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

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

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

        3
  •  6
  •   tvanfosson    16 年前

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

        4
  •  6
  •   Aaron Digulla    16 年前

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

    简言之:

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

    你想不想提供其他信息(比如第三方东西的设置,这样别人就有机会调试后来发生的事情)?使用例外。

        5
  •  3
  •   Petar Petrov    16 年前

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

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

    依我之见,这不是个好主意。我建议您实现IDisposable模式。 只有我的2美分。

        6
  •  1
  •   James    16 年前

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

    如果你的程序运行实际上不需要这个库,你当然需要在某个时候捕捉异常,但你可能想在更高的层次上捕捉。

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

    最后,如果硬件故障很常见,与故障很常见的情况相比,您可能更希望返回错误代码(在这种情况下为false)。

    我认为就你而言,这真的归结为第一个问题。如果你真的不需要这个库,返回false,并确保有非常明确的记录,说明操作可能会因完全任意的原因而失败,并且他们需要检查返回值。如果你需要它工作,重新抛出异常,让它传播到你可以优雅退出的任何地方。

        7
  •  0
  •   VonC    16 年前

    我认为例外机制背后的原则是“ 快速失败 “理论。

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

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

    返回false意味着客户端可能会忽略问题,他的应用程序可能仍然会崩溃,但“稍后”会崩溃。..

    推荐文章