【问题标题】:How to refactor a function that throws exceptions?如何重构抛出异常的函数?
【发布时间】:2016-06-19 10:28:02
【问题描述】:

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

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 ()

使用以下implicits

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) 
}

有意义吗?

附: implicits 肯定会添加更多代码。我希望有朝一日用来自scalaz/catsimplicit 替换OptionTry,也许可以找到BoolTry 的类似物。

【问题讨论】:

  • 我觉得你让事情变得更复杂了。如果 check 不再抛出异常,那么调用它的目的是什么?
  • Success(Unit) 应该是 Success(())
  • @mavarazy check 确实会引发异常。重构不会改变原来的 check 行为。 (更新了问题以使其清楚)。
  • @Łukasz 你能解释一下为什么Success(())Success(Unit) 更好吗?
  • 因为Unit 是伴生对象并且具有Unit.type 类型,而()Unit 类型的唯一值。您的代码之所以有效,是因为 () 是在 Unit 表达式之后隐式添加的。同样给出def a = 5 并说val t: Try[Unit] = Success(a) 给出Success(())

标签: scala exception refactoring option


【解决方案1】:

您可以使用贷款模式和Try 进行重构。

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)

【讨论】:

    猜你喜欢
    • 2019-07-11
    • 2015-08-26
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 2012-10-28
    • 2012-11-19
    • 2013-04-03
    相关资源
    最近更新 更多