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

何时重新引发异常,何时返回false?

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

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

    来自dll的connect函数可以抛出一些特定的异常,例如,当硬件不存在时。对于应用程序,有关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 年前

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

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

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

        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%的工作时间),则使用返回代码,因为调用方无论如何都必须处理这种情况,而异常没有帮助。

    是否要传递附加信息(如第三方thingy的设置,以便有人有机会调试以后发生的事情)?使用异常。

        5
  •  3
  •   Petar Petrov    16 年前

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

     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意味着客户端可能忽略问题,他的应用程序可能仍然崩溃,但“稍后”…