最好在获取URL时返回None或抛出异常?

时间:2011-07-31 17:24:27

标签: scala exception throw idiomatic scala-option

我有一个Scala帮助器方法,当前尝试获取URL并返回带有该网页HTML的Option [String]。

如果有任何异常(格式错误的网址,读取超时等等)或者如果有任何问题,则返回“无”。问题是,抛出异常以便调用代码可以记录异常或者在这种情况下返回None是否更好?

3 个答案:

答案 0 :(得分:32)

创建异常非常昂贵,因为必须填充堆栈跟踪。投掷和捕获异常也比正常回报更昂贵。考虑到这一点,您可能会问自己以下问题:

  • 您是否要强制调用者处理错误?如果是,请不要抛出异常,因为Scala没有强制调用者捕获的检查异常机制它们。

  • 如果出现错误,您是否要包含失败原因的详细信息?如果没有,您只需返回Option[A],其中A是您的退货类型,然后您有Some(validContent)None,没有其他说明。如果是,您可以返回Either[E, A]或Scalaz Validation[E, A]之类的内容。所有这些选项都会强制调用者以某种方式展开结果,同时可以根据需要自由处理错误E。现在E应该是什么?

  • 您是否希望在发生故障时提供堆栈跟踪?如果是,您可以返回Either[Exception, A]Validation[Exception, A] 。如果您真的使用例外,则需要使用Try[A],其中两个可能的情况是Failure(exc: Throwable)Success(value: A)。请注意,您当然会产生创建throwable的成本。如果没有,您可以返回Either[String, A](并且要特别小心,以便记住Right在此处是成功还是失败 - Left通常用于错误,Right用于“正确”的价值 - Validation可能更清晰)。如果您希望可选返回堆栈跟踪,您可以使用Lift的Box[A]Full(validContents)Empty,无其他说明(非常类似于{ {1}}到此为止),或指示可以存储错误字符串和/或throwable(以及更多)的Option[A]

  • 您是否想要提供有关失败原因的多种指示?然后返回Failure。如果你经常这样做,你可能想要使用Scalaz和Either[Seq[String], A]代替,这提供了一些其他不错的好东西。查找有关它的更多信息或查看these usage examples

答案 1 :(得分:1)

我认为在这种情况下,如果记录异常很重要,那么一定要抛出异常(并且可能只返回String而不是选项)。否则你也可以只返回None。一个警告 - 由于您没有预见到的其他原因可能会有例外情况,在这种情况下,制作一个全部的代码可能是危险的。

你可以做的一件事就是像Lift的Box系统。 Box实际上是一个选项,但添加了一些功能:Full就像SomeEmpty就像None,但是却走了一步进一步,有一个Failure,就像Empty但有理由/消息。

答案 2 :(得分:0)

一般的经验法则是“如果你能处理异常,就处理它”。所以没有足够的背景来猜测。您可以使用tryFetchUrl / fetchUrl方法对。