在我的scala代码(库和应用程序)中,我目前使用Option
和Try
的混合物,只要两者中的任何一个感觉更合适。
我倾向于实现“doSomething”方法,这些方法可以通过返回值或使用Try
失败而成功。也就是说,它们可以包含抛出的代码,或者,当我“手动”检测到错误时,我人为地创建了一个Throwable
并返回一个Failure
。因此,这些方法的返回值是Try[ReturnType]
。
现在我读到创建异常有点不理想,因为它创建了一个堆栈跟踪(因此很慢),我甚至不需要它。我还看到了使用ControlThrowable
的子类的示例,它们没有创建堆栈跟踪,但是它们也没有消息,而Try
当然也不会捕获它。
现在我的具体问题是,当我想做运行时错误处理/方法返回值时,我是否应该优先使用Either
而不是Try
,并且仅在我实际需要捕获某些内容的情况下使用Try
(例如第三方代码)?
这样我就不必创建笨拙的Throwable
s,而只是使用例如Left
中的字符串表示错误。
所以基本上:
Option
:每天使用普通有价值的东西Try
:捕获方法中的异常,但不用作返回值Either
:通用返回值,包含错误(字符串)或成功值这个概念会很好用,还是有更可行/通用的方法?
正如Travis Brown在评论中指出的那样,没有真正的惯例,它在很大程度上是一种文化的东西。为了保持代码可读性,一致性是最重要的。我见过代码库:
None
是成功的,任何Some(...)
都包含错误消息”Either[?, Throwable]
)显然这些都不是好的做法,但只要你保持一致就没那么重要。我个人在娱乐和工作中使用的惯例是:
Option
用于何时丢失值(例如,使用playframework解析JSON时)。Try
在尝试做一些可能失败的事情时(除非它在未来,在这种情况下我只使用.recover
),我关心匹配异常的类型,但也希望成功的结果可用。Either
,当我不想在我的“失败”情况下返回Exception / Throwable时(尽管说实话这很少见)。无论我使用上述哪种,我个人认为最好尽可能长时间地保持它。这样可以阻止在代码中抛出不必要的Throwables(haha),并使调试变得更容易,因为没有任何隐藏的getOrElse
行返回默认值(这在大型代码库中会非常烦人)。