簡體   English   中英

scala中的異常處理

[英]Exception handling in scala

我正在使用Scala處理應用程序。 我試圖在應用程序中實現異常處理。 我嘗試使用Either來處理異常。 對於簡單的情況,似乎足以處理異常。 但是,當我需要通過連接從多個表中獲取結果時,異常處理產生的問題多於解決問題。 我的應用程序結構解釋如下:

將存儲庫模式用於定義所有數據庫交互操作的數據庫操作。 例如,我有一個中央存儲庫,它定義了findAllfindByIdinsertdeleteupdateexists等。我的findAll方法簽名已經改為Either[CustomException, List[TEntity]] ,類似的findById方法類型是Either[CustomException, Option[TEntity]]

現在假設,如果我需要在我的方法中從數據庫中獲取員工,我將執行以下操作:

def getVehicleById(id:Long) = {

val vehicle = repository.findById(id)
//i have one-to-one mapping with Employee table for the driver of the vehicle
val driver = empRepository.findById(vehicle.driverId)

}

現在車輛的類型將是Either[CustomException, Option[Vehicle]]和驅動程序的類型是Either[CustomException, Employee]

如果我在獲得結果后需要再做一些操作,我必須使用右/左案例然后再這樣做。 問題是,可能在Right的情況下,我可能需要與另一個表連接,這使得結果再次成為Either[CustomException, Entity] 如果在該操作中發生任何錯誤,我需要再次使用try catch塊。 我覺得當代碼復雜性增加時,這種處理變得非常難以管理,而且我將有很多鍋爐板代碼來處理這些情況,這違反了Scala原則本身。

所以我的問題是,如何在沒有太多鍋爐板代碼的情況下以更好的方式處理異常。

注意:我來自Java背景,現在只在Scala工作了幾個月。

編輯

使用Try添加示例代碼:此示例非常接近我的要求。

import scala.util._
def checkTry:Try[List[Int]] = Success(List(2))
def checkTryStr:Try[String] = Success("Asd")

def getVehicleWithDriver = for {
  a <- checkTry
  c <- a
  b <- checkTryStr
}yield {
  (c,b)
}
getVehicleWithDriver

但是使用bove代碼,我收到了編譯錯誤。

 Error:(9, 6) type mismatch; found : scala.util.Try[(Int, String)] required: scala.collection.GenTraversableOnce[?] b <- checkTryStr ^ Error:(9, 6) type mismatch; found : scala.util.Try[(Int, String)] required: scala.collection.GenTraversableOnce[?] b <- checkTryStr ^ Error:(8, 6) type mismatch; found : List[Nothing] required: scala.util.Try[?] c <- a ^ 

你想使用for / yield糖。 您可以在推桿的習慣得到.right上所有Either S,或@Gangstead表明,使用\\/從Scalaz。 (Scalaz當然有可怕的部分 - 我已經使用它4年了,我仍然被例如Strength嚇倒 - 但是完全有可能從簡單的部件開始並按照你的方式工作)。

for {
  vehicle <- repository.findById(id).right
  driver <- empRepository.findById(vehicle.driverId).right
  somethingElse <- somePossiblyFailingComputation.right
} yield somethingElse
//Don't need the .right if you're using Scalaz \/

其他重要提示:當您想要將有效函數應用於List時,您希望使用Scalaz traverse

vehicleList <- vehicleIdList.traverse(repository.findById) //assuming you're using \/
//might need a few .right if you're using Either

當你調用Java代碼可能拋出一個異常,使用scala.util.control.Exceptioncatching

val myEither = catching(classOf[SomeException]) either someJavaMethodThatThrows()
// (...).disjunction if you're using \/.

如果你需要在使用Either / \\/的同時使用另一種“有效的上下文”,你將不得不開始尋找monad變換器 ,但最好是先使用Either

希望有所幫助; 祝你好運,希望你喜歡斯卡拉。

看看Scalaz的分離\\/

警告:Scalaz是由鐵桿人寫的硬核scala。

看看Brendon McAdams(@Rit)關於“Scalaz'Gateway Drugs”的演講。 對於來自Java的程序員來說,他更加平易近人,而且他非常實用

你想使用Try ,而不是Either 它是一個monad,所以你可以mapflatMap它,或者用它for理解。 它實際上看起來很優雅。

def getVehicleWithDriver(id: String): Try [(Vehicle, Driver)] = for {
    vehicle <- repository. findById(id)
    driver <- empRepository.findById(vehicle.driverId)
} yield {
    (vehicle, driver)
}

暫無
暫無

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

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