2009-11-28 81 views

回答

7

如果您可以处理异常,那就这样做。如果你不能,那就让异常冒险吧!

4

一些一般性的想法:

  1. 抛出异常,只有特殊的错误条件。

  2. Fail fast.

  3. 既然你扔了特殊的错误情况仅例外,假设是,你不能在类内解决它,所以异常应泡了调用堆栈。无论你是在眼前的课堂上面处理它,还是以一揽子方式处理它,都取决于你。

+0

我会建议“只为**错误**条件抛出异常。”错误条件应该是例外(不是主程序流程),但我喜欢隐含的观点。例如,如果您使用错误代码进行错误处理,请切换到例外。 – TrueWill 2009-11-29 02:55:13

+0

是的,这就是我的意思。修正了我的帖子。 – 2009-11-29 04:14:36

0

只要您能做出有效的反应,您应该处理异常。如果它要泡得更高,那就放手吧。

我也在一些比我的代码更低的层次抛出异常时重新打包异常。在Java中执行SQL调用可以看到一个很好的例子。一切都会抛出一个SQLException,如果我有一个方法可以触发多个异常,但无法处理它们,这将毫无帮助。通过重新包装,我可以在连接失败和构建准备好的语句的问题之间区别并作出不同的反应。

0

我相信最好的方法可能是一种混合的方法。

在类中执行与类有关的问题的错误处理。例如,如果属性设置器进行验证,则会从该类中检测并抛出这些错误。

在网页或表单级别,您可以在一种方法中处理所有错误。例如,对于ASP.Net Web应用程序,您可以使用Page_Error方法来捕获到达页面的所有异常。然后,显示由类属性setter引发的错误消息文本。

或者,您可以在每个方法签名中包含errorMessage字符串返回值。调用页面/表单检查errorMessage的内容,并根据上下文决定要执行的操作。这需要比上述方法更多的编码。

有时,类不知道事件是否实际上是一个错误。例如,如果一个类方法从数据库中选择一条记录并返回它的数据,那么类不知道这是否是一个错误。如果调用类方法的页面/表单是一个搜索页面,那么获取没有返回的记录不是错误,它是“找不到记录”,并显示该信息。

2

一般来说,只要需要将异常“转译”到最终用户,异常处理应在业务/控制器逻辑/层中完成。因此不在例如数据层,模型层,视图层和实用程序类中。

捕获运行时异常(如空指针,算术错误,数组索引越界等)一般应该完成而不是。他们通常只是表示编程错误。您应该相应地编写代码,以避免它们发生(例如if (x != null) { x.doStuff() })。

+0

如果你正在编写一个多层应用程序,这是真的。 – 2009-11-29 04:20:55

2

您如何与异常交互取决于您的代码在应用程序层中的位置。一般来说,错误报告是UI的问题,通常最好留给应用程序,即最外层的代码。

低级代码和中级业务逻辑代码通常在不同的应用程序之间共享。由于不同的应用程序会针对向用户报告多少错误和向哪个错误报告不同的策略,所以低级别和中级别的代码应该避免为了错误报告而处理异常。让应用程序做到这一点。

在低级和中级代码中捕获异常有很多合法的原因,尤其是在主路径失败时尝试替代路径,或者将低级异常转换为更具体的异常目前的操作。注意不要过分,尽可能使你的异常陷阱(不要过度泛化,否则你会陷入你没有准备处理的事情),并且极度批评在低级和中级水平完全禁止异常码。

低级和中级代码的一般原则应该是:如果调用者请求的操作失败,让调用者看到后果 - 例外。

您的低级和中级代码通常会自然分为两个阵营:执行请求操作或抛出异常(如果无法完成)的“硬”功能,以及更“软”的功能方便实验性探查。如果一个操作可能会在大部分时间内失败,比如“FileExists()”,那么可能很少使用异常来抛出异常,并要求调用者将所有对这个函数的调用包装在异常处理程序中。这将为调用者创造更多的工作。在这个用例中,FileExists()应该是一个“软”函数,它返回true/false而不是抛出。这个“硬”版本可能被称为“RequireFile()”,如果找不到该文件,则会引发该问题。

作为命名模式,您经常会看到“尝试”作为软函数的前缀。因此,如果GetData()不能完成工作,GetData()将成为硬函数,而TryGetData()将是返回布尔值而不是抛出的软函数。根据使用情况,通常在类或库中看到这两种功能。如果TryGetData()返回false,或TryGetData()在try..catch块内调用GetData(),则GetData()会调用TryGetData()并抛出。使用哪种模式取决于函数完成的工作的复杂性。如果故障情况容易被布尔逻辑检测到(异常风险低),那么TryGetData将成为主要实现。如果失败案例因异常而失败,那么GetData将成为主要实现。

“硬”功能让调用者充分利用异常来简化程序逻辑 - 如果此调用成功,那么我可以使用调用结果继续下一步。如果这个调用失败,它会抛出一个异常,下一步将不会执行。 “硬”功能可以让您通过一系列操作来进行操作,并假设每个操作都返回合法结果,因为如果某个操作无法返回合法结果,则会抛出并将我们从操作序列中删除。这样可以让您集中主要路径程序逻辑,而不会出现消防队列错误处理的混乱情况 - 分析每次呼叫时的功能错误代码并决定如何处理它们。

相关问题