首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java或C#中异常管理的最佳实践

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

Stack Overflow用户
提问于 2009-01-03 18:41:52
回答 15查看 33.2K关注 0票数 118

我无法决定如何处理应用程序中的异常。

很多情况下,如果我的异常问题来自1)通过远程服务访问数据,或者2)反序列化JSON对象。不幸的是,我不能保证这些任务都能成功(切断网络连接,格式错误的JSON对象,超出我的控制范围)。

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

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

代码语言:javascript
复制
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;
}

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

在关键问题摘要:

  1. 只捕获异常,而不是将它们冒泡起来,或者正式通知系统(通过日志或通知用户)可以吗?
  2. 对于不需要try/catch块的异常,有哪些最佳实践?

追踪/编辑

感谢您的反馈,在网上找到了一些关于异常管理的优秀来源:

  • 处理异常的最佳实践O‘’Reilly媒体
  • .NET中的异常处理最佳实践
  • 最佳做法:异常管理 (文章现在指向archive.org副本)
  • 异常处理反模式

异常管理似乎是根据上下文的不同而变化的事情之一。但最重要的是,在如何管理系统内的异常方面,应该保持一致。

此外,通过过度尝试/捕获或不尊重异常(异常是警告系统,还需要警告什么?)

此外,这也是来自m3rLinEz的一个不错的选择。

我倾向于同意Anders和您的观点,即大多数来电者只关心手术是否成功。

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

  • 抛出这个异常有什么意义?
  • 处理它有什么意义呢?
  • 调用方是否真的关心异常,还是只关心调用是否成功?
  • 强制调用方管理潜在的异常是否很优雅?
  • 你尊重语言的偶像吗?
    • 你真的需要返回一个像布尔一样的成功标志吗?返回布尔值(或int)更像是C思维,而不是Java (在Java中,您只需要处理异常)。
    • 遵循与语言相关的错误管理结构:)!

EN

回答 15

Stack Overflow用户

回答已采纳

发布于 2009-01-03 18:49:36

我觉得奇怪的是,您希望捕获异常并将它们转换为错误代码。为什么您认为调用方更喜欢错误代码而不是异常,而后者是Java和C#中的缺省值?

至于你的问题:

  1. 您应该只捕获实际可以处理的异常。在大多数情况下,仅仅捕获异常并不是正确的做法。有一些异常(例如,在线程之间记录和编组异常),但是即使在这些情况下,通常也应该重新抛出异常。
  2. 您的代码中绝对不应该有太多的try/catch语句。同样,我们的想法是只捕获您可以处理的异常。您可以包含一个最顶层的异常处理程序,以将任何未处理的异常转换为对最终用户有一定帮助的东西,但否则,您不应该试图在每个可能的地方捕获每个异常。
票数 63
EN

Stack Overflow用户

发布于 2009-01-03 18:51:46

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

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

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

  1. 在我的组件和库中,只有当我打算处理它或基于它做一些事情时,我才会捕获异常。或者如果我想在异常中提供额外的上下文信息。
  2. 我在应用程序入口点使用一般的尝试捕获,或者在可能的最高级别使用。如果有异常出现,我只记录它并让它失败。理想情况下,例外情况永远不会出现。

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

代码语言:javascript
复制
try
{
    //do something
}
catch(Exception)
{
   throw;
}

这样的代码没有用,也不应该包括在内。

票数 25
EN

Stack Overflow用户

发布于 2009-01-03 21:24:44

我想推荐关于这个话题的另一个好消息来源。这是对C#和Java的发明者、Anders和James的采访,主题分别是Java的检查异常。

失败和例外

页面底部也有大量的资源。

我倾向于同意Anders和您的观点,即大多数来电者只关心手术是否成功。

Bill :您提到了与检查异常有关的可伸缩性和版本控制问题。你能澄清一下这两个问题是什么意思吗? Anders :让我们从版本控制开始,因为在那里很容易看到问题。假设我创建了一个方法foo,它声明它抛出异常A、B和C。在foo的第二版中,我想添加一些特性,而现在foo可能会抛出异常D。对我来说,将D添加到该方法的抛出子句是一个巨大的变化,因为该方法的现有调用者几乎肯定不会处理该异常。 在新版本中向抛出子句添加新异常会破坏客户端代码。这就像向接口添加一个方法一样。在发布接口之后,就所有实际目的而言,它都是不可变的,因为它的任何实现都可能具有要添加到下一个版本中的方法。所以你必须创建一个新的界面。同样,如果有异常,则必须创建一个名为foo2的全新方法,该方法将引发更多异常,或者必须在新foo中捕获异常D,并将D转换为A、B或C。 Bill :但是在这种情况下,即使是在一种没有检查异常的语言中,您也不会破坏他们的代码吗?如果foo的新版本要抛出一个新的异常,客户端应该考虑处理,难道他们的代码不是因为他们在编写代码时没有预料到这个异常而中断了吗? Anders Hejlsberg:不,因为在很多情况下,人们都不在乎。他们不会处理这些异常。在它们的消息循环中有一个底层异常处理程序。该处理程序将只会弹出一个对话框,说明出了什么问题并继续。程序员通过编写“尝试无处不在”来保护他们的代码,所以如果出现异常,他们会正确地退出,但实际上他们对处理异常并不感兴趣。 抛出子句(至少它在Java中的实现方式)并不一定强迫您处理异常,但如果不处理它们,则强制您准确地确认哪些异常可能通过。它要求您捕获已声明的异常或将它们放入您自己的抛出子句中。为了满足这一要求,人们会做一些可笑的事情。例如,他们用“抛出异常”来装饰每一种方法。这完全违背了这个特性,而您只是让程序员编写了更多的粘糊糊。这对任何人都没有帮助。

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

票数 10
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/409563

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档