Как скрыть управление конфигурацией от основной функции?
У меня есть точка входа, как это:
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)
}
В котором ясно, что обработка сбоев и загрузка конфигурации является лишь аксессуаром.
1 ответ
Один из наиболее распространенных способов использования PureConfig из main
метод вашей программы заключается в быстром сбое в случае ошибки. API обеспечивает loadConfigOrThrow
который возвращает конфигурацию, если загрузка прошла успешно, и выдает ConfigReaderException
иначе:
import pureconfig.loadConfigOrThrow
def main(args: Array[String]): Unit = {
val conf = loadConfigOrThrow[Conf] // will throw if Conf cannot be loaded
doStuff(conf)
}
Причина по которой pureconfig.loadConfig
возвращает Either
это потому, что загрузка конфигурации может быть неудачной. Either
моделирует случай отказа, с Left
и случай успеха, с Right
, Это хорошо для библиотеки, потому что вы никогда не знаете, где loadConfig
будет вызван, и, следовательно, вы не хотите бросать исключение. Хотя это в целом верно, когда loadConfig
используется из "поверхностного" метода, например 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)