Bonnes pratiques Maven

Fermé
Jithel Messages postés 843 Date d'inscription mercredi 20 juin 2018 Statut Membre Dernière intervention 31 août 2021 - Modifié le 23 avril 2019 à 23:48
Jithel Messages postés 843 Date d'inscription mercredi 20 juin 2018 Statut Membre Dernière intervention 31 août 2021 - 27 avril 2019 à 22:56
Bonjour,

Une petite réflexion à propos de la gestion des dépendances Maven. Selon ce site : https://books.sonatype.com/mvnex-book/reference/multimodule-sect-simple-parent.html, il est intéressant d'utiliser une architecture Maven en multi-module avec une hiérarchie de module.

Ma réflexion est à propos des dépendances vers des librairies tiers comme par exemple JUnit (ou Log4J). Dans ce site, il est suggéré de mettre les librairies "universelles" au niveau du module parent pour que les modules enfants en héritent. Cependant, je vois un inconvénient plus lourd qu'un avantage

Avantage :
- Tous les projets dépendants de cette librairie n'auront pas besoin de la déclarer dans le POM

Inconvénient :
- Une application web, module enfant de ce parent, va hériter de JUnit alors que c'est une dépendance qui n'a rien à voir avec le web.

Ma suggestion consiste à déclarer deux enfants à ce parent : backend et frontend.
Dans backend, on y mets tous les modules en rapport avec Java et dans son pom.xml JUnit et Log4J.
Dans frontend, on y mets tous les modules en rapport avec le langage web et pas de dépendances a priori dans son pom.xml.

Une autre suggestion est de garder la structure actuelle (un parent et les enfants sont web + Java) mais dans ce cas, ne pas déclarer JUnit au niveau du parent mais unitairement dans chaque projet qui en a besoin spécifiquement. Cependant, Maven ira chercher X fois la même dépendance, ce qui n'est pas pratique.

Un avis ? Des pistes pour ma réflexion ?

1 réponse

KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015
24 avril 2019 à 13:31
Bonjour,

Dans le Dependency Mechanism, tu n'envisages que les Transitive Dependencies, mais pour ta réflexion il faudrait considérer le Dependency Management et les Dependency Scopes.

JUnit par exemple devrait être défini avec
<scope>test</scope>
afin de n'être utilisé que dans les phases de tests, mais sans être ajouté au livrable de runtime.

Remarque : tu pourrais aller plus loin dans la modularisation de ton projet, le back ne doit pas dépendre du front et le front ne devrait pas dépendre du back, cependant ils peuvent manipuler des objets communs, en particulier les interfaces des web services et leurs DTO, qui seraient à mettre dans un module à part.
Tu pourrais également isoler les accès aux base de données, pour faire une ségrégation forte des dépendances et avoir une architecture multi-tiers propre.
0
Jithel Messages postés 843 Date d'inscription mercredi 20 juin 2018 Statut Membre Dernière intervention 31 août 2021 171
24 avril 2019 à 22:51
Ma réflexion se base en fait sur les transitive dependencies. En effet, doit-on faire confiance à un parent pour nous fournir une librairie dont on a besoin ou doit-on déclarer soit même dans notre pom les dépendances dont nous avons besoin ?

Par exemple, je suis sur un projet côté service. Mon code fait appel à aspectj. Cependant, j'ai déjà importé spring-core qui lui-même rapatrie aspectj. Dois-je déclarer aspectj dans mon pom ou dois-je faire confiance à la transitivité ? Le problème se pose le jour où spring-core pour une raison quelconque décide de ne plus fournir par transitivité aspectj. On se retrouve à devoir faire une mise à jour pour ajouter aspectj dans le pom (qui ne serait pas arrivé si on l'avait fait avant).
0
KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024 3 015 > Jithel Messages postés 843 Date d'inscription mercredi 20 juin 2018 Statut Membre Dernière intervention 31 août 2021
24 avril 2019 à 23:45
"On se retrouve à devoir faire une mise à jour pour ajouter aspectj dans le pom (qui ne serait pas arrivé si on l'avait fait avant)"
Ce problème n'arriverait que si tu décides de mettre à jour spring-core dans une version qui n'utilises plus aspectj, mais l'opération de mise à jour qui t'obligerait à ajouter aspectj est celle qui consiste à modifier spring-core, en aucun cas aspectj ne disparaîtra tout seul si tu ne changes rien à spring-core.

"doit-on faire confiance à un parent pour nous fournir une librairie dont on a besoin ou doit-on déclarer soit même dans notre pom les dépendances dont nous avons besoin"
Je dirai qu'il vaut mieux les déclarer toi même et éviter d'utiliser des bibliothèques qui sont obtenus par transitivité uniquement pour faire fonctionner le code de la dépendance ajoutée, pas celui de ton code.

Attention aux versions ! Exemple (un grand classique avec Spring) :
Tu ajoutes une dépendance A qui ramène transitivement X, puis une dépendance B qui ramène transitivement Y, il peut arriver que X et Y comportent les mêmes classes mais dans des versions différentes et que "aléatoirement" ton programme utilisera tantôt X pour faire fonctionner A et B, tantôt Y pour faire fonctionner A et B, mais tu n'auras pas X qui fait fonctionner A et en même temps Y qui fait fonctionner B.
Remarque : C'est tout l'intérêt des modules introduit par Java 9 qui règlent une partie du problème.

Plusieurs manières d'éviter ce genre de problèmes :
  • bien découper les modules de ton projet pour limiter le nombre de dépendances dans chaque module, moins il y aura de dépendance, moins il y a de risque de conflits pour un module donné
  • contrôler avec
    mvn dependency:tree
    d'éventuels conflits de version et les gérer en excluant les imports transitifs en trop (cela demande une analyse poussée pour savoir quelle est la bonne version)
  • utiliser au maximum les dépendances ajoutées, si une bibliothèque A dépend de B et que tu as besoin de B, c'est peut-être que tu utilises mal les fonctionnalités de A.
0
Jithel Messages postés 843 Date d'inscription mercredi 20 juin 2018 Statut Membre Dernière intervention 31 août 2021 171 > KX Messages postés 16734 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 24 avril 2024
27 avril 2019 à 22:56
Vis-à-vis de la gestion des dépendances, ça me paraît plus clair :
1. Ne pas compter sur une dépendance transitive pour faire fonctionner le code qui en a besoin mais l'importer
2. Importer une bibliothèque transitive peut simplement vouloir dire que j'utilise mal les fonctionnalités de la dépendance directe

Avant de passer le sujet en résolu, tu aurais des bonnes sources externes sur lesquelles je peux m'appuyer ? Livre ? Site ? Vidéo ? Conférence ?
0