为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

手掌心 2019-07-29 10:24:21
Java或C#中异常管理的最佳实践我一直在决定如何在我的应用程序中处理异常。如果我的异常问题来自1)通过远程服务访问数据或2)反序列化JSON对象。不幸的是,我不能保证这些任务中的任何一个都成功(切断网络连接,不正确的JSON对象,这是我无法控制的)。因此,如果我遇到异常,我只需在函数内捕获它并返回FALSE给调用者。我的逻辑是,所有调用者真正关心的是任务是否成功,而不是为什么它不成功。这是典型方法的一些示例代码(在JAVA中)public boolean doSomething(Object p_somthingToDoOn){     boolean result = false;     try{         // if dirty object then clean         doactualStuffOnObject(p_jsonObject);         //assume success (no exception thrown)         result = true;     }     catch(Exception Ex)     {         //don't care about exceptions         Ex.printStackTrace();     }     return result;}我认为这种方法很好,但我真的很想知道管理异常的最佳实践是什么(我应该在调用堆栈中一直冒出异常吗?)。总结关键问题:是否可以捕获异常但不会冒泡或正式通知系统(通过日志或通知用户)?对于不会导致所有需要try / catch块的异常的最佳实践有哪些?跟进/编辑感谢所有反馈,在网上找到了一些关于异常管理的优秀来源:异常处理的最佳实践| 奥莱利媒体.NET中的异常处理最佳实践最佳实践:异常管理(文章现在指向archive.org副本)异常处理反模式似乎异常管理是根据上下文而变化的事情之一。但最重要的是,人们应该如何管理系统中的异常。另外注意通过过多的尝试/捕获代码腐烂或不给予例外它的尊重(例外是警告系统,还需要警告什么?)。此外,这是m3rLinEz的一个很好的选择评论。我倾向于同意Anders Hejlsberg和你的看法,大多数来电者只关心操作是否成功。从这个评论中,它提出了一些在处理异常时要考虑的问题:抛出此异常有什么意义?处理它有什么意义?呼叫者是否真的关心异常,还是只关心呼叫是否成功?是否强制调用者管理潜在的异常优雅?你是否尊重这种语言的含义?你真的需要返回像布尔这样的成功标志吗?返回boolean(或int)更像是一种C思维模式,而不是Java(在Java中你只是处理异常)。遵循与语言相关的错误管理结构:)!
查看完整描述

3 回答

?
炎炎设计

TA贡献1808条经验 获得超4个赞

对我来说,想要捕获异常并将它们转换为错误代码似乎很奇怪。为什么在后者是Java和C#中的默认值时,您认为调用者更喜欢错误代码而不是异常?

至于你的问题:

  1. 您应该只捕获实际可以处理的异常。在大多数情况下,捕获异常并不是正确的做法。有一些例外(例如,线程之间的日志记录和编组异常),但即使对于这些情况,通常也应该重新抛出异常。

  2. 你的代码中绝对不应该有很多try / catch语句。同样,我们的想法是只捕获您可以处理的异常。您可以包含一个最顶层的异常处理程序,将任何未处理的异常转换为对最终用户有用的东西,但是否则您不应该尝试捕获每个可能位置的每个异常。


查看完整回答
反对 回复 2019-07-29
?
HUH函数

TA贡献1836条经验 获得超4个赞

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

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

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

  1. 在我的组件和库中,如果我打算处理它或基于它做某些事情,我只会捕获异常。或者,如果我想在异常中提供其他上下文信息。

  2. 我在应用程序入口点或尽可能高的级别使用常规try catch。如果异常到达此处,我只需记录它并让它失败。理想情况下,异常永远不会到达此处

我发现以下代码是一种气味:

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

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


查看完整回答
反对 回复 2019-07-29
?
青春有我

TA贡献1784条经验 获得超8个赞

我想就这个主题推荐另一个好的来源。这是对C#和Java,Anders Hejlsberg和James Gosling的发明者的访谈,分别是关于Java的Checked Exception的主题。

失败和例外

页面底部还有很多资源。

我倾向于同意Anders Hejlsberg和你的看法,大多数来电者只关心操作是否成功。

Bill Venners:您提到了关于已检查异常的可扩展性和版本控制问题。你能澄清这两个问题的含义吗?

Anders Hejlsberg:让我们从版本开始,因为问题很容易在那里看到。假设我创建了一个声明它抛出异常A,B和C的方法foo。在foo的第二个版本中,我想添加一些功能,现在foo可能会抛出异常D.这对我来说是一个彻底的改变。将D添加到该方法的throws子句中,因为该方法的现有调用者几乎肯定不会处理该异常。

在新版本中向throws子句添加新异常会破坏客户端代码。这就像在界面中添加方法一样。在发布接口之后,它实际上是不可变的,因为它的任何实现都可能具有您要在下一个版本中添加的方法。所以你必须创建一个新的界面。与异常类似,您可能必须创建一个名为foo2的全新方法,该方法会抛出更多异常,或者您必须在新foo中捕获异常D,并将D转换为A,B或C.

Bill Venners:但是你不是在这种情况下破坏他们的代码,即使是在没有检查异常的语言中吗?如果foo的新版本将抛出一个客户应该考虑处理的新异常,那么他们的代码是不是因为他们在编写代码时没有预料到异常这一事实?

Anders Hejlsberg:不,因为在很多情况下,人们并不关心。他们不会处理任何这些例外情况。它们的消息循环周围有一个底层异常处理程序。那个处理程序只是打开一个对话框,说明出了什么问题并继续。程序员通过在任何地方编写try finally来保护他们的代码,因此如果发生异常他们将正确退出,但他们实际上并不感兴趣处理异常。

throws子句,至少它在Java中的实现方式,并不一定会强制您处理异常,但如果您不处理它们,它会强制您确切地确认哪些异常可能会通过。它要求您捕获声明的异常或将它们放在您自己的throws子句中。为了解决这个问题,人们做了荒谬的事情。例如,他们用“抛出异常”来装饰每个方法。这完全打败了这个功能,你只是让程序员写了更多的gobbledy gunk。这对任何人都没有帮助。

编辑:添加了有关转换的更多详细信息


查看完整回答
反对 回复 2019-07-29
  • 3 回答
  • 0 关注
  • 527 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信