scala - 如何重构抛出异常的函数?

标签 scala exception refactoring

假设我正在重构这样的函数:

def check(ox: Option[Int]): Unit = ox match {
  case None => throw new Exception("X is missing")
  case Some(x) if x < 0 => throw new Exception("X is negative")
  case _ => ()
}

我想摆脱异常,但我需要保持 check 签名和行为不变,所以我考虑了一个纯粹的实现 - doCheck:

import scala.util.{Try, Success, Failure}

def doCheck(ox: Option[Int]): Try[Unit] = ???

def check(ox: Option[Int]): Unit = doCheck(ox).get

现在我正在实现 doCheck 如下:

def doCheck(ox: Option[Int]): Try[Unit] = for {
  x <- ox toTry MissingX()
  _ <- (x > 0) toTry NegativeX(x)
} yield ()

使用以下隐式:

implicit class OptionTry[T](o: Option[T]) { 
  def toTry(e: Exception): Try[T] = o match {
    case Some(t) => Success(t)
    case None    => Failure(e)
  }
}

implicit class BoolTry(bool: Boolean) { 
  def toTry(e: Exception): Try[Unit] = if (bool) Success(Unit) else Failure(e) 
}

隐式肯定会添加更多代码。我希望有一天能用来自 scalaz/cats 的隐式替换OptionTry,并且也许能找到BoolTry的类似物。

最佳答案

您可以使用贷款模式进行重构,然后尝试

def withChecked[T](i: Option[Int])(f: Int => T): Try[T] = i match {
  case None => Failure(new java.util.NoSuchElementException())
  case Some(p) if p >= 0 => Success(p).map(f)
  case _ => Failure(
    new IllegalArgumentException(s"negative integer: $i"))
}

然后可以如下使用。

val res1: Try[String] = withChecked(None)(_.toString)
// res1 == Failure(NoSuchElement)

val res2: Try[Int] = withChecked(Some(-1))(identity)
// res2 == Failure(IllegalArgumentException)

def foo(id: Int): MyType = ???
val res3: Try[MyType] = withChecked(Some(2)) { id => foo(id) }
// res3 == Success(MyType)

关于scala - 如何重构抛出异常的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37906243/

相关文章:

scala - 零参数的抽象类和没有参数的抽象类有什么区别?

scala - sbt 程序集中的合并策略和缺少应用程序加载程序

java - 自动化性能测试框架

c# - Java 等效于 C# 'using' 语句

delphi - 有关重构一些不良代码的建议

scala - 将 UDF 传递给方法或类

c++ - 我是否也仅在函数头或声明中指定异常类型? (C++)

swift - “ fatal error :在展开可选值时意外发现nil”是什么意思?

c++ - 每个编译单元是否只有一个未命名的命名空间?

refactoring - 如何重构多个复杂的 if-else 分支