US

Projet 7 : Documentation et spécifications

Ce projet est relativement simple et va aborder les problèmes de documentation et spécification. Comment documenter du code, spécifier des méthodes, générer la documentation ? Ce projet apporte des réponses à ces différentes questions.

Le problème

Le problème n'est donc pas bien compliqué car on va surtout se concentrer sur la documentation du code. Ce qu'on veut faire, c'est écrire une classe qui représente un pion. Ce pion serait ensuite utilisé pour écrire un programme de jeu de plateau par exemple.

Afin de faire un programme propre et extensible, on va tout d'abord écrire une interface qui représente un pion, ensuite un type énuméré pour représenter les mouvements du pion et enfin, on va écrire une classe qui implémente l'interface.

Définition de l'interface Piece

Une fois le projet Projet7 créé dans Eclipse, crééz donc une nouvelle interface de nom Piece. Cette interface va définir deux méthodes qui permettent d'obtenir la position du pion et de déplacer le pion. L'interface ressemble donc actuellement à :

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
// Piece.java
 
import java.awt.Point;
 
/**
* Interface qui décrit une pièce d'un jeu de plateau
*
* @author Sébastien Combéfis
* @version 02-mai-08
*/
public interface Piece
{
    public Point getPosition();
 
    public void move (Direction d);
}
listing j1 L'interface Piece

La classe Point est une classe du package java.awt qui représente une coordonnée d'entiers (x, y). On va utiliser des objets de type Point pour représenter la coordonnée du pion sur le plateau de jeu. La méthode move prend en paramètre un objet du type énuméré Direction que l'on va voir tout de suite.

Lorsqu'on écrit une classe, une interface ou un type énuméré, il faut le documenter en précisant une courte description, l'auteur et la date. C'est pour le moment la seule documentation que l'on a ajouté pour l'interface Piece.

Le type énuméré Direction

Voyons maintenant le type énuméré Direction qui représente donc la direction que va prendre le pion lors d'un mouvement. On va considérer les mouvements simples vers le Nord, le Sud, l'Est ou l'Ouest. Le type énuméré comporte donc quatre valeurs NORTH, SOUTH, EAST et WEST.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
// Direction.java
 
/**
* Énumération qui représente des directions de mouvement d'une pièce
*
* @author Sébastien Combéfis
* @version 02-mai-08
*/
public enum Direction
{
    NORTH (0, 1),
    SOUTH (0, -1),
    EAST (1, 0),
    WEST (-1, 0);
 
    // Variables d'instance
    private int dx, dy;
 
    // Constructeur
    private Direction (int dx, int dy)
    {
        this.dx = dx;
        this.dy = dy;
    }
 
    public int dx()
    {
        return dx;
    }
 
    public int dy()
    {
        return dy;
    }
}
listing j2 Le type énuméré Direction

Le type énuméré possède deux variables d'instance qui représente de combien de cases en x et en y le mouvement fait bouger le pion. Pour le Nord, c'est (0, 1) puisque le pion ne bouge pas horizontalement mais monte d'une case verticalement.

Encore une fois, le type énuméré n'est pas très très documenté. On va s'attaquer tout de suite aux spécifications de l'interface et du type énuméré.

Spécifications

Attaquons-nous maintenant aux spécifications. On va commencer par le plus facile, c'est-à-dire les méthode dx() et dy() du type énuméré Direction. Intéressons-nous d'abord aux préconditions, c'est-à-dire les conditions qui doivent être vérifiées avant exécution de la méthode. Pour rappel, les préconditions portent sur la valeur des paramètres et sur l'état de l'objet. Ces deux méthodes n'ont aucune précondition.

Et qu'en est-il des postconditions, conditions qui sont vérifiées une fois que la méthode a été exécutée. Pour rappel, les postconditions portent sur l'état de l'objet, sur l'état des objets passés en paramètre et enfin sur la valeur de retour. Ces deux méthodes se contentent de renvoyer le déplacement en x et en y, la postcondition doit donc juste dire ça.

Le listing suivant reprend juste les spécifications des méthodes dx() et dy() du type énuméré Direction.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
/**
* Récupère le delta x
*
* @pre -
* @post La valeur renvoyée contient le delta x correspondant à cette position
*/
public int dx() { /* ... */ }
 
/**
* Récupère le delta y
*
* @pre -
* @post La valeur renvoyée contient le delta y correspondant à cette position
*/
public int dy() { /* ... */ }
listing j3 Spécifications des méthodes dx() et dy() du type énuméré Direction

Comme vous pouvez le voir sur le listing précédent, on donne d'abord une petite description de ce que fait la méthode, ensuite, on donne les pré et postconditions à l'aide des tags @pre et @post.

Voyons maintenant les spécifications des méthodes de l'interface Piece. Elles vous sont présentées sur le listing suivant. La première méthode permet d'obtenir la position du pion. Il n'y a toujours aucune préconditions par contre, la postcondition est un peu plus fournie. Il faut bien préciser que la position renvoyée est plus grande que (0, 0), en effet, une position comme (-2, 5) n'est pas envisageable. Il s'agit bien d'une postcondition puisqu'elle porte sur la valeur de retour.

En ce qui concerne la méthode move, il y a une précondition, le paramètre doit être différent de null. Enfin, la postcondition indique que la pièce est en effet déplacée selon la direction spécifiée.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
/**
* Obtient la position de la pièce dans le plateau
*
* @pre -
* @post La valeur renvoyée contient la position de la pièce sur le plateau
* Cette position est positive, c'est-à-dire plus grande que (0,0)
*/
public Point getPosition();
 
/**
* Fait se déplacer la pièce dans une certaine direction
*
* @pre d != null
* @post la pièce est déplacée selon la direction spécifiée
*/
public void move (Direction d);
listing j4 Spécifications des méthodes de l'interface Piece

La classe SimplePiece

Il ne nous reste plus qu'à écrire la classe SimplePiece. Créez donc cette classe dans Eclipse en n'oubliant pas de préciser qu'elle implémente l'interface Piece. Eclipse va alors vous générer un squelette de classe automatiquement.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
// SimplePiece.java
 
import java.awt.Point;
 
/**
* Description
*
* @author Sébastien Combéfis
* @version 02-mai-08
*/
public class SimplePiece implements Piece
{
    /* (non-Javadoc)
     * @see Piece#getPosition()
     */
    public Point getPosition ()
    {
        // TODO Auto-generated method stub
        return null;
    }
 
    /* (non-Javadoc)
     * @see Piece#move(Direction)
     */
    public void move (Direction d)
    {
        // TODO Auto-generated method stub
    }
}
listing j5 Génération automatique de classe

Liste des tâches

Remarquez que certains commentaires qu'Eclipse a ajouté commencent par TODO. Ce sont des commentaires spéciaux pour Eclipse qui indiquent qu'il reste quelque chose à faire. Vous pouvez à tout moment voir une liste de tout ce qui reste à faire via l'onglet Tasks en bas d'Eclipse.

Liste des todo's
fig j1 Liste des todo's

Implémentation de la classe

On ne doit pas remettre les spécifications des méthodes qui sont définies dans l'interface. Par contre, il va falloir spécifier le constructeur que l'on va ajouter. De plus, on va ajouter des assertions pour vérifier que les pré et postconditions sont bien vérifiées.

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
// Variables d'instance
private int x, y;
 
/**
* Constructeur
*
* @pre x, y >= 0
* @post Une instance de la classe est créée et représente un pion
* qui se situe en position (x, y)
*/
public SimplePiece (int x, int y)
{
    assert x >= 0 && y >= 0 : "x et y doivent être >= 0 (x = " + x + ", y = " + y + ")";
 
    this.x = x;
    this.y = y;
}
 
/* (non-Javadoc)
* @see Piece#getPosition()
*/
public Point getPosition()
{
    assert x >= 0 && y >= 0 : "x et y doivent être >= 0 (x = " + x + ", y = " + y + ")";
 
    return new Point (x, y);
}
 
/* (non-Javadoc)
* @see Piece#move(Direction)
*/
public void move (Direction d)
{
    assert d != null : "d doit être != de null";
 
    int oldx = x, oldy = y;
 
    x += d.dx();
    y += d.dy();
 
    assert x == oldx + d.dx() && y == oldy + d.dy();
}
listing j6 Implémentation de la classe SimplePiece

Vous pouvez voir qu'on a ajouté des assertions pour vérifier les pré et postconditions. Parfois, quand on veut ajouter une assertions, il faut ajouter du code supplémentaire, comme pour la méthode move, on a du mémoriser l'ancien état de l'objet pour pouvoir vérifier qu'il a bien été mis à jour puisque la postcondition porte sur l'état de l'objet.

Vous voyez également qu'on a ajouté un petit message à chaque fois avec les assertions, cela nous permettra de retrouver plus facilement d'où vient le problème si une assertions n'était pas valide.

Tester le programme et activer les assertions

Pour rappel, les assertions sont un mécanisme utilisé par le développeur pour débugguer son application. Elles ne sont dès lors pas activées par défaut. Voyons tout de suite comment les activer sous Eclipse et voyons ce qui se passe si on ne respecte par une précondition par exemple. Soit le programme de test suivant :

1 
2 
3 
4 
5 
6 
7 
8 
public class TestPiece
{
    public static void main (String[] args)
    {
        SimplePiece piece = new SimplePiece (-9, 0);
        piece.move (Direction.NORTH);
    }
}
listing j7 Programme de test

Si vous exécutez ce programme tout de suite (Menu Run > Run As ... > Java Application), aucune erreur ne va se produire, le programme se termine sans problème mais pourtant, on n'a pas respecté les préconditions du constructeur de la classe SimplePiece. On pourrait dès lors se dire que tout va bien mais comme on n'a pas respecté les préconditions, en fait, on ne peut rien dire, une erreur pourrait arriver à tout moment.

Exécutons le maintenant en activant les assertions. Pour cela, cliquez sur le menu Run > Run .... Retrouvez ensuite la classe TestPiece dans la liste de gauche et sélectionnez l'onglet Arguments. Il faut ensuite ajouter -ea (pour enable assertions) dans la zone de texte VM arguments.

Activer les assertions
fig j2 Activer les assertions

Si vous exécutez le programme cette fois-ci, une erreur d'exécution va se produire parce que une assertion n'est pas vérifiée. Vous pouvez voir sur la console :

Exception in thread "main" java.lang.AssertionError: x et y doivent être >= 0 (x = -9, y = 0)
	at SimplePiece.<init>(SimplePiece.java:25)
	at TestPiece.main(TestPiece.java:13)

Générer la documentation

Une fois que les méthodes ont été documentées, il est possible de générer la documentation au format HTML en utilisant l'outil javadoc qui est fourni avec le JDK. Voyons comment générer cette documentation à partir d'Eclipse. CLiquez d'abord sur le menu Project > Generate Javadoc ....

Générer la documentation (1)
fig j3 Générer la documentation (1)

Choisissez le projet pour lequel vous voulez générer la documentation dans la liste de gauche, ensuite, choisissez les classes à inclure dans la documentation à droite. Choisissez le dossier dans lequel vous voulez que la documentation soit générée et puis cliquez deux fois sur Next.

Générer la documentation (1)
fig j3 Générer la documentation (2)

Dans le champ texte Extra Javadoc options, ajoutez -tag pre:cm:Préconditions -tag post:cm:Postconditions. Cette option permet de reconnaitre les tags @pre et @post qui ne sont pas supportés par défaut.

Cliquez enfin sur Finish et la documentation va être générée. Vous pouvez voir le résultat de la documentation générée par Javadoc ici.

Résumé des points importants

  • On documente les classes, interfaces et types énumérés en donnant une description, l'auteur et la date ;
  • On documente les méthodes en donnant une description et les spécifications ;
  • Les préconditions portent sur l'état de l'objet et sur les paramètres ;
  • Les postconditions portent portent sur l'état de l'objet, l'état des paramètres de type objet et sur la valeur de retour ;
  • On utilise des assertions pour vérifier les pré et postconditions dans un but de débugage ;
  • On génère la documentation au format HTML avec l'outil javadoc ;

Vous pouvez télécharger le projet si vous le désirez. Ensuite, vous pouvez poursuivre le tutoriel, faire les exercices ou passer au projet suivant.

Pour tout problème, toute remarque, rendez-vous sur le forum consacré aux exercices pratiques.

  • Espace membre
  • Learning Center
  • Les forums
  • Livre d'or
  • Imprimer
  • Boutique
  • Info
  • Règlement
  • Erreur
  • Newsletter

MyPagerank.Net

Firefox 3.6

Browse Happy logo

Open Clip Art Library

Join our Facebook Group

Twitter

Copyright © 2000-2018 UKO. Toute reproduction strictement interdite sans autorisation du webmaster

Valid XHTML 1.1 !
Valid CSS2 !
Level Triple-A conformance icon, W3C-WAI Web Content Accessibility Guidelines 1.0
ICRA Internet Content Rating Association
Creative Commons License
Site optimisé pour Firefox avec une résolution 1024x768 --- Page chargée en 0.0704098 secondes --- This site uses Thumbshots previews