如何实现错误处理


13

即使我已经在专业水平上编程了几年,但我仍然不完全理解错误处理。尽管我的应用程序运行良好,但错误处理并未在专业级别上实现,而是多种技术的结合与匹配。

我的错误处理没有任何结构。我想学习和理解它是如何在专业水平上实现的。这是我缺乏知识的领域。

什么时候应该使用异常,什么时候应该返回成功状态,以在逻辑流程中进行检查?可以混合异常并返回状态吗?

我主要使用C#编写代码。


2
为什么要投反对票?我在问一个有关错误处理实现及其实现方式的严肃问题。如果这不是程序员之间问此类问题的最佳地点,那么哪里呢?当人们对此类问题投反对票时,这真让我感到烦恼,因为没有其他地方可以提出这样的问题。这可能是网络上我唯一获得可靠答案和可能资源的地方。因此,与其否定一个其他人一定会问Google的问题,不比回答这个问题容易吗?
James Jeffery 2013年

6
您的问题很广泛。也许您可以通过列举一些未能实现编码目标的具体示例来缩小范围。
安迪斯·史密斯

网络上有很多有关错误处理的文章:尝试以下操作:msdn.microsoft.com/en-us/library/seyhszts.aspx
Nir Kornfeld 2013年

Answers:


25
  1. 对异常情况使用例外,您不能合理地期望经常遇到的异常,表明出现问题的异常。例如,如果网络中断,则对于Web服务器来说是一件例外的事情。如果数据库不可用,则表示出了点问题。如果缺少配置文件,则可能意味着用户将其弄乱了。

  2. 不要使用异常来处理错误的代码。为了检查代码的正确性,您应该使用断言,或者在.NET Framework 4和更高版本中使用代码协定(它取代断言并具有其他特别有价值的功能)。

  3. 在非例外情​​况下请勿使用例外。当用户被要求输入数字时,输入“狗”的事实并不是例外,因此不应例外。

  4. 选择例外类型时要小心。在需要时创建自己的类型。仔细选择继承,要记住,抓父母也将抓孩子。从不throw Exception

  5. 不要将返回代码用于错误。错误代码容易被掩盖,忽略,遗忘。如果有错误,请处理它或将其传播到上层堆栈。

  6. 如果期望某个方法返回错误并且该错误不是异常,请使用枚举,而不要使用错误编号。例:

    // Note that the operation fails pretty often, since it deals with the servers which are
    // frequently unavailable, and the ones which send garbage instead of the actual data.
    private LoadOperationResult LoadProductsFromWeb()
    {
        ...
    }

    的意思LoadOperationResult.ServerUnavailableLoadOperationResult.ParsingError等更加明确的比,说,记住,代码12只意味着该服务器已关闭,并且代码13 -该数据不能被解析。

  7. 当错误代码引用通用代码时,请使用错误代码,该错误代码为在特定领域工作的每个开发人员都知道。例如,请勿为HTTP 404 Not Found或HTTP 500 Internal Server Error重新创建枚举值。

  8. 当心布尔值。迟早,您不仅要了解特定方法是成功还是失败,还需要知道原因。为此,异常和枚举要强大得多。

  9. 不要捕获所有异常(除非您处于堆栈的最顶端)。如果发现异常,则应该准备好处理它。捕获所有内容表明您不在乎代码是否正确运行。这可能会解决“我现在不想搜索如何解决此问题”,但迟早会伤害您。

  10. 在C#中,永远不要抛出这样的异常:

    catch (SomeException ex)
    {
        ...
        throw ex;
    }

    因为您要破坏堆栈。而是这样做:

    catch (SomeException)
    {
        ...
        throw;
    }
  11. 编写异常消息时要付出努力。我看过几次类似throw Exception("wrong data")或的东西throw Exception("shouldn't call this method in this context")。其他开发人员,包括六个月后的您自己,都不知道什么数据是错误的,以及为什么或为什么我们不应该在上下文中调用某些方法,也不知道究竟是哪种上下文。

  12. 不要向用户显示异常消息。它们不是普通人所期望的,甚至对于开发人员自己来说也是不可读的。

  13. 不要本地化异常消息。在文档中搜索本地化的消息非常耗时且毫无意义:每条消息均应使用英文和英文。

  14. 不要只关注异常和错误:日志也非常重要。

  15. 在.NET中,请不要忘记在该方法的XML文档中包括异常:

    /// <exception cref="MyException">Description of the exception</exception>

    在XML文档中包含异常对于使用该库的人来说使事情变得容易得多。除了尝试猜测某个方法可能会抛出哪个异常以及原因之外,没有什么比这更令人烦恼了。

    从这个意义上讲,Java异常处理提供了一种更严格,更好的方法。它迫使您要么处理被调用方法可能引发的异常,要么在您自己的方法中声明它可以引发您不处理的异常,从而使事情特别透明。


¹话虽这么说,但我发现Java对异常和错误的区分毫无用处和混乱,因为该语言已检查和未检查了异常。幸运的是,.NET Framework只有例外,没有错误。


我从中学到了一些报价,请问清单来自哪里?网站或个人经验?无论哪种方式,出色的工作(他能得到吗?)。
Shelby115 2013年

@ Shelby115:该列表按顺序来自:Steve Mcconnell的堆栈交换,个人经验和Code Complete。
阿森尼·穆尔琴科

谢谢@MainMa,这是一个很好的回应!我上大学时曾经拥有Code Complete,但有人偷了它。我没看懂。
James Jeffery 2013年

@JamesJeffery:然后在图书馆借第二版,或者买一本:这是与开发相关的稀有书籍之一,完全值得。
阿森尼·穆尔琴科

@MainMa刚刚从亚马逊订购,感谢:DI还拥有干净的代码,并且完全忘记了第7章
詹姆斯杰弗里

1

我认为MainMa的清单非常完整。我将添加一些自己的:

  1. 阅读Eric Lippert的文章,了解他如何对异常进行分类。特别重要的是他的观点是不捕获实际上是代码中的错误的异常。改正代码!
  2. 如果您知道可能会发生异常,并且可以对其进行处理,请处理该异常,但要限制尝试捕获的范围并捕获所需的特定异常。也就是说,不要这样做:

public void Foo() {
    try {
        //get input from use
        //do calculations
        //open file
    }
    catch (Exception ex) {
       //handle exception
    }
}

而是这样做:

public void Foo() {
    //get input from use
    //do calculations
    try {
        //open file
    }
    catch (FileOpenException ex) {
       //handle exception
    }
}
  • 不要将异常用于控制流。例如,不要在查找对话框中抛出ClientNotFoundException(在这种情况下,未找到客户端是非例外的),并且期望调用代码在发生这种情况时显示“未找到结果”消息。

  • 不要吞下例外!

  • 请记住,真正处理异常仅意味着三件事:

    1. 重试该操作。仅在问题是暂时的时有效。
    2. 尝试其他方法。
    3. 通知某人有关问题。仅在通知是可操作的(即用户可以对此做某事)时才有效。

    如果这些选项都不适用,那么您可能不应该捕获该异常。但是,您应该记录它,然后取消操作或关闭。当然,这取决于您对正确性与鲁棒性的要求。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.