3

我试图在这里理解程序的正确结构以促进一切。基本上在哪里“放”东西。

例如:

你有 2 节课。

1类是你的主要。

这两个类都有很多方法。

类 1 调用类 2 的一个实例并运行一个方法。该方法应该返回一个值。

问题 1:我应该在这个方法里面有一个 try/catch 块吗(在第 2 类中)?

问题 2:try/catch 块是否应该在我调用方法的地方(在第 1 类中)?

try
   method();
catch
...

问题3:在执行类2中的方法时,当涉及到返回值时,我是否应该返回“错误代码”然后在调用类中处理此代码?

问题 4:当发生错误并且我需要“停止”程序时,我应该使用 if/else 语句以便代码仅在满足正确条件时才继续前进,还是应该更频繁地使用关键字“break”?

问题 5:出错的可能性是无穷无尽的,特别是如果你有大中型程序。你们如何处理用户运行程序时可能遇到的不可知错误?

4

5 回答 5

4

例外就是:例外。您不应该对常规程序流程使用异常。(如果你说,“哦,是的,我预料到了”,它可能不应该是一个例外。)

在需要处理的地方处理异常。如果您可以在该try-catch块不成功的情况下生存该功能,那么您应该在那里处理它。同样,如果您需要包装一些东西,您也可以添加一个finally块(using类似于finallyC# 中的 - 它编译为try-finally,但不如自己编写它强大。它只是调用.Dispose()您指定的一次性对象)。

但是,如果您需要退出该函数,或者您正在运行一系列函数,这些函数需要在您的主类中全部成功,那么在您的 Class 1 中进行处理可能会更好。

警告:每条规则都有例外(哈!)。随着您编写更多程序,您可以直观地了解应该在哪里进行错误处理 - 但通常会有多个选项,并且可能不是很明确。

于 2012-08-15T13:41:35.997 回答
3

一般来说,所有这些问题的答案都是“视情况而定”。显然,您需要做什么取决于情况的具体情况及其包含的应用程序。

从实践的角度来看,我通常遵循几个规则:
1. 使用异常处理而不是错误代码
2. 只有在我知道如何处理异常时才使用 try/catch

显然,在不知道该方法的作用以及您是否可以处理任何异常的情况下,没有人可以告诉您是否需要在方法中使用 try/catch。

错误代码是否真的适用取决于您。我一般认为它不适用;但是,有时它可能是。在这些情况下,如果调用者总是使用代码而不是传递它,我只认为它是适用的。“GetErrorCode”可能是错误代码适用的一个很好的例子。

您不可能“处理”(即补偿)“未知”错误。推荐的做法是不处理异常并让句柄优雅地终止,因为它处于未知状态。

于 2012-08-15T13:41:52.567 回答
0

我大体上同意 David 和 Peter ...我要补充的一件事是要小心捕获异常时捕获的异常... Richter有一个非常有趣的章节,关于异常处理以及应该如何继承异常与它们的实际实现方式相比......但即使如此,如果你发现自己一直在捕捉通用 Exception 类,它(IMO)仍然是懒惰的,或者至少是考虑不周的......

如果您正在执行文件读取/写入,您可能非常希望捕获适当的 IO 异常,但是如果说,如果抛出 NullReferenceException 并且您的 try/catch 只是保护,那么始终捕获最通用的 Exception 类可能会导致您遇到问题针对 IO 异常...您的 catch 块会尝试修复(假设是)一个 IO 异常,它可能会使您的代码处于非常不稳定的状态。

此外,在继续重新抛出原始错误时要非常小心,除非您确信您确实正确地处理了它......如果您编写了一个库并发布了它并吞下了所有错误,因为您认为自己在做最好的事情,那么使用您的库的人将无法调试正在发生的事情......异常也会被抛出到服务器日志中,因此被吞下的错误永远不会出现。

我主张捕获通用错误的一个地方是在 UI 层,您显然不想向用户显示 YSOD,但即便如此,您的捕获也可能会做一些日志记录或其他帮助您稍后调试的东西。

于 2012-08-15T13:47:47.150 回答
0

捕获异常并返回错误代码/布尔值会导致“箭头”代码,如下所示:

if(Func1())
{
   if (Func2())
   {
       if (Func3())
       {
       }
   }
}

不幸的是,我维护了一个复杂的项目,其中异常被视为埃博拉病毒,并在它们萌芽时立即被遏制。它实际上只是让代码更难理解和维护。

于 2012-08-15T13:49:24.217 回答
0

这取决于您如何可视化和构建应用程序。第 1 类和第 2 类是同一模块的一部分还是在不同的模块中?一般来说,一个模块提供“API”,“API”的调用者需要捕获错误和异常。看看防御性编程

问题 1:我应该在这个方法里面有一个 try/catch 块吗(在第 2 类中)?

如果 Class 2 是一个单独的模块并且您不想将异常传播到调用者模块,那么可以。如果你想,那就不行。然后需要记录从此类/模块引发的异常。

如果第 1 类和第 2 类在同一个模块中,那么这又取决于您是否要处理内部类中的异常。

问题 2:try/catch 块是否应该在我调用方法的地方(在第 1 类中)?

如果您想确保 Class 1 不会引发更多异常,那么可以。

问题3:在执行类2中的方法时,当涉及到返回值时,我是否应该返回“错误代码”然后在调用类中处理此代码?

如果您想抛出异常以返回错误代码,这又是一个设计/实现决定。

问题 4:当发生错误并且我需要“暂停”程序时,我应该使用 if/else 语句以便代码仅在满足正确条件时才继续前进,还是应该更频繁地使用关键字“break”?

要使用break,您需要在调用者中使用一个循环。

问题 5:出错的可能性是无穷无尽的,特别是如果你有大中型程序。你们如何处理用户运行程序时可能遇到的不可知错误?

大型程序分为模块,可以由不同的开发人员编写。所以设计和接口契约在这里变得至关重要。

于 2012-08-15T13:52:40.090 回答