我正在使用Scala处理应用程序。我试图在应用程序中实现异常处理。我尝试使用Either
来处理异常。对于简单的情况,似乎足以处理异常。但是,当我需要通过连接从多个表中获取结果时,异常处理产生的问题多于解决问题。我的申请结构如下:
将存储库模式用于定义所有数据库交互操作的数据库操作。例如,我有一个中央存储库,用于定义findAll
,findById
,insert
,delete
,update
,exists
等我的{{ 1}}方法签名已更改为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]]
如果我在获得结果后需要再做任何操作,我必须使用右/左案例然后再这样做。问题是,可能在Right的情况下,我可能需要与另一个表连接,这使得结果再次成为Either[CustomException, Employee]
。如果在该操作中发生任何错误,我需要再次使用try catch块。
我觉得当代码复杂性增加时,这种处理变得非常难以管理,而且我将有很多锅炉板代码来处理这些情况,这违反了Scala原则本身。
所以我的问题是,如何在没有太多锅炉板代码的情况下以更好的方式处理异常。
注意:我来自Java背景,现在只在Scala工作了几个月。
修改
使用Try添加示例代码: 这个样本非常接近我的要求。
Either[CustomException, Entity]
但是使用bove代码,我收到了编译错误。
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
答案 0 :(得分:2)
您想使用for
/ yield
糖。您可以养成将.right
放在所有Either
上的习惯,或者@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
&#39; s catching
:
val myEither = catching(classOf[SomeException]) either someJavaMethodThatThrows()
// (...).disjunction if you're using \/.
如果您需要使用另一种有效的背景&#34;在使用Either
/ \/
的同时,您必须开始查看 monad变形金刚,但最好只使用{{ {1}}首先。
希望有所帮助;祝你好运,希望你喜欢斯卡拉。
答案 1 :(得分:1)
看看Scalaz的分离\/
。
警告:Scalaz是由铁杆人写的硬核scala。
看看Brendon McAdams(@Rit)关于"Scalaz' Gateway Drugs"的演讲。对于来自Java的程序员来说,他更加平易近人,而且他非常实用
答案 2 :(得分:0)
您想使用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)
}