Avertissement Je ne parle pas de JUnit dans la suite car je parle bien de debuguer son code et non de le tester. Ce sont, pour moi, deux tâches différentes (et toutes les deux indispensables ... quoique les bisounours peuvent sans doute se passer de débugage)



  • Comment débuguer son code ?
  • La méthode de l'homme pauvre
  • Utilisations des assertions
  • Utilisation d'un débugueur, jdb

Comment débuguer son code ?

Débuguer un code, c'est trouver et quand le code devient mauvais et pourquoi ? Il existe plusieurs types d'erreurs; les erreurs de compilation et de syntaxe, les erreurs logiques et les erreurs à l'exécution (runtime). En Java, les erreurs de compilation et de syntaxe sont rapidement détectées grâce au compilateur.

Pour détecter les autres erreurs;

  • placer des points d'arrêt (breakpoints) afin de savoir «jusqu'où ça fonctionne»
  • inspecter (inspect) le contenu des variables afin de voir si elles contiennent bien les valeurs que l'on attend
  • entrer à l'intérieur d'une méthode afin de parcourir ce qu'elle fait (step in) ou bien simplement l'exécuter car l'on sait qu'elle fait bien son travail et passer à la suite (step over)

Si l'on ne sait pas par où commencer, il suffit de commencer par la première instruction de la méthode main.

Pour débuguer son code, il existe différentes techniques

  • la méthode de l'homme pauvre (ou des System.out.println) décrite ci-dessous
  • la méthode des commentaires qui consiste à mettre tout le code en commentaires et à décommenter ligne par ligne jusqu'à trouver l'endroit «qui coince»
  • l'utilisation d'un débugueur

La méthode de l'homme pauvre (poor man)

La première méthode, celle que l'on préconise pour les débutants, consiste à placer des instructions sout[1] dans son code afin de voir le contenu de certaines variables ou simplement de savoir si le programme «passe bien» par certaines instructions.

System.out.println("DEBUG (...)");

On évitera des commentaires de style «coucou», «passe par ici» et l'on préfèrera toujours commencer par le mot «DEBUG». Ceci afin de pouvoir facilement retrouver ce type de commentaire dans son code.

Cette méthode, bien que qualifiée d'archaïque, fait le boulot et peut convenir lorsqu'un débutant veut débuguer un programme (moyennement) simple. L'inconvénient de la méthode est qu'il faudra retirer ces commentaires à un moment donné.

Si l'on veut améliorer un peu la méthode, on peut placer à l'endroit qui va bien une variable booléenne précisant si l'on veut les commentaires de débugage ou pas (on peut même envisager que cette valeur soit un argument du programme). Le code aura alors l'allure suivante

private static boolean debugEnabled = true;
// (...)
if (debugEnabled) System.out.println("DEBUG - <mon commentaire>");

Utilisation des assertions

Cette technique peut venir en complément de la précédente. Le mécanisme consiste à placer à certains endroits du code un check du style; «je suppose que mon programme est dans cet état, sinon arrête toi». Ce test consiste le plus souvent à tester l'état d'une ou plusieurs variables.

You can use assertions to detect errors that may otherwise go unnoticed. Assertions contain Boolean expressions that define the correct state of your program at specific points in the program source code.

Extrait de http://java.sun.com/developer/technicalArticles/JavaLP/assertions/

Cette méthode est liée au design by contract (design-by-contract model of programming voir Qusay) qui, pour moi, peut être résumé par

  • certaines conditions sont invariantes tout au long du programme, je peux vérifier ces invariants
  • certaines conditions doivent être vérifiées avant l'appel d'une procédure ou d'un traitement, je peux vérifier ces préconditions
  • certaines conditions doivent être vérifiées après l'appel d'une procédure ou d'un traitement, je peux vérifier ces postconditions

Par exemple: Un traitement consiste en le calcul d'une racine carrée: précondition, le nombre doit être positif.

Une assertion s'exprime à l'aide d'une expression booléenne. Lorsque celle-ci est fausse, le programme s'arrête et génère une exception. Une assertion peut être affublée d'un message spécifique.

Board b = null; 
// on essaie de créer ce plateau de jeu 
b = new Board();
 
assert b != null;
// ou
assert b != null : "Can't create game board";

En Java, ce mécanisme est disponible depuis Java 1.4[2]. Par défaut les assertions ne sont pas utilisées au runtime. Ajouter ces instructions dans le code ne fait donc que «grossir» le code mais ne le font pas «ralentir». Pour que ces assertions soient testées, il faut le dire à la machine virtuelle par le biais de l'option enableassertion.

java -ea my.package.MyClass
java -enableassertions my.package.MyClass

Utilisation d'un débugueur, jdb

Java est fourni avec un débugueur (malheureusement) en ligne de commande. Pour pouvoir l'utiliser, il faut demander au compilateur de générer un bytecode qui pourra être utilisé par jdb. Cela se fait grâce à l'option -g (l'option -O est alors à proscrire car un code optimisé ne pourra pas être débugué). Ensuite, lancer le débugueur

java -g MyClass.java
jdb MyClass

Les commandes comprise par jdb sont (entre autres)

  • stop in MyClass.foo
  • run (démarre l'exécution)
  • cont (continue l'exécution après un break, ... )
  • step (ligne par ligne)
  • print (affiche la valeur d'une expression)
  • locals (affiche les variables locales)
  • threads (liste tous les threads)
  • help (affiche l'aide)

Une séance de débugage avec le code (erroné) suivant peut avoir l'allure décrite brièvement ci-dessous

public class TestJdb { 
	 public static void main ( String[] args ) { 
		  int i; 
		  i = 5;
		  i = foo(i); 
	 }
 
	 public static int foo(int i){ 
		 // Attention, c'est sans doute mieux --i;
		 return i--;
	 }
}

En quelques images;

  • lancer jdb et placer un breakpoint au début de la méthode main
  • à grands coups de step / print j'exécute le code instruction par instruction en regardant le contenu de la variable i

jdb-2.png

jdb-3.png

jdb-4.png

L'utilisation d'un débugueur demandera un certain temps d'adaptation avant de pouvoir correctement tracer son programme.

Enjoy !

Note d'orthographe

Certains utilisent le mot débogage puisqu'ils recherchent des bogues dans le programme ... ce sont les plus proches de l'académie française.

D'autres utilise le mot débugage car ils sont à la recherche de bugs dans leur programme ... ce sont les plus enclins à moins françiser les mots.

... l'important c'est de pouvoir se comprendre ;-)

Sources / Liens

À (re)lire aussi

Notes

[1] comprendre System.out.println par exemple

[2] À l'heure où j'écris on en est au JDK 7