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

问题描述 投票:4回答:1

在我的scala代码(库和应用程序)中,我目前使用OptionTry的混合物,只要两者中的任何一个感觉更合适。

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

现在我读到创建异常有点不理想,因为它创建了一个堆栈跟踪(因此很慢),我甚至不需要它。我还看到了使用ControlThrowable的子类的示例,它们没有创建堆栈跟踪,但是它们也没有消息,而Try当然也不会捕获它。

现在我的具体问题是,当我想做运行时错误处理/方法返回值时,我是否应该优先使用Either而不是Try,并且仅在我实际需要捕获某些内容的情况下使用Try(例如第三方代码)? 这样我就不必创建笨拙的Throwables,而只是使用例如Left中的字符串表示错误。

所以基本上:

  • Option:每天使用普通有价值的东西
  • Try:捕获方法中的异常,但不用作返回值
  • Either:通用返回值,包含错误(字符串)或成功值

这个概念会很好用,还是有更可行/通用的方法?

scala error-handling exception-handling try-catch either
1个回答
4
投票

正如Travis Brown在评论中指出的那样,没有真正的惯例,它在很大程度上是一种文化的东西。为了保持代码可读性,一致性是最重要的。我见过代码库:

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

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.