【问题标题】:Scala error handling: Try or Either?Scala 错误处理:Try or Either?
【发布时间】:2015-01-26 01:59:54
【问题描述】:

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

选项 A:

def update(...): Try[User]

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

选项 B:

def update(...): Either[Error, User]

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

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

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

【问题讨论】:

  • 我更喜欢Either,因为它允许您明确指出哪些错误类型是可能的,而不是使用Try 得到的通用Throwable。正如@Gabriele 所说,我更喜欢scalaz \/,因为它有一个更有用的map 构造。

标签: scala error-handling


【解决方案1】:

没有灵丹妙药。

正如您已经指出的,Try 只是Either 的更专业版本,其中Left 类型固定为Throwable

Try 可能是一个不错的选择,如果您需要具体化由外部(可能是 java)库抛出的异常,因为它的构造函数会自动捕获它们。

Try 的另一个优点是它具有mapflatMap,因此您可以直接在for-comprehensions 中使用它,而使用Either 您必须明确地投影right 案例。 无论如何,有很多带有“右偏”的替代实现,并且可能 scalaz \/ 类型是最受欢迎的。

话虽如此,我通常使用\/ 或几乎等效的Validation(均来自scalaz),因为我喜欢能够返回不扩展Throwable 的错误。

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

【讨论】:

    猜你喜欢
    • 2015-12-28
    • 1970-01-01
    • 1970-01-01
    • 2016-01-23
    • 1970-01-01
    • 1970-01-01
    • 2019-04-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多