[英]Exception handling in scala
我正在使用Scala处理应用程序。 我试图在应用程序中实现异常处理。 我尝试使用Either
来处理异常。 对于简单的情况,似乎足以处理异常。 但是,当我需要通过连接从多个表中获取结果时,异常处理产生的问题多于解决问题。 我的应用程序结构解释如下:
将存储库模式用于定义所有数据库交互操作的数据库操作。 例如,我有一个中央存储库,它定义了findAll
, findById
, insert
, delete
, update
, exists
等。我的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.Exception
的catching
:
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,所以你可以map
或flatMap
它,或者用它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.