Matrice de structure de dépendances (DSM)
Améliorer l'organisation du code avec la Dependency Structure Matrix
Introduction
La DSM (Dependency Structure Matrix) est un moyen compact de représenter et de naviguer à travers les dépendances entre composants. Pour la plupart des ingénieurs, parler de dépendances signifie parler de quelque chose qui ressemble à cela :

DSM sert à représenter les mêmes informations qu'un graphe.
- Les éléments d’en-tête de la matrice représentent les boîtes du graphe
- Les cellules non vides de la matrice correspondent aux flèches du graphe.
Par conséquent, dans la capture ci-dessous, le couplage de Net à Foundation est représentée par une cellule non vide dans la matrice et par une flèche dans le graphe.

Pourquoi utiliser deux façons différentes, graphe et DSM, pour représenter la même information ? Parce qu'il y a un compromis :
- Le graphe est plus intuitif mais peut devenir totalement incompréhensible lorsque le nombre de nœuds et d'arêtes augmente (quelques dizaines de boîtes peuvent suffire à produire un graphe trop complexe)
- DSM est moins intuitive mais peut être très efficace pour représenter des graphes larges et complexes. On dit que DSM évolue comparer au graphe.
Une fois les principes du DSM compris, on préfère généralement le DSM au graphe pour représenter les dépendances. Cela tient principalement au fait que le DSM offre la possibilité de repérer les motifs structurels d’un coup d’œil Ceci est expliqué dans la seconde moitié du présent document.
CppDepend offre Aide contextuelle pour expliquer à l'utilisateur ce qu'il voit sur la DSM. La DSM de CppDepend repose sur un schéma simple de 3 couleurs pour les cellules : Bleu, Vert et Noir. En survolant une ligne ou une colonne avec la souris, l'aide contextuelle explique la signification de ce schéma de couleurs :

Une cellule DSM non vide contient un nombre. Ce nombre représente la force du couplage représenté par la cellule. La force du couplage peut être exprimée en nombre de membres/méthodes/champs/types ou namespaces impliqués dans le couplage, selon la valeur actuelle de l'option Poids sur cellules En plus de l'aide contextuelle, le DSM offre également Panneau d’info qui explique le couplage avec une description en langage clair :

Le DSM de CppDepend propose de nombreuses options à essayer :
- Il offre de nombreuses possibilités pour explorer les dépendances en profondeur (une colonne/ligne parente peut être ouverte, les cellules peuvent être développées...)
- Il peut gérer les DSM carrées symétriques et les DSM rectangulaires non symétriques
- Les en-têtes horizontaux et verticaux peuvent être liés pour avoir en permanence une matrice carrée symétrique
- Il est fourni avec l’option Utilisation indirecte, où la cellule montre l’utilisation directe et indirecte
- L'en-tête vertical peut contenir des éléments de code de niveau
- ...
Il est conseillé de découvrir toutes ces fonctionnalités par vous-même, en analysant les dépendances de votre base de code.
Identifier les motifs de structure du code sur la matrice
Comme expliqué dans l'introduction, la DSM a la particularité d'offrir une identification facile des patterns de structure de code populaires. Présentons les scénarios les plus courants :
Code en couches
Un motif qu’une DSM rend évident est structure en couches (c.-à-d. une structure acyclique). Lorsque la matrice est triangulaire, avec toutes les cellules bleues dans le triangle inférieur gauche et toutes les cellules vertes dans le triangle supérieur droit, cela montre que la structure est parfaitement en couches. En d'autres termes, la structure ne contient aucun cycle de dépendances.

Sur la partie droite de la capture, la même structure en couches est représentée avec un graphe. Toutes les flèches ont la même direction de gauche à droite. Le problème avec le graphe, c'est que la disposition du graphe ne passe pas à l'échelle. Ici, on voit à peine la vue d'ensemble de la structure. Si le nombre de boîtes était multiplié par 2, le graphe serait complètement illisible. En revanche, la représentation DSM ne serait pas affectée ; on dit qu'elle La DSM passe mieux à l’échelle que le graphe.
Remarque : Fait intéressant, la plupart des algorithmes de disposition de graphes reposent sur le fait qu'un graphe est acyclique. Pour calculer la disposition d'un graphe avec des cycles, ces algorithmes écartent temporairement certaines dépendances pour travailler avec un graphe en couches, puis rajoutent les dépendances écartées à la dernière étape du calcul.
Cycle de dépendances
Si une structure contient un cycle, le cycle est affiché par un carré rouge sur la DSM. On peut voir qu'à l'intérieur du carré rouge, les cellules vertes et bleues sont mélangées de part et d'autre de la diagonale. Il y a aussi des cellules noires qui représentent une utilisation directe mutuelle (c.-à-d. A utilise B et B utilise A).

Le DSM de CppDepend propose l'option unique Dépendance indirecte. Une dépendance indirecte entre A et B signifie que A utilise quelque chose, qui utilise quelque chose, qui utilise quelque chose ... qui utilise B. Ci-dessous est montrée la même DSM avec un cycle mais en mode indirect. On peut voir que le carré rouge est rempli uniquement de cellules noires. Cela signifie simplement que pour tout élément A et B du cycle, A et B sont indirectement et mutuellement dépendants.

Voici la même structure représentée avec un graphe. La flèche rouge montre que plusieurs éléments sont mutuellement dépendants. Mais le graphe n'est d'aucune aide pour mettre en évidence tous les éléments impliqués dans le cycle parent.

Notez que dans CppDepend, nous avons fourni un bouton pour mettre en évidence les cycles dans la DSM (le cas échéant). Si la structure est en couches, ce bouton a pour effet de triangulariser la matrice et de garder les cellules non vides aussi proches que possible de la diagonale.

Forte cohésion - faible couplage
L'idée de forte cohésion (au sein d'un composant) / faible couplage (entre composants) est populaire de nos jours. Mais si l'on ne peut pas mesurer et visualiser les dépendances, il est difficile d'obtenir une évaluation concrète de la cohésion et du couplage. Le DSM est très bon pour montrer une forte cohésion. Dans le DSM ci-dessous, un agrégat carré évident autour de la diagonale est affiché. Cela signifie que les éléments impliqués dans le carré ont une forte cohésion : ils sont fortement dépendants les uns des autres. De plus, on peut voir qu'ils sont en couches puisqu'il n'y a pas de cycle. Ils sont certainement candidats pour être regroupés dans un artefact parent (comme un namespace ou un assembly).
D'un autre côté, le fait que la plupart des cellules autour du carré soient vides plaide en faveur d'un faible couplage entre les éléments du carré et les autres éléments.

Dans le DSM ci-dessous, nous pouvons voir 2 composants avec une forte cohésion (carrés supérieur et inférieur) et un couplage assez faible entre eux.

Lors de la refactorisation, disposer d'un tel indicateur peut être très utile pour savoir s'il existe des opportunités de diviser des composants grossiers en plusieurs composants plus fins.
Trop de responsabilités
Le Principe de responsabilité unique (SRP) devient populaire dans la communauté des architectes logiciels aujourd'hui. Le principe stipule que : une classe ne devrait pas avoir plus d'une raison de changer. Une autre façon d'interpréter le SRP est qu'une classe ne devrait pas utiliser trop d'autres types différents. Si nous étendons l'idée à d'autres niveaux (assemblys, namespaces et méthodes), il est certain que si un élément de code utilise des dizaines d'autres éléments de code différents (au même niveau), il a trop de responsabilités. Souvent, le terme God class ou Composant god est utilisé pour qualifier ce morceau de code.
La DSM peut aider à repérer les éléments de code ayant trop de responsabilités. Un tel élément de code est représenté par des colonnes avec beaucoup de cellules bleues et des lignes avec beaucoup de cellules vertes. La DSM ci-dessous illustre ce phénomène.

Éléments de code populaires
Un élément de code populaire est utilisé par de nombreux autres éléments de code. Les éléments populaires sont inévitables (pensez à Chaîne classe par exemple), mais un élément de code populaire n'est pas un défaut. Cela signifie simplement que dans chaque base de code, il existe des concepts centraux représentés par des classes populaires.
Un élément de code populaire est représenté par des colonnes avec beaucoup de cellules vertes et des lignes avec beaucoup de cellules bleues. La DSM ci-dessous met en évidence un élément de code populaire.

Il est à noter que lorsqu'on garde sa structure de code parfaitement en couches, les composants populaires sont naturellement maintenus à bas niveau. En effet, un composant populaire ne peut de facto pas utiliser beaucoup de choses, car les composants populaires étant de bas niveau, ils ne peuvent pas utiliser quelque chose de plus haut niveau. Cela créerait une dépendance du bas niveau vers le haut niveau et briserait la propriété acyclique de la structure.
Mutuellement dépendants
Vous pouvez voir le couplage entre 2 composants en faisant un clic droit sur une cellule non vide, puis en sélectionnant le menu Ouvrir cette dépendance.

Si la cellule ouverte était noire comme dans la capture ci-dessus (c.-à-d. si A et B sont mutuellement dépendants), alors la matrice rectangulaire résultante contiendra à la fois des cellules vertes et bleues (et éventuellement des cellules noires également) comme dans la capture ci-dessous.

Dans cette situation, vous remarquerez souvent un déficit de cellules vertes ou bleues (3 cellules bleues pour 1 cellule verte ici). C'est parce que même si 2 éléments de code sont mutuellement dépendants, il existe souvent un ordre de niveau naturel entre eux. Par exemple, considérez le System.Threading espaces de noms et le System.String classe. Elles sont mutuellement dépendantes ; elles s'appuient l'une sur l'autre. Mais la matrice montre que Multithreading dépend beaucoup plus de Chaîne que l'inverse (il y a beaucoup plus de cellules bleues que de vertes). Cela confirme l'intuition que Multithreading est de niveau supérieur à Chaîne.

Ressources associées
Essayez CppDepend aujourd'hui
Commencez votre essai gratuit de 14 jours avec accès complet à toutes les fonctionnalités de documentation. Sans carte bancaire.
