Scala错误处理:尝试还是要么?

x1a*_*1a0 6 error-handling scala

给定UserService中的方法:update这里处理错误/异常的最佳方法是什么?

选项A:

def update(...): Try[User]
Run Code Online (Sandbox Code Playgroud)

这样,我需要定义我的自定义异常,并在需要时将它们放入函数体中.大多数这些异常都是业务错误(例如,user_id无法更改等).这里的重点是无论引发什么异常(业务错误,网络异常,DB IO异常等),以同样的方式对待它们并且只返回Failure(err)- 让上层处理它们.

选项B:

def update(...): Either[Error, User]
Run Code Online (Sandbox Code Playgroud)

这是无异常的方式.在函数体中,它捕获所有可能的异常并将它们转换为Error,并且对于业务错误,只返回Left[Error].

使用Try对我来说似乎是一种更自然的方式,因为我想处理错误.Either是一个更通用的东西 - Either[Error, T]只是一个特例,我认为Try是为这个特殊情况发明的.但我也读到我们应该避免使用异常进行错误处理......

那么,哪种解决方案更好,为什么呢?

Gab*_*lla 6

没有银弹.

正如您已经注意到的,Try它只是一个更专业的版本Either,其中Left类型是固定的Throwable.

Try 如果你需要实现外部(也许是java)库抛出的异常,它可能是一个很好的选择,因为它的构造函数会自动捕获它们.

另一个优点Try是它有mapflatMap,所以你可以直接在for-comprehensions中使用它,而Either你必须明确地投射right案例.无论如何,有很多替代实现具有"右偏",可能scalaz \/类型是最受欢迎的.

话虽这么说,我通常使用\/或几乎相当Validation(都来自scalaz),因为我喜欢有能力返回不扩展的错误Throwable.

它还允许更精确的错误类型,这是一个巨大的胜利.