C# Java或C中异常管理的最佳实践#

C# Java或C中异常管理的最佳实践#,c#,java,exception,error-handling,C#,Java,Exception,Error Handling,我一直在决定如何处理应用程序中的异常 如果我的异常问题来自1)通过远程服务访问数据,或2)反序列化JSON对象,那么我的问题就更大了。不幸的是,我不能保证这两项任务都能成功(切断网络连接,格式错误的JSON对象超出我的控制) 因此,如果遇到异常,我只需在函数中捕获它,并向调用方返回FALSE。我的逻辑是,调用方真正关心的是任务是否成功,而不是任务为什么不成功 下面是一些典型方法的示例代码(JAVA) 我认为这种方法很好,但我真的很想知道管理异常的最佳实践是什么(我真的应该在调用堆栈中一直冒泡异常

我一直在决定如何处理应用程序中的异常

如果我的异常问题来自1)通过远程服务访问数据,或2)反序列化JSON对象,那么我的问题就更大了。不幸的是,我不能保证这两项任务都能成功(切断网络连接,格式错误的JSON对象超出我的控制)

因此,如果遇到异常,我只需在函数中捕获它,并向调用方返回FALSE。我的逻辑是,调用方真正关心的是任务是否成功,而不是任务为什么不成功

下面是一些典型方法的示例代码(JAVA)

我认为这种方法很好,但我真的很想知道管理异常的最佳实践是什么(我真的应该在调用堆栈中一直冒泡异常吗?)

关键问题摘要:

  • 是否可以只捕获异常,但不将其冒泡或正式通知系统(通过日志或通知用户)
  • 对于不会导致一切都需要try/catch块的异常,有哪些最佳实践
  • 跟进/编辑

    感谢所有反馈,在异常管理在线上找到了一些优秀的来源:

    • (文章现在指向archive.org副本)
    异常管理似乎是根据上下文而变化的事情之一。但最重要的是,在如何管理系统内的异常方面应该保持一致

    此外,还要注意通过过度的try/catch或不尊重异常(异常是警告系统,还有什么需要警告的?)

    此外,这是一个很好的选择评论

    我倾向于同意Anders Hejlsberg和你的观点,大多数来电者 注意手术是否成功

    从这一评论中,它提出了一些在处理异常时需要考虑的问题:

    • 抛出此异常的目的是什么
    • 处理它有什么意义
    • 调用方是否真的关心异常,还是只关心调用是否成功
    • 强制调用方管理潜在异常是否合适
    • 您是否尊重该语言的IDOM?
      • 您真的需要返回一个类似布尔值的成功标志吗?返回布尔(或int)更像是一种C思维方式,而不是Java思维方式(在Java中,您只需处理异常)
      • 遵循与以下语言关联的错误管理构造:)

      • 我觉得奇怪的是,您想要捕获异常并将其转换为错误代码。当Java和C#都默认使用异常时,为什么您认为调用者更喜欢错误代码而不是异常

        关于你的问题:

      • 您应该只捕获实际可以处理的异常。只是 在大多数情况下,捕获异常不是正确的做法。 存在一些例外情况(例如,日志记录和编组例外情况) 线程之间),但即使在这些情况下,您通常也应该 重新显示异常
      • 您的文档中绝对不应该有很多try/catch语句 代码。同样,这个想法是只捕获您可以处理的异常。 您可以包含一个最顶层的异常处理程序来处理任何未处理的异常 将异常转换为对最终用户有些有用的内容,但 否则,您不应该尝试捕获中的每个异常 每一个可能的地方

      • 这取决于应用和情况。如果您正在构建一个库组件,您应该弹出异常,尽管它们应该被包装为与您的组件相关。例如,如果您正在构建一个Xml数据库,假设您正在使用文件系统存储数据,并且您正在使用文件系统权限保护数据。您不希望冒泡出FileIOAccessDenied异常,因为这会泄露您的实现。相反,您将包装异常并抛出AccessDenied错误。如果将组件分发给第三方,则尤其如此

        至于是否可以接受例外。这取决于你的系统。如果您的应用程序可以处理失败案例,并且通知用户失败原因没有任何好处,那么继续,尽管我强烈建议您记录失败。我总是发现被调用来帮助解决问题,发现他们正在吞下异常(或者替换它并抛出一个新异常,而不设置内部异常)

        一般来说,我使用以下规则:

      • 在我的组件和库中,只有在我打算处理异常或基于异常执行某些操作时,我才会捕获异常。或者如果我想在异常中提供其他上下文信息
      • 我在应用程序入口点或可能的最高级别使用常规try-catch。如果出现异常,我只记录它并让它失败。理想情况下,例外情况永远不会出现 我发现以下代码是一种气味:

        try
        {
            //do something
        }
        catch(Exception)
        {
           throw;
        }
        

        这样的代码没有意义,不应该包括在内

        如果要捕获异常并返回false,那么它应该是一个非常特定的异常。你没有那样做,你抓住了所有的错误,然后返回false。如果我收到MyCarIsOnFireException,我想马上知道!其余的例外我可能不在乎。因此,您应该有一个异常处理程序堆栈,对某些异常(rethrow,或捕获并重新抛出一个新异常,更好地解释所发生的情况)说“whoa whoa something is house here”,而对其他异常只返回false

        如果这是一个您将要发布的产品,那么您应该在某个地方记录这些异常,它将帮助您在将来进行调整

        编辑:关于用try/catch包装所有东西的问题,我认为
        try
        {
            //do something
        }
        catch(Exception)
        {
           throw;
        }
        
        try
        {
           sendMessage();
        
           if(message == success)
           {
               doStuff();
           }
           else if(message == failed)
           {
               throw;
           }
        }
        catch(Exception)
        {
            logAndRecover();
        }
        
        // throws NumberNotHexidecimalException
        int ParseHexidecimal(string numberToParse); 
        
        bool TryParseHexidecimal(string numberToParse, out int parsedInt)
        {
             try
             {
                 parsedInt = ParseHexidecimal(numberToParse);
                 return true;
             }
             catch(NumberNotHexidecimalException ex)
             {
                 parsedInt = 0;
                 return false;
             }
             catch(Exception ex)
             {
                 // Implement the error policy for unexpected exceptions:
                 // log a callstack, assert if a debugger is attached etc.
                 LogRetailAssert(ex);
                 // rethrow the exception
                 // The downside is that a JIT debugger will have the next
                 // line as the place that threw the exception, rather than
                 // the original location further down the stack.
                 throw;
                 // A better practice is to use an exception filter here.
                 // see the link to Exception Filter Inject above
                 // http://code.msdn.microsoft.com/ExceptionFilterInjct
             }
        }
        
        static void set(Object array, int index, Object value);
        
        static int set(Object array, int index, Object value);