2017-10-20 10 views
1

J'ai mon point d'entrée comme ceci:Comment cacher la gestion de la configuration de la fonction principale?

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

il ressemble le but principal de mon programme est de charger une configuration, ce qui est vrai, le cœur de mon programme est de doStuff. Comment représenter cela de manière explicite et cacher la configuration sous-jacente?

Je voudrais quelque chose comme ceci:

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

dans lequel est clair que le traitement de l'échec et le chargement de la configuration est tout simplement accessoire.

+0

Je dirais que tout becase vous appelez 'pureconfig.loadConfig' d'abord, cela signifie que c'est le but principal de votre programme. – mfirry

Répondre

1

L'un des moyens les plus courants d'utiliser PureConfig à partir de la méthode main de votre programme consiste à échouer rapidement en cas d'erreur. L'API fournit loadConfigOrThrow qui retourne la configuration si le chargement a été un succès et jette un ConfigReaderException autrement:

import pureconfig.loadConfigOrThrow 

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

La raison pour laquelle pureconfig.loadConfig retourne un Either est parce que configuration de chargement peut échouer. Either modèles à la fois l'échec cas, avec Left, et le cas de succès, avec Right. C'est bon pour une bibliothèque, parce que vous ne savez jamais où loadConfig sera appelé et par conséquent vous ne voulez pas jeter une exception . Bien que ceci soit vrai en général, lorsque loadConfig est utilisé à partir d'un procédé de "surface", par ex. main, en levant l'exception ou juste en sortant en cas d'échec de chargement de configuration est logique et c'est pourquoi pureconfig fournit loadConfigOrThrow.

Si vous ne voulez pas jeter exception ou si vous préférez un gestionnaire d'échec personnalisée , comme lectureUserAboutStuff, vous pouvez créer une aide :

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

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

Une dernière chose à garder à l'esprit est qu'un mineur problème avec ce code est que le code de sortie de l'application n'est pas affectée par échecs de configuration. Si vous souhaitez définir un code de sortie lorsque la configuration ne peut pas être chargé, puis changer main à

val configReaderFailureErrorCode = 42 

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

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

Wow! Réponse incroyable! – gurghet