C# Java或C中异常管理的最佳实践#
我一直在决定如何处理应用程序中的异常 如果我的异常问题来自1)通过远程服务访问数据,或2)反序列化JSON对象,那么我的问题就更大了。不幸的是,我不能保证这两项任务都能成功(切断网络连接,格式错误的JSON对象超出我的控制) 因此,如果遇到异常,我只需在函数中捕获它,并向调用方返回FALSE。我的逻辑是,调用方真正关心的是任务是否成功,而不是任务为什么不成功 下面是一些典型方法的示例代码(JAVA) 我认为这种方法很好,但我真的很想知道管理异常的最佳实践是什么(我真的应该在调用堆栈中一直冒泡异常吗?) 关键问题摘要:C# Java或C中异常管理的最佳实践#,c#,java,exception,error-handling,C#,Java,Exception,Error Handling,我一直在决定如何处理应用程序中的异常 如果我的异常问题来自1)通过远程服务访问数据,或2)反序列化JSON对象,那么我的问题就更大了。不幸的是,我不能保证这两项任务都能成功(切断网络连接,格式错误的JSON对象超出我的控制) 因此,如果遇到异常,我只需在函数中捕获它,并向调用方返回FALSE。我的逻辑是,调用方真正关心的是任务是否成功,而不是任务为什么不成功 下面是一些典型方法的示例代码(JAVA) 我认为这种方法很好,但我真的很想知道管理异常的最佳实践是什么(我真的应该在调用堆栈中一直冒泡异常
- (文章现在指向archive.org副本)
- 抛出此异常的目的是什么
- 处理它有什么意义李>
- 调用方是否真的关心异常,还是只关心调用是否成功
- 强制调用方管理潜在异常是否合适
- 您是否尊重该语言的IDOM?
- 您真的需要返回一个类似布尔值的成功标志吗?返回布尔(或int)更像是一种C思维方式,而不是Java思维方式(在Java中,您只需处理异常)李>
- 遵循与以下语言关联的错误管理构造:)李>
- 您应该只捕获实际可以处理的异常。只是 在大多数情况下,捕获异常不是正确的做法。 存在一些例外情况(例如,日志记录和编组例外情况) 线程之间),但即使在这些情况下,您通常也应该 重新显示异常
- 您的文档中绝对不应该有很多try/catch语句 代码。同样,这个想法是只捕获您可以处理的异常。 您可以包含一个最顶层的异常处理程序来处理任何未处理的异常 将异常转换为对最终用户有些有用的内容,但 否则,您不应该尝试捕获中的每个异常 每一个可能的地方
- 在我的组件和库中,只有在我打算处理异常或基于异常执行某些操作时,我才会捕获异常。或者如果我想在异常中提供其他上下文信息
- 我在应用程序入口点或可能的最高级别使用常规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);
- 我觉得奇怪的是,您想要捕获异常并将其转换为错误代码。当Java和C#都默认使用异常时,为什么您认为调用者更喜欢错误代码而不是异常
关于你的问题:
这取决于应用和情况。如果您正在构建一个库组件,您应该弹出异常,尽管它们应该被包装为与您的组件相关。例如,如果您正在构建一个Xml数据库,假设您正在使用文件系统存储数据,并且您正在使用文件系统权限保护数据。您不希望冒泡出FileIOAccessDenied异常,因为这会泄露您的实现。相反,您将包装异常并抛出AccessDenied错误。如果将组件分发给第三方,则尤其如此 至于是否可以接受例外。这取决于你的系统。如果您的应用程序可以处理失败案例,并且通知用户失败原因没有任何好处,那么继续,尽管我强烈建议您记录失败。我总是发现被调用来帮助解决问题,发现他们正在吞下异常(或者替换它并抛出一个新异常,而不设置内部异常) 一般来说,我使用以下规则: