2014-12-02 59 views
2

爲什麼有些人使用scala的Either或scalaz的\/而不是使用Future的失敗狀態來代替scala.concurrent.Future中的失敗?未來[A]與未來[Throwable /A]

那麼您如何處理錯誤,以及如何將呼叫鏈接到快樂路徑上?


更新一些例子:

converting Akka's Future[A] to Future[Either[Exception,A]]

Scalaz Task - the missing documentation 這一個回答了爲什麼部分,並使用scalaz.EitherT的鏈接調用(?這對\/,那EitherTry)暗示,但我不知道是否應該使用Future.failed,在什麼條件下等,以及如何檢查失敗。

我不確定這是否是普遍的做法,這就是爲什麼我問。 :)

+0

這可能是一些稍微好一些的例子。 – 2014-12-02 23:30:16

回答

3

我對待Future的失敗狀態與我處理異常的方式相同:它們用於意外的故障,指示編程錯誤或系統故障,如OutOfMemoryError s。因此,除非是高水平的「重試整個任務」,否則預計不會被抓住或處理。

失敗的期貨不是非常類型安全的(失敗僅僅是Throwable),並且可以將這些系統級失敗與可以以可預測方式處理的更多語義失敗混爲一談。因此,如果我的系統中出現故障,例如Unauthorized,那麼我寧願將其表示爲Either,就像Future[Unauthorized \/ MessageData]。然後有三種可能的狀態:

  • Success(\/-(data)) - 成功
  • Success(-\/(unauthorized)) - 「預期」 的故障。我知道如何處理特定的事物,例如通過向用戶顯示特定的消息或返回特定的返回碼。不應該爲程序員引發警報。
  • Failure(throwable) - 意外的系統級故障。只能用通用的錯誤頁面或其他方式處理。應該啓動監視並提醒程序員。

我曾經使用monad變壓器來使構成快樂路徑更容易(即,EitherT[Future, Unauthorized, MessageData]),這工作得很好,但現在我正在尋找更通用的方法(我的scalaz-transfigure庫)。

4

我個人使用或者在未來,當我有「我可以期待的失敗」,並可以做些事情來恢復他們。特別是,如果我需要做出明確的以API

sealed trait UserServiceError 
case object UserDbNotAvailable extends UserServiceError 
case object UserNotFoung extends UserServiceError 

def getUser(id: Long): Future[UserServiceError \/ User] 

的外部用戶可能的故障信息此代碼是更爲明確,什麼都可能發生故障。在某些情況下,這可能很重要。

同樣可以與未來[用戶]和Future.recover但有關可能的故障這種情況下,信息可以實現不型(可以在文檔)

不過,我同意,這是很有爭議的設計決定,因爲Try已經設計用於故障處理。

+0

但是,如果您嘗試對結果進行處理,則無論如何,如果您收到User或UserServiceError,那麼它與「成功(用戶)」和「失敗(userServiceError)」上的模式匹配確實不同。 ? – benji 2014-12-03 03:05:22

+0

我在'未來[UserServiceError,User]]中看到的優點是,你可以期待你會得到什麼樣的錯誤,如果你使用了一個你沒有寫過的API,但是還有其他優點,這很好嗎? – benji 2014-12-03 03:06:51