Comprendre les dépendances… Visuellement!

Montrez vos mains, combien d’entre nous comprennent vraiment comment votre outil d’automatisation de construction génère son arbre de dépendances? Maintenant, baissez la main si vous comprenez parce que vous travaillez sur des outils d’automatisation de construction. C’était prévisible!

Une responsabilité frustrante des ingénieurs logiciels est de comprendre les dépendances de votre projet : quelles dépendances transitives ont été introduites et par qui ; pourquoi v1.3.1 est utilisé alors que v1.2.10 a été déclaré ; quelles ont été les conséquences des changements des dépendances transitives ; comment se produisent-elles plusieurs versions du même artefact?

Chaque ingénieur logiciel a pipé un arbre de dépendances dans un fichier texte, recherché des artefacts spécifiques, puis remonté pour identifier son origine. Pour tout projet autre que trivial, créer une carte mentale des dépendances est extrêmement difficile, voire impossible.

I faced this problem when starting a new job with a mature code base, presenting a challenge to assemble the puzzle pieces.  I’ve previously worked with graph databases and thought a graphical view of the dependency artifacts could be created using Neo4J, which resulted in DependencyLoader.

Note: ce n’est pas un tutoriel sur les bases de données graphes, ni ce tutoriel n’exige une formation en bases de données graphes. Si vous êtes intéressé, Neo4J propose tutoriels et livres blancs pour vous aider à démarrer.

Configurer l’environnement

Installer Java

Java 11 ou ultérieur est requis. Si ce n’est pas déjà le cas, installez votre OpenJDK préféré.

Installer Neo4J

Le tutoriel requiert une base de données Neo4J dans laquelle les informations de dépendance sont chargées, de préférence non partagée, car le chargeur purge la base de données avant chaque exécution.Vous avez été prévenu !

Neo4J fournit des sandbox personnelles, idéales pour des projets à court terme comme ce tutoriel.

Sinon, installez Neo4J localement sur votre ordinateur de bureau ou portable. Homebrew simplifie les installations sous MacOS :

Shell

 

brew install neo4j && brew services start neo4j

Avant de continuer, confirmez l’accès à votre base de données Neo4J en utilisant le navigateur, en utilisant soit le lien et les identifiants pour le sandbox Neo4J, soit localement à http://localhost:7474. Les identifiants par défaut pour une installation locale sont neo4j/neo4j; après une connexion réussie, vous êtes obligé de changer le mot de passe.

Cloner les dépôts

Le référentiel neo4j-gradle-dependencies contient les éléments pour charger les dépendances dans Neo4J. Ce tutoriel générera un graphe de dépendance pour spring-boot. Vous devez cloner ces deux référentiels.

Shell

 

Scott.Sosna@mymachine src% git clone [email protected]:scsosna99/neo4j-gradle-dependencies.git
Scott.Sosna@mymachine src% git clone [email protected]:spring-projects/spring-boot.git

Note : Gradle local n’est pas nécessaire car les deux référentiels utilisent le Gradle Wrapper, qui télécharge tous les composants nécessaires la première fois que le wrapper est utilisé. 

Générer des dépendances

DependencyLoader prend en entrée l’arborescence des dépendances générée par Gradle. Bien que plusieurs configurations puissent être chargées ensemble — par exemple, compileClasspath, runtimeClasspath, testCompileClasspath, testRuntimeClasspath — commencer avec une seule configuration est plus simple à naviguer, surtout pour un tutoriel.

Pour générer des dépendances pour toutes les configurations : 

  • gradle dependencies
  • ./gradlew dependencies

Pour générer des dépendances pour une seule configuration

  • gradle dependencies --configuration <configuration>
  • ./gradlew dependencies --configuration <configuration>

Générer les dépendances Spring Boot

Ce tutoriel crée un graphe de dépendances dans Neo4J en utilisant les dépendances compileClasspath de Spring Boot. À partir du répertoire où les dépôts ont été clonés, exécutez les commandes suivantes :

Shell

 

Scott.Sosna@mymachine src% cd spring-boot/spring-boot-project/spring-boot
Scott.Sosna@mymachine spring-boot% ./gradlew dependencies --configuration compileClasspath > dependencies.out

Le fichier dependencies.out contient les dépendances de la classe à la compilation pour Spring Boot.

Charger les Dépendances

Tout d’abord, confirmez l’URL de connexion et les informations d’identification d’authentification dans DependencyLoader.java et modifiez-les si nécessaire.

Exécutez les commandes suivantes pour charger les dépendances de Spring Boot dans Neo4j :

Shell

 

Scott.Sosna@mymachine spring-boot% cd ../../../neo4j-gradle-dependencies
Scott.Sosna@mymachine neo4j-gradle-dependencies% ./gradlew clean run  --args="../spring-boot/spring-boot-project/spring-boot/dependencies.out"

Lorsque cela réussit, les lignes de sortie de gradle sont :

Shell

 

Scott.Sosna@PVHY32M6KG neo4j-gradle-dependencies % ./gradlew clean run  --args="../spring-boot/spring-boot-project/spring-boot/dependencies.out"

> Task :compileJava
Note: /Users/Scott.Sosna/data/src/github/neo4j-gradle-dependencies/src/main/java/dev/scottsosna/neo4j/gradle/relationship/DependsOn.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.

> Task :run
SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Jun 02, 2023 6:19:22 AM org.neo4j.driver.internal.logging.JULogger info
INFO: Direct driver instance 1606286799 created for server address localhost:7687
dependencies.out completed.
Jun 02, 2023 6:19:23 AM org.neo4j.driver.internal.logging.JULogger info
INFO: Closing driver instance 1606286799
Jun 02, 2023 6:19:23 AM org.neo4j.driver.internal.logging.JULogger info
INFO: Closing connection pool towards localhost:7687

Deprecated Gradle features were used in this build, making it incompatible with Gradle 8.0.

You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.

See https://docs.gradle.org/7.5.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 3s

Afficher les Dépendances

Plusieurs outils sont disponibles pour afficher les graphes Neo4J, mais l’outil de navigateur intégré convient pour ce tutoriel.

Afficher l’Arbre Complet

La requête MATCH(a) RETURN a est l’équivalent relationnel de SELECT * FROM <table>

Afficher les Détails d’un Artifact

Chaque artefact trouvé crée un nœud dont les propriétés identifient l’artefact (groupId/artifactId) et son type, affiché dans le volet de droite.

Voir les détails d’une dépendance

Chaque dépendance est créée sous la forme d’une relation dont les propriétés identifient les spécificités de la dépendance : configuration, version spécifiée et configuration. La dépendance sélectionnée ci-dessous montre spring-security:spring-web dépend de io.micormeter:micrometer-observation, mais la version spécifiée 1.10.7 de spring-web a été résolue en version 1.11.0.

Parcourir les dépendances

Neo4J vous permet d’explorer le graphique nœud par nœud, vous permettant d’étendre manuellement le nœud du graphique nœud par nœud, offrant un moyen d’explorer des zones spécifiques de l’arbre des dépendances.

Supposons que vous souhaitiez comprendre les dépendances pour l’artéfact io.projectreactor.netty:reactor-netty-http. Tout d’abord, nous interrogerons Neo4J pour ce nœud spécifique.

Cypher

 

MATCH(a:Artifact {groupId: 'io.projectreactor.netty', artifactId: 'reactor-netty-http'}) RETURN a

En double-cliquant sur le nœud, vous voyez ses nœuds voisins — les artéfacts dont il dépend et les artéfacts dont il est dépendant.

Cette vue élargie du graphique montre un artéfact qui en dépend — la racine du projet avec un type d’artéfact PROJET et six autres dépendances dont il dépend.

Ensuite, double-cliquez sur io.netty:netty-code https://github.com/netty/netty/tree/4.1/codec-httpc-http pour afficher le niveau de dépendances suivant. Notez que, en plus des relations (dépendances) du nœud sélectionné, des relations supplémentaires pour les nœuds déjà présents sur le graphique peuvent être affichées.

Identifier un désalignement de version

La sortie des dépendances de Gradle indique l’endroit où la version spécifiée n’était pas la version résolue par Gradle. Les propriétés sur la dépendance (relation) peuvent être utilisées dans une requête Neo4J, restreignant les relations affichées et les artefacts attachés (nœuds).

Cypher

 

MATCH (a:Artifact)-[d:DEPENDS_ON]->(b:Artifact) WHERE d.specifiedVersion<>d.resolvedVersion RETURN a,b,d

Neo4J peut retourner des résultats sous forme tabulaire pour une revue plus aisée, si nécessaire.

Cypher

 

MATCH (a:Artifact)-[d:DEPENDS_ON]->(b:Artifact) WHERE d.specifiedVersion<>d.resolvedVersion RETURNa.name AS source, b.name AS dependency, d.specifiedVersion AS specified, d.resolvedVersion AS resolved

Information supplémentaire

mappings.out

Le fichier mappings.out vous permet de personnaliser le type d’artefact attribué à un nœud en fonction du groupId de l’artefact, le plus souvent pour identifier spécifiquement les artefacts créés par votre organisation.

Répertoire d’entrée

L’argument de ligne de commande pour DependencyLoader peut être un répertoire contenant plusieurs arbres de dépendances Gradle chargés dans la même base de données Neo4J. Cela aide à comprendre les dépendances de projets liés ayant des fichiers build.gradle séparés.

Contraintes et Omissions

Gradle identifie certaines dépendances comme Contraintes et Omissions. Actuellement, celles-ci ne sont pas chargées mais pourraient être facilement incluses, probablement en créant des propriétés supplémentaires pour les relations.

Source:
https://dzone.com/articles/understanding-dependenciesvisually