如何从主要功能中隐藏配置管理?

How to hide configuration management from the main function?

我的切入点是这样的:

def main(args: Array[String]): Unit = {
  pureconfig.loadConfig[Conf] match {
    case Right(conf) => doStuff(conf)
    case Left(fail) => lectureUserAboutStuff(fail)
  }
}

所以看起来我的程序的主要目的是加载一个配置,这是不正确的,我的程序的核心是doStuff

如何表达这个并隐藏卧底配置?

我想要这样的东西:

def main(args: Array[String]): Unit = {
  doStuff(conf)(failHandler)
}

其中很明显,故障处理和配置加载只是附属的。

从程序的 main 方法使用 PureConfig 的最常见方法之一是在出现错误时快速失败。如果加载成功,API 提供 loadConfigOrThrow 其中 returns 配置,否则抛出 ConfigReaderException

import pureconfig.loadConfigOrThrow

def main(args: Array[String]): Unit = {
  val conf = loadConfigOrThrow[Conf] // will throw if Conf cannot be loaded
  doStuff(conf)
}

之所以pureconfig.loadConfigreturns一个Either是因为 加载配置可能会失败。 Either 模型都失败了 案例 Left,成功案例 Right。这是 适合图书馆,因为你永远不知道在哪里 loadConfig 将被调用,因此您不想抛出一个 例外。虽然这通常是正确的,但当 loadConfig 是 从 "surface" 方法中使用,例如main,抛出异常或 在配置加载失败的情况下退出是有道理的, 这就是 pureconfig 提供 loadConfigOrThrow.

的原因

如果您不喜欢抛出异常或者您更喜欢自定义 失败处理程序,例如 lectureUserAboutStuff,您可以创建一个 帮手:

def loadConfig(): Option[Conf] = {
  val errorOrConf = pureconfig.loadConfig[Conf]
  errorOrConf.left.foreach(lectureUserAboutStuff)
  errorOrConf.toOption
}

def main(args: Array[String]): Unit =
  loadConfig().foreach(doStuff)

最后一件事要记住,这是一个小问题 代码是应用程序的退出代码不受 配置失败。如果你想设置一个退出代码 无法加载配置,然后将 main 更改为

val configReaderFailureErrorCode = 42

private def configFailureExit() =
  sys.exit(configReaderFailureErrorCode)

def main(args: Array[String]): Unit =
  loadConfig().fold(configFailureExit())(doStuff)