我编写了一个函数,生成报告,然后将其作为电子邮件的附件发送。如果在此过程中出现错误,我不想用大量的关闭文件系统的调用来干扰这个函数。你们都怎么想?
// attempt to generate the report, any error will be wrapped in Failure(ex)
val op1 = Try {
DB.withConnection{ implicit c =>
generateReport(command.programId, token.claims)(output, c)
}
}
// use (abuse?) pattern matching to send the report if it generated succesfully
val op2 = op1 match {
case Success(_) => Try(sendReport(Address(user.email, user.first), file, command.created))
// if the op1 value is of type Failure(ex), carry it forward until after the temp files have been removed
case Failure(ex) => Failure(ex)
}
// the operations have either succeeded or failed, so clean up the filesystem
cleanUp(output, file)
// throw any exception that occurred along the way
op2.get假设抛出异常是此函数的合理设计选择,则调用过程期望抛出异常并优雅地处理它们。
发布于 2014-10-25 09:10:41
您可以考虑使用ARM (自动资源管理)来清理资源。在Scala中,有一个名为scala臂的库。
然后,您的代码可以被构造成如下所示:
import resource._
import scala.util.Try
for {
connection ← managed(DB.getConnection())
output ← managed(...)
file ← managed(...)
} {
val result = for {
report ← Try(generateReport(...)(output, connection))
sendResult ← Try(sendReport(..., file))
} yield sendResult
// throws exception from generateReport or sendReport
result.get
}清理资源的细节将由scala中的默认行为处理,或者如果需要定义自定义清理行为,则可以创建自己的资源特性实现。可以在资源的伴生对象中创建隐式对象。下面的代码片段显示了哪些方法可以被重写;只有close()实现是必需的:
class MyOutput {}
object MyOutput {
implicit object OutputResource extends Resource[MyOutput] {
override def open(r: MyOutput): Unit = super.open(r)
override def closeAfterException(r: MyOutput, t: Throwable): Unit = super.closeAfterException(r, t)
override def isFatalException(t: Throwable): Boolean = super.isFatalException(t)
override def isRethrownException(t: Throwable): Boolean = super.isRethrownException(t)
override def close(r: MyOutput): Unit = ???
}
}https://codereview.stackexchange.com/questions/61917
复制相似问题