在scala中正确使用Either,Try和Exception / ControlThrowable

use*_*955 5 error-handling scala exception-handling try-catch either

在我的Scala代码(库以及应用程序)我目前使用的混合OptionTry,当任一两个感觉更apropriate。

我倾向于实现“ doSomething”方法,该方法可以在返回值成功或在失败时成功Try。也就是说,它们可以包含引发的代码,或者当我“手动”检测到错误时,人为地创建a Throwable并返回a Failure。这些方法的返回值因此为Try[ReturnType]

现在,我读到创建异常在某种程度上不是最优的,因为它创建了堆栈跟踪(因此很慢),而我什至不需要。我还看到了使用的子类的示例ControlThrowable,这些示例不会创建堆栈跟踪,但是它们也没有消息,Try当然也不会捕获它。

现在我的具体问题是,我一般都主张EitherTry,当我想要做的运行时错误处理/方法的返回值,并使用Try在那里我真正需要的情况下,只能东西(如第三方代码)?
这样,我就不必创建笨拙的Throwables,而只需使用例如字符串in Left来产生错误。

所以基本上:

  • Option:日常使用的东西是否具有价值
  • Try:在方法内捕获异常,但不用作返回值
  • Either:通用返回值,包含错误(字符串)或成功值

这个概念行得通吗,还是有一种更可行/更通用的方法?

Jam*_*ley 4

正如特拉维斯·布朗在评论中所说,没有真正的惯例,这在很大程度上是一种文化问题。为了保持代码的可读性,一致性是最重要的。我见过的代码库:

  • 使用选项表示“None成功并且任何Some(...)包含错误消息”
  • 使用 Try 来返回包含空字符串的成功或包含错误消息的失败
  • 使用错误的方式(即Either[?, Throwable]

显然这些都不是好的做法,但只要你保持一致,这并不重要。我个人在娱乐和工作中使用的惯例是:

  • Option当值缺失时有效(例如,使用 playframework 解析 JSON 时)。
  • Try当尝试做一些可能会失败的事情时(除非它是在未来,在这种情况下我只使用.recover),我关心匹配异常类型,但也希望获得成功的结果(如果可用)。
  • Either当我不想在“失败”的情况下返回异常/可抛出的情况时(尽管说实话,这种情况很少见)。

无论我使用上述哪一种,我个人认为最好尽可能长时间地将其包裹起来。这会阻止代码中不必要的 Throwables 被抛出(哈哈),并且使调试变得更容易,因为没有任何隐藏getOrElse行返回默认值(这在大型代码库中可能会变得非常烦人)。

  • 谢谢你的评论。我决定按照我在问题中的建议去。使用“Try”捕获来自第三方的异常,使用“Either[A, B]”作为一般返回值,“A”是带有补充信息的自定义错误类型。与“通常”一样,只要允许不存在值,就使用“Option”。一般来说,我根本避免使用异常,所以从不抛出或创建它们。 (2认同)