【发布时间】: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/cats 的implicit 替换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