L’outil JDepend permet de calculer des métriques de qualité pour les packages d’une application. Il évalue les dépendances amont et aval de chaque package, identifie les dépendances circulaires et fait ressortir le niveau d’abstraction et d’instabilité de chaque package. JDepend est très facile à mettre en oeuvre ; par contre, l’analyse des métriques demande un bon niveau d’expérience en conception objet.
Les résultats de JDepend peuvent être sortis dans un écran dédié (version swingui), dans un fichier xml (version xmlui) ou dans un fichier texte (version textui). C’est cette dernière possibilité qui m’a intéressée car le fichier résultat contient une synthèse des métriques sous forme CSV. Le défaut, c’est que le séparateur de colonnes utilisé est la virgule, qui est aussi le séparateur décimal puisque mon poste est en français.
Pour contourner ce problème, j’ai redéveloppé une classe de lancement pour JDepend, dans laquelle, j’ai modifié le séparateur de colonnes. J’en ai profité pour retirer toutes les autres informations et utiliser le suffixe .csv.
Classe JDepend
L’outil JDepend propose une classe JDepend centrale (package framework), plus 1 classe par type de sortie. Etant plutôt fainéant, j’ai estimé qu’en héritant de la classe textui.JDepend, j’aurais un minimum de travail à fournir. J’ai donc développé une classe qui hérite de jdepend.textui.JDepend, qui a sa méthode main, et qui redéfinit quelques méthodes…
package fr.sewatech.design.dependency;
public class CsvJDepend extends jdepend.textui.JDepend {
public static void main(String args[]) {
new CsvJDepend().instanceMain(args);
}
public CsvJDepend() {
super();
}
public CsvJDepend(PrintWriter writer) {
super(writer);
}
// ...
}
Formatage des sorties
La classe jdepend.textui.JDepend implémente plusieurs méthodes préfixées par print, qui écrivent les différentes parties du fichier texte. Seule la partie summary m’intéresse, j’ai donc redéfinit toutes les autres méthodes print avec des méthodes vides. Je sais que ce n’est pas très design, mais je suis dans un contexte où je ne domine pas le contenu de la sur-classe, et surtout, c’est pratique !
@Override
protected void printHeader() {
}
@Override
protected void printPackages(Collection packages) {
}
@Override
protected void printCycles(Collection packages) {
}
@Override
protected void printFooter() {
}
Ecriture du CSV
Enfin, pour la partie summary, je me suis inspriré de la sur-classe, en modifiant le séparateur de colonnes.
@Override
protected void printSummary(Collection packages) {
final String separator = ";";
getWriter().println(
"Name"+separator+" CC"+separator+" CA"+separator+" Ca"+separator+" Ce"+separator+" A"+separator+" I"+separator+" D"+separator+" V");
Iterator i = packages.iterator();
while (i.hasNext()) {
JavaPackage jPackage = (JavaPackage) i.next();
getWriter().print(jPackage.getName() + separator);
getWriter().print(jPackage.getClassCount() + separator);
getWriter().print(jPackage.getAbstractClassCount() + separator);
getWriter().print(jPackage.afferentCoupling() + separator);
getWriter().print(jPackage.efferentCoupling() + separator);
getWriter().print(toFormattedString(jPackage.abstractness()) + separator);
getWriter().print(toFormattedString(jPackage.instability()) + separator);
getWriter().print(toFormattedString(jPackage.distance()) + separator);
getWriter().println(jPackage.getVolatility());
}
}
Lancement de la classe
Les options de lancement sont les mêmes que pour l’outil jDepend standard, de même que le même fichier jdepend.properties est pris en compte. Le lancement du nouvel outil se fait de la façon suivant :
java fr.sewatech.design.dependency.CsvJDepend -file jdepend-report.csv D:\Projets\leader\workspace\novanet\novanet\WEB-INF\classes