簡體   English   中英

在公共/開源Scala API中使用Try或Either進行錯誤處理是否存在問題?

[英]Are there problems using Try or Either for error handling in public/open source Scala APIs?

我注意到許多開源Scala API使用Future (如Slick)或Java風格的異常處理(如spray-json)而不是TryEither

在沒有長時間運行或異步的簡單開源API中返回TryEither是否存在問題? 我應該避免這些,如果是這樣,我應該使用什么呢?

(顯然,我更傾向於使用核心Scala API而不是第三方庫,例如Scalaz,以避免迫使下游用戶使用這些庫。)

Try包裝非異步操作的異常是很好的。
但是,我認為使用異常實例返回非異常錯誤條件是不正確的 當API是異步的並且使用Future時,我也是這樣。 異常錯誤與業務錯誤混合容易導致API客戶端(也就是我:)的錯誤處理不正確/不充分。

如果您仍然決定使用例外來表示您的業務錯誤,請記住異常帶有隱藏價格:構建堆棧跟蹤。 如果您創建自己的業務異常並混合使用scala.util.control.NoStackTrace則可以減輕這種scala.util.control.NoStackTrace

Scala標准庫中的默認Either實現是無偏的,這意味着區分成功和失敗的情況僅依賴於約定:

右是正確的(正確),因此左錯(錯誤)。

不偏不倚的一面也讓追隨“快樂”的道路變得痛苦(或使錯誤恢復脫穎而出)

此時您的最佳選擇(scala 2.11.6和相應的標准庫)將根據您的依賴關系和要向用戶公開的API而有所不同,但它不會來自scala標准庫。

  • 如果您已經嚴重依賴scalaz,則Scalaz Validation\\/是一個選項
  • Scalactic的Or類型是一個很好的輕量級解決方案,如果你不想拉入整個scalaz。 它是成熟的,是從金字塔中提取出來的
  • (來自評論) Accord可能是一個選項,但我不太了解它與其他人比較。
  • (來自評論) Cat的Xor可能是一個選項,但我不太了解它與其他人比較。
  • Rapture modes允許您讓API的客戶端決定他想要取回的類型(例如,這種方法在parboiled2中使用)。 我不知道圖書館作者或編譯時間的成本是多少。

您可能已經依賴於提供自己的validation類型的庫。 例如,play-json有一個JsResult類型,其驗證類似於能力。 根據您正在處理的內容重用類型可能是有意義的。

有一個進展和專家組呼叫至偏壓任一類型添加到Scala的標准庫。 上述兩種解決方案具有已經能夠累積錯誤的額外好處。

在以下情況下返回Try [T]:正確的結果和不正確的結果(即錯誤)之間存在語義差異。 這是因為:

  • 嘗試是偏右的(它適用於地圖,平面地圖和for-comprehensions)。

  • 失敗案例是一個Throwable,這很重要,因為throwable總是清楚地意味着甚至超出了代碼邊界的錯誤。

警告 :堆棧跟蹤生成有時是一種開銷,但並非總是如此! 在過早優化代碼之前要三思而后行:堆棧跟蹤帶有許多有用的調試信息。 如果您以后發現您確實需要跳過堆棧跟蹤生成,沒問題:使用with NoStackTrace如上所示。

def validate(s:String):Try[String] = Option(s).filter(!_.isEmpty).map(Try(_)).getOrElse(new Exception("bad input") with NoStackTrace 

使用[L,R]時 :兩種情況都可以接受,但它們是互斥的(即[Integer,Float])。 出於這個原因,盡管Scalaz的家伙們不得不對此發表評論,但我相信這兩者都是公正的。

def parseNum(s:String):Either[Int,String] = Try(parseInt(s)).map(Left(_)).getOrElse(Right(s))

類似於Either 時使用Tuple ,但是當你有N時,非互斥值(你知道所有都有用)

def parseAndReturn(s:String):(Integer,String) = (parseInt(s), s) 

T可以為空時,或者當你處於與Try [T]相同的情況時, 返回一個選項[T] ,但是你沒有給出關於為什么出錯的原因。

def attemptToparse(s:String):Option[Result] = Try(parse(s)).toOption

我同意Try是捕獲/通知異常,而不是返回業務/驗證錯誤。 Scalaz是一個非常好的選擇,但是如果你不想依賴它,我認為Either是好的,不偏不倚是令人討厭但不是交易破壞者恕我直言:一旦你建立了Right是有效結果的約定,你可以“正確偏見”它與.rightProjection (如果你只想處理錯誤,你可以做左投影。另一種選擇是使用Either的折疊fold[X](fa: (A) ⇒ X, fb: (B) ⇒ X): X myEither.fold(dealWithErrors _, happyPath _ ) fold[X](fa: (A) ⇒ X, fb: (B) ⇒ X): X喜歡myEither.fold(dealWithErrors _, happyPath _ ) (雖然這意味着dealWithErrorshappyPath返回相同的類型)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM