Qualité de code — Checkstyle et SpotBugs
Un code qui compile et fonctionne n'est pas forcément un bon code. Des outils d'analyse statique permettent de détecter automatiquement les problèmes de style, les bugs potentiels et les mauvaises pratiques sans exécuter le programme.
Notions théoriques
Pourquoi l'analyse statique ?
Relire le code manuellement est lent et subjectif. Les outils d'analyse statique :
- appliquent les conventions de façon objective et systématique
- détectent des bugs que les tests ne couvrent pas encore
- s'intègrent dans le build Maven pour bloquer le déploiement si des problèmes existent
Checkstyle — Respect des conventions
Checkstyle vérifie que votre code respecte un ensemble de règles de style. Il ne cherche pas de bugs, mais garantit la cohérence du code dans une équipe.
Configuration Maven
<!-- Dans pom.xml <plugins> -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>3.3.1</version>
<configuration>
<configLocation>checkstyle-google.xml</configLocation>
<consoleOutput>true</consoleOutput>
<failsOnError>true</failsOnError>
</configuration>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
Téléchargez checkstyle-google.xml depuis le dépôt GitHub de Checkstyle et placez-le à la racine de votre projet.
Règles Google Java Style vérifiées
| Catégorie | Règle |
|---|---|
| Nommage | Classes en PascalCase, variables et méthodes en camelCase |
| Nommage | Constantes en UPPER_SNAKE_CASE |
| Format | Longueur de ligne ≤ 100 caractères |
| Imports | Pas d'imports * (import java.util.* interdit) |
| Structure | Une seule instruction par ligne |
| Javadoc | Javadoc obligatoire sur les méthodes publiques |
Lancer Checkstyle
mvn checkstyle:check # vérifier uniquement
mvn checkstyle:checkstyle # générer le rapport HTML
mvn checkstyle:check fait échouer le build si des violations sont trouvées (comportement configuré avec failsOnError: true). C'est voulu : aucun code non conforme ne doit pouvoir être livré.
Exemples de violations courantes
// VIOLATION : nom de variable en PascalCase (devrait être camelCase)
String NomPersonnage = "Aragorn";
// VIOLATION : import wildcard
import java.util.*;
// VIOLATION : ligne trop longue
public Personnage creerPersonnageAvecTousLesParametres(String nom, int force, int defense, int mana) {
// CORRECTION
public Personnage creerPersonnage(
String nom, int force, int defense, int mana) {
Désactiver une règle ponctuellement
// CHECKSTYLE:OFF
// Code généré automatiquement — règle désactivée ici
private static final long serialVersionUID = -7043994889789898773L;
// CHECKSTYLE:ON
N'utilisez // CHECKSTYLE:OFF qu'en dernier recours pour du code généré automatiquement ou des contraintes externes. Ne jamais l'utiliser pour contourner une règle applicable.
SpotBugs — Détecter les bugs potentiels
SpotBugs (successeur de FindBugs) analyse le bytecode Java compilé à la recherche de patterns de bugs connus.
Configuration Maven
<!-- Dans pom.xml <plugins> -->
<plugin>
<groupId>com.github.spotbugs</groupId>
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.4.0</version>
<executions>
<execution>
<phase>verify</phase>
<goals><goal>check</goal></goals>
</execution>
</executions>
</plugin>
Catégories de bugs détectés
| Catégorie | Exemple |
|---|---|
| Null deref | Appel de méthode sur une valeur potentiellement null |
| Equals sans hashCode | equals() redéfini mais pas hashCode() |
| Ressource non fermée | Connection ou InputStream jamais fermé |
| Synchronisation | Variable partagée sans synchronisation |
| Mauvaise comparaison | == sur des objets String au lieu de .equals() |
// BUG SpotBugs : comparaison d'objets avec ==
String nom = getNom();
if (nom == "Aragorn") { // FAUX : compare les références, pas les valeurs
System.out.println("Trouvé");
}
// CORRECTION
if ("Aragorn".equals(nom)) { // correct
System.out.println("Trouvé");
}
// BUG SpotBugs : equals() sans hashCode()
public class Personnage {
@Override
public boolean equals(Object o) { ... }
// MANQUE : hashCode() non défini → bug si utilisé dans une HashMap
}
Lancer SpotBugs
mvn spotbugs:check # vérifier (échoue si bugs trouvés)
mvn spotbugs:spotbugs # générer le rapport
mvn spotbugs:gui # ouvrir l'interface graphique
Le rapport HTML est généré dans target/site/.