Bonjour à tous,
Dans le cadre d'un développement d'application modulaire, je souhaiterais trouver le "meilleur" moyen de charger des paramètres définis par le développeur du module. Je m'explique
Supposons un core sur lequel je branche un ensemble de modules. Chacun de ces modules possède (forcément) un ensemble de méthodes dont la signature est invariante (type plug() et unplug() par exemple). Maintenant, il arrive que certains de ces modules définissent un ensemble d'attributs qui, dans l'idéal, pourraient être initialisés via une configuration définie par l'utilisateur.
Malheureusement, je ne peux pas me permettre de demander à l'utilisateur de trifouiller un fichier de configuration (les Properties de l'API JavaSE dans le meilleur des cas), et pour cause : l'un de mes modules contiens des attributs qui sont des objets bien spécifiques (par exemple, une classe DataFile qui prend en constructeur un chemin vers un fichier ou un File, et un objet Class<T> (donc DataFile(path, X.class)). Alors bien sûr, je pourrais définir des options dans un fichier Properties du type
dataPath="le chemin"
parserClass="nom de la classe"
et faire appel à un Class.forName(), mais je ne trouve pas cette façon de faire "élégante".
Au lieu de procéder de la sorte, j'ai préféré définir une annotation @Configurable(ignore = {attributs à ignorer pour la configuration}, optional = {attributs optionnels}) à placer au niveau de la définition de la classe (du module), permettant de le définir comme étant Configurable (no way ?!).
Ensuite, lors du chargement de mon core, et plus précisément lors de la découverte des modules installés (sous format .jar), je vérifie si le module possède cette annotation.
Si tel est le cas, j'appelle une méthode configure() sur mon module prenant en paramètre une Map<String, Object>, dont chaque clé correspond en fait au nom d'un attribut de mon module. Par exemple, supposons que j'insère dans cette map un couple de type ("file1", new DataFile("./test.txt", SomeClass.class)). Vous l'aurez donc deviné, je procède à l'initialisation de ces objets par introspection : à chaque clé de la map correspondant au nom de l'attribut de mon module, j'attribue à ce dernier la valeur associée à la clé dans ma map (j'utilise le type Object histoire d'être sûr qu'au moins je pourrais mettre n'importe quoi).
Cette façon de procéder marche très bien mais possède un seul inconvénient qui, j'avoue, me chagrine un peu : il faut construire une telle map à fournir au module, ce qui peut être un peu pénible et rébarbatif, de plus que celle-ci demande forcément à être codée, alors que le paradigme du fichier de configuration relève plus de ce qui se fait aujourd'hui (mais offre moins de souplesse quant à la définition des paramètres à utiliser, car ne marche qu'avec des types String (ou du moins des flux de caractères)).
Je ne souhaite pas serialiser mes objets à utiliser non plus, car ceux-ci ne sont pas statiques, et leur valeur peut changer d'une exécution à l'autre de mon application.
Si jamais vous voyez ici un soucis de conception, ou une meilleure - voire la meilleure- façon de procéder, je suis grandement preneur de vos conseils avisés.
Bonne soirée à vous !
et merci d'avoir pris le temps de lire mon pavé
Partager