是否使用例外情况来控制正常的控制流程?

时间:2013-08-23 09:02:17

标签: coding-style scalability design-patterns anti-patterns

如果函数失败是正常的,例如通过在数据库中找不到记录或者表示可能缺少值的任何其他情况,是否建议使用异常来处理这种情况?

伪代码示例:

function retrieve(foo):
  results = db.query("SELECT * FROM bar WHERE foo="+foo)
  if not results:
    throw Exception("no results")
  return results[0]

function main:
  try:
    record = retrieve(42)
  except:
    print "no record with 42"
    .... will create the record and continue
  else:
    print "record found: "+record
    .... will use the existing record and continue

另一种解决方案可能是返回null值而不是启动此异常。 哪一个最有可能是反模式?在哪种情况下使用异常更好,而不是?

3 个答案:

答案 0 :(得分:2)

Joshua Bloch在“Effective Java”中总结道:

  顾名思义,

例外仅用于特殊情况;它们永远不应该用于普通的控制流程

您可以在Google图书上找到相应的图书摘要(“项目57:仅针对例外情况使用例外情况”)。

除了滥用异常导致代码难以理解之外,Bloch还有一些理由对今天的JVM实现有效:

  

因为异常是针对特殊情况而设计的,所以几乎没有   激励JVM实现者使它们像显式测试一样快。

对于(Hotspot)JVM,创建异常非常昂贵(想想生成的堆栈跟踪)。

答案 1 :(得分:1)

来自.Net Framework Development Guidelines

如果可能,请勿对正常的控制流使用异常。

除了系统故障和具有潜在竞争条件的操作之外,框架设计者应该设计API,以便用户可以编写不会抛出异常的代码。例如,您可以在调用成员之前提供检查前提条件的方法,以便用户可以编写不会抛出异常的代码。

用于检查另一个成员的前提条件的成员通常被称为测试者,实际完成工作的成员称为实施者。

有些情况下,Tester-Doer模式可能会产生不可接受的性能开销。在这种情况下,应考虑所谓的Try-Parse模式(有关更多信息,请参阅例外和性能)。

答案 2 :(得分:0)

使用异常通常会导致更高的开销,滥用它们可能会降低应用程序的速度。没有什么例外关于查找没有查询的记录,所以我肯定建议返回null。

所以不,使用正常控制流的异常不是一个好习惯。