在scala中选择正确的异常处理

Jul*_*éon 4 coding-style scala exception-handling

我是Scala的新手,对于处理异常的各种方式以及寻找有关该主题的最佳实践建议感到有些困惑.我正在编写一个使用现有阻止SDK检索客户的简单方法.可能的结果是:

  1. 找到了客户
  2. 找不到客户(从SDK返回为NotFoundException)
  3. 与远程服务器通信时出错(SDK引发其他一些异常)

所以我希望我的方法有一个返回类型Future[Option[Customer]],并返回上面的每个案例:

  1. 成功的未来:一些(客户)
  2. 成功的未来:没有
  3. 失败的未来

这是我用try/catch写的:

private def findCustomer(userId: Long): Future[Option[Customer]] = future {
  try {
    Some(gateway.find(userId))
  } catch {
    case _: NotFoundException => None
  }
}
Run Code Online (Sandbox Code Playgroud)

这工作正常,对我来说似乎很干净,但似乎并不是真正的"Scala方式" - 我被告知要避免使用try/catch.所以我一直在寻找一种方法来改写它Try.

这里有2个变体(我认为)表现完全相同,使用a Try.

变式A:

private def findCustomer(userId: Long): Future[Option[Customer]] = future {
  Try(
    Some(gateway.find(userId))
  ).recover {
    case _: NotFoundException => None
  }.get
}
Run Code Online (Sandbox Code Playgroud)

变式B:

private def findCustomer(userId: Long): Future[Option[Customer]] = future {
  Try(
    Some(gateway.find(userId))
  ).recover {
    case _: NotFoundException => None
  }
} flatMap {
  case Success(s) => Future.successful(s)
  case Failure(f) => Future.failed(f)
}
Run Code Online (Sandbox Code Playgroud)

我不是A的忠实粉丝(尽管它比B更简洁),因为它.get看起来有点危险.B绝对是最明确的,但将Try案例映射到相应的Future结果似乎很无聊.

经验丰富的Scala程序员如何写这个?

Ion*_*tan 5

我认为您使用的初始版本try/catch非常好,因为它是现有SDK的包装器.

或者,您可以使用以下recover方法Future:

def findCustomer(userId: Long): Future[Option[Customer]] =
  Future(Option(gateway.find(userId))).recover {
    case e: NotFoundException => None
  }
Run Code Online (Sandbox Code Playgroud)