我有时可以下沉我的例外吗?

我有一个最佳实践问题。 我意识到这是主观的,但是如果这是一个常见的编程习惯,我想问问比我聪明的人。

如果你有一个非关键的方法,你不想干涉你的应用程序的重要function,这是常见的使用这样的错误汇?

Try 'do stuff. not important if it fails. Catch ex as exception 'sink. do nothing. End Try 

如果你想雇用我,而你正在阅读我的一些代码,看到这个…你会吗?

赛斯

编辑哇! 感谢您的回答。 我认为共识是永远不应该做,或者应该是非常罕见的。

我想我会给你这个问题的背景。 首先,我对Karl Sequin的文章非常熟悉,并且多年来一直遵循这种模式。

但今天在我正在进行的这个项目上,我正在通过更改列表,面对增加了一个简单的function。 (如果你想知道…它将添加上下文菜单支持一个富文本框。)

附注说:“如果需要15分钟以上的时间,请把它放下。”

所以我面临增加什么是一个潜在的有用的function,但没有真正有时间来testing,它不会打破工作function。 为了logging,这个系统的exception处理程序有一个处理和下沉或logging这些错误的机制。 但是如果我正在研究一个没有健壮的error handling系统的系统呢。 添加这个function是否可以,如果发生错误,什么都不会丢失。

那是我的想法。 但是我把你的信息放在心上……基本上这是一个坏主意。

赛斯

是的,这是常见的,但总的来说不应该这样做。

有一些例外,比如OutOfMemoryException ,除非你抓住它们试图正常地终止你的应用程序。

在大多数情况下,吞咽System.ExceptionSystem.SystemException将不可避免地隐藏进一步的运行时问题。

永远不应该隐藏exception 。 无论如何,我可能会雇用你,但是当你为我工作的时候你不会这样做:)

严重的是,在Java中(例如)exception是用于某些情况下,你可能会select忽略,如FileNotFoundException (像你一样,有一个评论)。 但是,如果你曾经遇到过一种types的exception – 比如IOException – 你不能隐藏它。 如果Exception对你来说没有任何意义,那么把它封装在一个RuntimeException并把它抛给客户端。

一路上, Exception应该处理,但从来没有隐藏。

这很常见,但最好避免它。 至less你应该在某个地方loggingexception。

另外,避免使用stream量控制的exception。 你的代码应该写成处理所有可能的情况,而不诉诸例外。 除了性能增加,这种方法还告诉你,当发生exception时,值得你关注。

你不应该在这里捕捉所有的例外。 在罕见的情况下,可以忽略一个特定的,预期的例外。 但是,捕获所有exception并吞下它们将意味着您尝试在OutOfMemoryException和其他不可恢复的exception

虽然这里的大部分人都在谈论开发者,但我想指出另外一个观点。

我承认:我已经吞下了例外,并且在每种情况下都是因为function的devise者恕我直言。

“例外”是指“例外”,而不是失败或错误。 我的意思是:如果函数必须承认input可能不正确,我期望函数不使用exception。 我的愤怒特别针对“ParseException”。

如果你parsinginput,你很可能会发现未知/损坏/不精确的input。 这是“正常的”,不是一个例外。 在这种情况下,如果该函数的开发者抛出ParseException,如果该函数不能正确parsing,我觉得很烦人。

为什么?

  • exception打破了控制stream程
  • 例外是缓慢的
  • 通常,无论如何,因为您正在使用默认值进行初始化,所以无关紧要。

如果您调用parseFunction数千或数百万(!)次,那么您正在堵塞您的日志文件。

相比之下,我的理想function返回一个类对象与状态码和消息

 StatCode stat = parseXYZ(Reader r); 

然后可以进行testing。

 if (stat.code != OK) //whatever 

如果以另一种方式遇到你无法预见的问题(文件未locking,无意义的参数,非法的线程状态),例外情况非常好。

我个人认为这是非常糟糕的做法。

(不幸的是)我在查看代码的时候总是会寻找的东西之一,当我发现空的catch块或catch块实质上吞下exception时,我会问的是:

  1. 在这个时候,你是否100%肯定这个例外永远不会有问题?
  2. 无论代码库如何发展,您是否也100%确定在将来发生的任何exception都不会造成影响?
  3. 即使1和2都是真的,在这里做一些测井真的很难吗?

对于我来说最重要的是日志logging – exception的良好日志logging,良好的程序执行跟踪对于可以随着时间安全地修改的代码devise是至关重要的,并且演变成用户所信赖的稳定系统。

除此之外,一个好的做法是只捕捉特定的例外情况,并让所有其他exception冒出堆栈。 盲目地处理exception作为处理错误的一种方式是不正确的。

最佳实践说,你不应该这样做。 什么是不重要的,你不会想知道发生了错误? 我不认为我曾经遇到过这个问题。

我要么不使用try catch结构,要么将代码重构为返回布尔值的方法,这样我至less可以识别它是否成功…

那是我的想法

更新 :有时您可能需要剔除exception。 在这些情况下,我要确定哪些例外可能是这个候选,然后捕获这些特定的例外。 但是这远不是捕捉Exception ,可能是任何事情,比如前面提到的OutOfMemoryException 。 简而言之,我只是想明确地忽略它。

不,在我看来这不行。

你的系统可能并不重要,但是可能你想让它运行,否则你不会把它写在第一位。 现在,如果有一天它停止运行,那些维护它的人不知道为什么它突然不起作用,因为你完全隐藏了错误。 事实上,甚至可能需要很长时间才能知道错误来自哪里,甚至是首先出现错误。 这可能会浪费大量的开发人员时间,而不会花费太多时间来logging错误而不是丢弃错误。

而你正在捕捉像OutOfMemoryExceptionexception,你真的不想赶上和放弃。 如果代码不重要,但消耗太多的内存,并使整个系统变慢,那么您需要被告知可以修复它。

有时我发现开发人员宁愿捕捉并吞下exception,而不是编写正确的error handling代码。

有一些代码,如果抛出一个exception,他们捕获exception,尝试其他的东西,如果抛出一个exception,做一些其他的事情,等等。例外是对象,并在被引发时被创build。 如果可以,请编写正确的处理代码来处理错误,并且只有在因任何原因can't continue时才使用exception。

至于吞咽exception,如果我说我写了没有的代码,我会撒谎。 这不是一个最佳实践,当你的程序行为不好的时候,debugging是非常困难的。 我也被他们咬了一口

这几乎从来都不是一个好主意,但取决于你如何做例外,有些情况下适用。 例如:

 try { Cache.refresh(myObject) } catch (NotInCacheException) { // If the object isn't already in the cache, then we don't have to worry // about refreshing it. It's assumed that this is a common occurrence, // so we don't need to log it either; that ends up just spamming // the logs. So, just swallow it, silently. } 

(注意:Cache.refresh()是否应该抛出一个NotInCacheException在这里没有问题,我只是用它作为一个简单的例子)。

警惕:如果你有一个非常具体的例外,你只能逃避这一点,你正在寻找。 在你的例子中,你正在捕捉Exception ,这是太高级别(你会像其他人所说的那样吞下严重的错误)。

另外:如果你有一个灵活的日志框架,你可能想logging这个exception,无论如何是为了信息的目的。 我在这里特别想到Log4Net / Log4J:你可以configuration你的日志logging(甚至是运行时),根据类和严重性来select/忽略exception。 因此,您可以在正常情况下将这些types的exception消除,但是如果您想要在应用程序中执行某些操作,请将其logging下来。

如果你决定吞下这个例外,我的政策是总是有一个代码注释来解释你为什么这样做; 这标志着这不仅仅是另一个糟糕的开发实践。

作为一个分配修复bug的新手,我发现我分配的特定bug是打印(debugging)“这绝不应该发生”。 我终于摆脱了在一个显然不可能的错误状态下工作的恐惧,终于发现它是由一个微妙的竞争条件造成的。 如果这个代码的作者原本只是在没有至less那么微不足道的debugging语句的情况下抛出了exception,那么跟踪竞争条件将会困难得多。

从那时起,我已经成为处理exception或推动它们的巨大支持者,直到错误条件以对用户友好的方式显示给最终用户,而这仅仅是简单地loggingdebugging语句的一个步骤。

我认为回答这个问题的最好方法就是谈论可以接受的情况。 在大多数情况下,这是不安全的。 在那些安全的情况下,通常最好是在警告,debugging或跟踪日志中至less吐出一些关于它的信息。 我只能想到一些安全的情况:

你期待一个非常特殊的例外,并且知道你可以从中恢复:

 try { Integer.Parse(someString); } catch (ParseException pe) { //In this particular use case, if the string doesn't parse, //I don't need to do anything. Logging a warning might be a //good idea, in some cases } 

您正在清理代码安全:

 beginDatabaseTransaction(); try { doSomeDatabaseOperation(); } catch (Exception e) { log.error(e); //log the original exception try { rollbackDatabaseConnection(); } catch(Exception e2) { //You may ignore this one-off exception, though //I would strongly consider logging it } throw; //rethrow the original exception and let it propagate } 

(这绝不是数据库操作的最佳实践模式,只是一个人为的例子。)

在我们的生产体系​​中,我们有不止一个情况,过度的例外诱捕造成的损害要比好的多得多。 小心这个。

还有一件事: 如果你除了要抛出一个特定的错误,你通常不应该试图抓住一个错误。

大多数例外情况可以帮助您,开发人员查找并诊断代码中的错误。 它们旨在使程序(或当前操作)终止,以防止不可预知的行为(如试图加载数据库中的所有logging,因为您无法为SQL语句构buildWHERE子句)。当你捕捉到一个未知的exception时,你隐藏了当前正在运行的代码中的错误,并使得代码可能意外行为,而不是终止。

你应该区分可忽略的例外和致命的例外。 我不知道这是如何在VB中完成的,但是在Java中(例如),从Error派生的exception不应该被忽略。 这包括类加载器故障,内存不足,堆栈溢出等。

处理exception的最佳实践(MSDN) :

根据他们你也可以

对错误做些事情或忽略它。

这取决于你和你的团队来决定我的猜测。

一般来说,我会说这是不好的做法 – 但让我们说,有问题的方法是一种日志logging方法。 我不希望我的应用程序崩溃,因为事件日志已满。 在这样的情况下,我会说没关系。 我仍然输出到debugging窗口。

我会说“不要这样做” – 不是这样的。

首先,尝试重构“非关键”代码,使其不会抛出exception。

如果你无法做到这一点,至less不要盲目追赶 Exception 。 只捕捉你期望抛出的exception(并将它们logging在某个地方!) – 其他任何东西都需要注意。

如果使用vs2008,您至less可以将它们发送到debugging窗口

  System.Diagnostics.Debug.WriteLine("exception in method - my method -: "+ex.message); 

我只是在讨厌的情况下才这样做,比如closures连接:

 try { conn.close() } catch( Exception e ) { } 

因为我已经确定我不再需要它了。

我的意思是,你可以做到这一点,但你必须保持睁大眼睛,知道你为什么这样做。 考虑一下。 在我的店里,我们要求你有一个评论,解释你为什么吃这个例外

如果这是一件好事,取决于语言和exception是多么昂贵。 你仍然不应该捕获所有的exception,但是,例如,在Python中,以下是一个常见的习惯用法:

 d={} for i in theList: try: d[i] += 1 except KeyError: d[1] = 1 

这是做默认插入的最快方法。 您会为DivisionByZeroError或其他任何exception做同样的事情。 而一堆stream量控制结构的定义归结为raise StopIteration

Java突出了使用Exceptions进行编程的必要性。 我发现Java倾向于随心所欲地抛出exception,这很烦人,因为如果你不想让自己的应用程序崩溃的话,你必须抓住它们。 不幸的是,Java中的exception是一个相当重要的特性。

我学会了有效地在图标中使用例外。 图标有这个整洁的东西叫'失败'。 如果一个expression式没有可以返回的值,它将会失败。 这只是一个微型的exception,而不是try {} catch {}符号,失败是由语言元素直接处理,如ifwhile

国际海事组织,这是exception应该如何在Java中工作…但不幸的是,他们不。 相反,你最终编写防御代码来防止exception,而不是轻易自然地处理它们。 无声地吞咽一个特殊的例外,因为它是相当罕见,比防止它更优雅,我会认为是一个有用的伎俩。 但是,这是对“ 你必须知道规则才能打破规则 ”的回应。 换句话说,不要经常这样做。

我希望更多的语言支持图标中find的成功/失败模式。