J’ai été contacté par les fondateurs de Kalistick il y a quelques semaines. Comme vous le savez, j’aime bien tester et parler ensuite de nouveaux logiciels, comme SpringFuse récemment. Je prends le temps de vous en parler afin d’être transparent : je fais cela sur mon temps libre sans aucunes contre-parties, à part une bière payée par Nicolas Romanetti de SpringFuse le 10 mars 2009 à 23h34 après la soirée du Paris JUG (!!!). Pour être tout à fait sérieux, je tenais à préciser tout cela, soyons plus concret et parlons maintenant de Kalistick.
L’éditeur Kalistick est une société française basée à Lyon, qui édite un logiciel d’analyse de code pour Java et C# en mode hébergé (Software as a Service). L’intérêt de la solution est donc de nous permettre d’utiliser un moteur d’analyse déporté, toujours à jour, disponible, et capable aussi de construire à terme une base de « bonnes pratiques ». En envoyant votre code, vous contribuez aussi à améliorer l’outil, en proposant de vrais cas, ce que je trouve vraiment intéressant et novateur.
Le fonctionnement est simple : tout d’abord nous préparons en local une archive avec le code source, les librairies et le code compilé. Après avoir téléchargé vers Kalistick cet ensemble, l’analyse commence. Vous recevez alors par email un message vous informant que l’analyse est terminée. Les tableaux de bords, les agents d’analyse et les explications sur l’analyse permettent ensuite d’identifier rapidement les points noirs de l’application. Vous pouvez renouveler l’analyse, et suivre ainsi l’avancement des améliorations.
Du côté de la concurrence, nous trouvons Insite SaaS de l’éditeur Metrixware. C’est l’outil utilisé par mon client actuel, BNP Paribas. Je n’ai pas eu l’occasion de m’en servir, mais il est intéressant de constater que les éditeurs suivent aussi la tendance du Saas tout comme « Application Intelligence Platform » de Cast. Chacunes de ces solutions se différencient sur les langages supportés et sur le type de règles. Pour ma part c’est Java, nous allons voir ce que je peux apprendre.
J’ai pris du vieux code de notre application, qui présente peu de dépendances. Pour tout vous dire, c’est du code qui date de 2003 ou 2004, dans lequel on trouve tout un tas de fonctions plus ou moins utiles. J’ai donc l’impression d’emmener un vieux chien de 14 ans chez le véto lorsque je commence l’analyse…
La première partie consiste à préparer une archive au format tar.gz ou zip avec le code source, les librairies et les jars compilés. La préparation de l’archive se fait à l’aide d’un Agent proposé avec Kalistick. Pour le code C#, un Add-In pour Visual Studio permet aussi de préparer son projet.
J’ai fait analyser environ 31000 lignes de codes Java, soit 244 classes, de qualité franchement pas top afin de voir ce que cela allait donner. L’analyse terminée, vous recevez un email vous informant que le rapport est prêt.
Je me connecte sur le portail de Kalistick. L’interface est vraiment très bien faite. Je reconnais Ext-JS, l’organisation est claire et simple. Franchement, on voit l’outil fait par de vrais développeurs qui ont travaillé en SSII sur le terrain : les informations les plus importantes sont affichées dès la page de synthèse.
J’ai été assez bluffé par la qualité de l’analyse. Les metrics sont groupées par domaine, afin de vous aider à regarder les domaines les plus importants pour vous : Efficacité, Evolutivité, Fiabilité, Maintenabilité, Sécurité et Transferabilité. Pour moi sur ce code, c’est tout d’abord la fiabilité. 27% du code analysé présente des problèmes dans le domaine de la Fiabilité, ce qui revient à dire qu’un quart de ce que j’ai utilisé… n’est pas fiable.
Nous allons voir un exemple trouvé par Kalistick, et tester au passage si vous êtes observateur ou pas 🙂
Prenons ce bout de code, digne des années 2000 où l’on portait des pantalons en patte d’éléphant.
A votre avis, que se passe-t-il à la ligne 96 ?
90 public static Properties filter(Properties source, ArrayList includingKeys) { 91 if (includingKeys != null) { 92 return new Properties(source); 93 } else { 94 final Properties properties = new Properties(); 95 96 for (Iterator iterator = includingKeys.iterator(); iterator.hasNext();) { 97 Object o = iterator.next(); 98 99 if (source.containsKey(o)) { 100 properties.put(o, source.get(o)); 101 } 102 } 103 return properties; 104 } 105 }
Je vous passe les mauvaises pratiques, on cherche un bug… Regardez la variable includingKeys et vous verrez le souci.
Kalistick trouve aussi des problèmes plus compliqués, comme le problème de comparaison des Float lorsque l’on tombe sur un cas NaN (not a number). En effet, une division par 0 retourne un NaN en Java, qui n’est pas inférieur à 0, même pas comparable à quoique ce soit. Il faut donc utiliser Double.isNaN() pour déterminer si un Float est un NaN.
A cet instant précis je sens un grand vide dans votre regard.
Ce code n’est pas bon (tiré de cet article) si vous passez en argument NaN car NaN n’est pas inférieur à 0, il n’est même pas égal à lui-même pour un float.
public employee(float monthly_salary){ if (monthly_salary < 0.0) throw new IllegalArgumentException("illegal monthly salary"); this.yearly_salary = 12.0 * monthly_salary; }
Celui-ci est correct, si je passe un salaire incorrect égal à NaN, une exception sera bien levée.
public employee(float monthly_salary) { if (monthly_salary >= 0.0) { this.yearly_salary = 12.0 * monthly_salary; } else throw new IllegalArgumentException("illegal monthly salary"); }
Cet exemple n’est pas le plus intéressant.
Comme Emmanuel Bernard d’ailleurs le rappelle dans le podast des LesCastCodeurs, dès que vous travaillez avec des doubles ou des floats, il faut redoubler d’attention. D’où l’idée d’utiliser Kalistick pour éviter de se tromper… ce qui arrivera tôt ou tard.
Jugez ce code par exemple (tiré de cet article de Kasper B. Graversen référencé sur lesCastCodeurs) :
double nan = 0.0 / 0.0, infinity = 1.0 / 0.0; System.out.println( Double.MAX_VALUE != infinity ); System.out.println( Double.MAX_VALUE != nan ); System.out.println( infinity != nan ); >> true >> true >> true
D’autres metrics comme le problème de l’équilibre hashCode()/equals() sont expliqués très clairement par Kalistick :
Si une des deux méthodes equals() ou hashCode() doit être suchargée, il est nécessaire de surcharger l’autre.
Ces méthodes vise à comparer le contenu de deux objets. Les spécifications Java exigent que ces deux méthodes soient surchargées ensemble pour garantir le bon fonctionnement de mécanismes tels que les collections basées sur les hash (HashMap, Hashtable, …).* http://www.javapractices.com/Topic17.cjp
* http://www.javapractices.com/Topic28.cjp(extrait documentation en ligne Kalistick)
Parmi d’autres points notés par Kalistick :
– Quelques soucis de création de Singleton qui ne sont pas Thread-Safe. Comme on le sait, la création en « lazy » des Singletons n’est pas thread-safe, ce qui peut donner de beaux bugs difficiles à trouver (voir cet article sur OnJava.com)
– Problème sur les DateFormatter qui ne sont pas Thread-Safe, ce que l’on ne sait pas toujours (voir cet article)
– et pleins d’autres… de quoi faire 3 pages sans problèmes
En conclusion pour la partie analyse, le moteur est puissant et la qualité des explications, en français, fait gagner un temps précieux. J’ai aussi trouvé pratique une fonction toute bête : la possibilité de désactiver facilement certaines alertes. Par exemple concernant la Javadoc, sur cette partie de code je n’ai pas envie de voir les problèmes de documentation. D’un clic, je peux ajouter ou exclure les règles, ce qui est pratique pour ne conserver que ce qui est vraiment important.
Là où un autre outil joue l’esbrouffe avec 724 440 metrics dont 80% ne servent pas, Kalistick est pragmatique, et donc bien plus efficace.
Je ne vous cache pas qu’après avoir récupéré mon diagnostic, j’ai eu l’envie de commencer à corriger le code, et à me lancer dans du nettoyage en règle. Contrat rempli donc.
La valeur ajoutée se trouve dans les cas que l’on ne peut pas détecter par l’analyse statique du code source. L’instrumentation du bytecode est un moyen de trouver plus de problèmes, ce que sait faire Kalistick. Son concurrent en terme de metrics est semble-t-il Findbugs. Mais le produit va plus loin, car n’oublions pas le Service.
Kalistick propose ensuite une partie Plan d’Action qui vous aide à corriger et à reprendre le code. C’est donc le médecin qui détecte de quoi vous souffrez, mais qui vous propose ensuite de vous aider à corriger les problèmes. C’est une approche plus intéressante que l’approche des outils open-source, qui sont bons pour vous dire de quoi vous souffrez, pas forcément bon pour vous expliquer comment ensuite résoudre ces problèmes.
Côté roadmap, la prochaine version est prévue pour le mois de juin :
– gestion des tags pour lotir, filtrer, rechercher…
– mesure de l’effort fourni (charts sur le nombre de violations corrigées, nouvelles, …)
– nouvelle règle qui croise le couplage efférent et la complexité cyclomatique
Puis un peu plus tard dans l’année:
– nouvelles règles d’implémentation
– nouvelles règles de structure (avec le couplage afférent)
– règles de design (type étanchéité des packages)
– antipatterns
Voilà, test terminé pour moi. Je pourrai encore en parler pas mal, mais je vous laisse car je vais faire un test tordu : prendre le code généré par SpringFuse et le faire auditer par Kalistick…
Hop à bientôt.
Références
Le site de Kalistick http://www.kalistick.fr
Problème des Floats et NaN http://www.concentric.net/~Ttwang/tech/javafloat.htm
L’allusion sur la bière offerte est bien passée, je ferai de même avec plaisir si vous passez dans la région lyonnaise ;-))
Sylvain FRANCOIS
Directeur Technique
Kalistick