Le but de cet exercice est de voir qu'une interface ne sert pas uniquement à abstraire des classes
représentant des données mais aussi à abstraire la façon dont un code doit s'exécuter.
Pour le programme, l'URI peut venir de différents endroits, elle peut être spécifiée
sur la ligne de commande, sous forme d'une propriété "uri" à l'intérieur d'un fichier de
properties,
sous forme d'une variable d’environnement, etc...
Le code suivant correspond, à peu près, à ce que l'on pourrait écrire trouver cette URI.
URI uri;
if (args.length != 0) {
uri = URI.create(args[0]);
} else {
var path = Path.of("healthcheck.txt");
if (Files.exists(path) {
uri = URI.create(extractValueFromProperties(path));
} else {
var uriValue = System.getenv("HEALTH_CHECK_URI");
if (uriValue != null) {
uri = URI.create(uriValue);
} else {
uriValue = System.getProperty("healthCheckURI");
if (uriValue != null) {
uri = URI.create(uriValue);
}
}
}
}
Le code précédent n'est pas faux en soi (enfin un peu quand même... voir plus loin),
mais plus on enchaîne les
if ... else, plus
il devient incompréhensible. En effet, au lieu d'expliquer
de façon déclarative quel est le résultat que l'on veut obtenir (un peu comme un cahier des charges), on explique comment il faut faire pour arriver à ce résultat.
On voudrait plutôt écrire un code équivalent qui serait le suivant.
var finder = fromArguments(args)
.or(fromPropertyFile(Path.of("healthcheck.txt"), "uri"))
.or(fromMapGetLike("HEALTH_CHECK_URI", System::getenv))
.or(fromMapGetLike("healthCheckURI", System::getProperty));
var uri = finder.find().orElseThrow();
Pour cela, nous avons besoin de créer une interface
URIFinder qui correspond au type de retour des méthodes
from*. Les méthodes
from* seront des méthodes
factories qui créent et renvoient un objet de ce type et la méthode
or une méthode d'instance.
Note: dans l'exemple les méthodes
from* sont importées grâce à un
import static
pour éviter la répétition du nom de la classe qui les contient.