… c’est souvent ne pas l’utiliser !
Tout commence sur twitter par @gboissinot qui se plaint du POM de log4j 1.2.15 qui tire une dépendance non disponible sur le repository central. Cela conduit à un échange avec @sanlaville et @ehsavoie sur l’utilité de définir une dépendance en tant qu’optionnelle dans un pom.
Dans la documentation Maven nous trouvons ceci :
Optional dependencies – If project Y depends on project Z, the owner of project Y can mark project Z as an optional dependency, using the “optional” element. When project X depends on project Y, X will depend only on Y and not on Y’s optional dependency Z. The owner of project X may then explicitly add a dependency on Z, at her option. (It may be helpful to think of optional dependencies as “excluded by default.”)
La question qui se pose donc est quel est le bon usage de l’attribut “optional” dans une dépendance ? Ma réponse est assez simple et peut paraître extrémiste, mais pour moi dans la majeure partie des cas l’attribut “optional” n’est pas utile et resulte d’une mauvaise organisation (architecture) du projet.
Souvent une dépendance est marquée comme optionnelle car une partie de notre livrable qui l’utilise n’est pas indispensable pour l’utilisateur. De ce fait, au lieu d’imposer à ce dernier de récupérer toutes les librairies qu’il n’utilisera peut-être pas, elles sont marquées optionnelles, et cela sera du ressort de l’utilisateur de rajouter dans son propre projet la dépendance manquante si il vient à l’utiliser. Pourquoi livrez-vous à l’utilisateur du code qu’il ne veut pas ? Le problème vient souvent de là !!! Rendre cette dépendance optionnelle, oblige l’utilisateur à avoir connaissance de son existence alors qu’il s’en fiche. Ce qu’il faut c’est rendre une partie de votre livrable optionnelle. Pour cela vous devez le découper en différents sous-modules : Il y en aura au moins un obligatoire et les autres pourront être ajoutés au besoin. On retrouve par exemple ce modèle lorsque vous livrez une API et différentes implémentations qui utilisent chacunes des dépendances différentes. Livrez d’une part votre API, et dans des modules séparés les diverses implémentations que vous proposez.
C’est cette erreur que log4J (mais ce ne sont pas les seuls) ont fait. Ils devraient externaliser dans des modules séparés les différentes implémentations de leurs Appenders, afin de laisser au choix aux utilisateurs de prendre ceux qui l’intéressent.
Bien sur cela peut entraîner la création de modules avec très peu de classes (voir une seule) mais c’est le prix à payer pour livrer une solution modulaire facilement utilisable.
Maven et sa gestion des dépendances transitive introduit une transformation notable dans notre conception des biliothèques. On est passé du “tout en un” (ex : gwt-dev.jar) au “au petits oignons” (ex : cxf et sa 50aine jars). La solution “tout en un” a déjà montré ses limites quand des conflits apparaissent, la solution petit-oignons nécessite .. un gestionnaire de dépendances 😉
Je me suis déjà posé la question de l’utilisation précise de optional. Sur un ou deux projets qui ne pouvaient être modularisés, je l’ai utilisé avec le mega commentaire qu’ils devaient être remis au runtime pour les projets nécessitant les fonctionnalité, ex: clustering donc jgroups.
Je suis assez d’accord avec Nicolas, trop de jars peut être pire qu’un seul, car soit ils finissent tous dans le classpath soit on peut en oublier lors du déploiement. Vivement OSGI et OBR 😉
Vive SLF4J et logback!