Travaux Pratiques n°2

Lectures préalables :  
Thèmes du TP :
  • Une pile d'entiers
  • Plusieurs classes
  • Tableaux
  • Variables d'instance

 

A partir de ce TP, il est demandé d'utiliser l'environnement de développement BlueJ,

et de fournir à la fin de chaque exercice une copie d'écran montrant le diagramme de classes dessiné par BlueJ.

Question 1. (application)

(i) Développer la traditionnelle structure de données Pile (dernier entré, premier sorti).

AIDE :

Une Pile est ici une structure de données homogènes, de taille fixe, sur laquelle seul un nombre limité d'opérations peut être effectué :

  • constructeur = créer une pile vide d'une certaine taille
  • procédure empiler = mettre une valeur au sommet de la pile (PUSH en assembleur)
  • fonction dépiler = retirer la valeur du sommet de la pile et la retourner (POP en assembleur)
  • fonction estVide = retourne vrai ou faux selon que la pile est vide ou non
  • fonction estPleine = retourne vrai ou faux selon que la pile est pleine ou non

Contraintes :

AIDE :

Vous pouvez vous inspirer des structures suivantes :

  public class Pile { // fichier Pile.java
    private ... // Une première implémentation utilise :
                //   - un tableau d'entiers (int) : le contenu de la pile
                //   - un indice sur ce tableau   : le pointeur de pile
                //  comme données d'instances de la classe Pile

    public ...  // les méthodes listées ci-dessus.
  }

  public class TestPile { // fichier TestPile.java
    public static void main( String[] args )
      {
      Pile p1 = new Pile(5);
      Pile p2 = new Pile(10);
      // à compléter par vos tests (bien choisis et probants !)
      // quel est le comportement en cas de débordement de la pile ?
      } // main()
  }
   

Et générez avec BlueJ la documentation javadoc pour les deux classes.
Remarques :

(ii) Pour pouvoir visionner le contenu de la pile, ajoutez à la classe Pile la méthode public String toString();

     Cette méthode doit retourner le contenu de la pile sous la forme  "[ i1, i2, i3, i4 ]" où i1 est l'entier au sommet de la pile.

Exemple: la pile résultante des actions p1.empiler(2); suivi de p1.empiler(5); est, en "String", la valeur [5,2]

Et complétez les tests comme suit :

  public class TestPile { // fichier TestPile.java
    public static void main( String[] args )
      {
      Pile p1 = new Pile(5);
      Pile p2 = new Pile(10);
      // déjà complété par vos tests...
      System.out.println( " la pile p1 : " + p1.toString() );
      // ou bien
      System.out.println( " la pile p1 : " + p1 );
    
      Object o = new Object();        
      o = p1;
      System.out.println( " o = " + o ); // Quel est l'affichage résultant ?

      Pile p3 = new Pile(4); p3.empiler(5); p3.empiler(6);
      Pile p4 = new Pile(6); p4.empiler(8);
      p3 = p4;
      int res = p3.depiler();
      System.out.println( p4.estVide() ); // true ou false ? pourquoi ?

      }
  }
Et générez la documentation javadoc modifiée en conséquence (à fournir dans le rapport).

(iii) Ajouter à la classe Pile la gestion des exceptions :

AIDE :

Ces 2 exceptions sont implantées par les 2 classes Java :
public class PileVideException extends Exception{}
  // fichier PileVideException.java

public class PilePleineException extends Exception{}
  // fichier PilePleineException.java

Pour ce tp, ces classes peuvent rester vides.

Et modifiez en conséquence la classe de Test : TestPile.java.

(iv) N'oubliez pas de fournir la documentation javadoc modifiée en conséquence.

Question 2. (test unitaire)

(i) Plutôt que d'utiliser une classe TestPile, nous allons maintenant utiliser les possibilités de test unitaire de BlueJ.

En cliquant avec le bouton droit sur la classe Pile, nous pouvons choisir Create Test Class.

AIDE :

Si ce choix n'apparaît pas, il faut choisir Preferences... dans le menu Tools et cocher la case Show unit testing tools dans l'onglet Miscellaneous.

Ensuite, 2 solutions :

  1. Double-cliquer sur la classe de test pour écrire en Java des méthodes de test
  2. .
    Pour cela, la méthode assertEquals(R,C) peut être très utile : R est le résultat attendu pour le calcul C, par exemple:
    assertEquals( true, p.estVide() );
    Pour mieux comprendre le code java nécessaire dans une classe de test, il vaut mieux adopter la solution 2, puis observer le code généré.
  3. Cliquer avec le bouton droit sur la classe de test et choisir Create Test Method... pour enregistrer toutes les actions permettant de réaliser un test. (cliquer sur le bouton END pour arrêter l'enregistrement).
    Cette solution est une aide à l'écriture de classe de test, mais il faut parfois retoucher le code généré par exemple pour ajouter la gestion des exceptions.
Enfin, pour exécuter les tests, on peut soit cliquer sur le bouton Run Tests pour déclencher tous les tests dans le projet en cours, soit avec le bouton droit sur la classe de test, choisir Test All pour déclencher tous les tests sur cette classe, soit enfin déclencher une par une chaque méthode de test.
Il est souhaitable auparavant de demander l'affichage de la fenêtre de résultats des tests (menu View, Show Test Results).

Il vous est demandé d'imaginer l'ensemble des tests nécessaires pour tester toutes les méthodes de la classe Pile dans tous les cas qui peuvent se produire et de vérifier que les résultats attendus sont bien obtenus.
Pour ne pas créer une méthode de test de taille trop monstrueuse, il est souhaitable de prévoir une méthode de test différente pour chaque méthode de la classe Pile.

(ii) Commenter les principaux tests réalisés et éventuellement ceux qu'il faudrait encore ajouter.

Optionnel* :

(iii) Modifiez l'implémentation de la Pile *, relancez les tests, et vérifiez qu'elle marche toujours parfaitement. Vous venez de faire un test de non-régression.

* Suggestions de modification :
 - si vous aviez besoin de deux indices dans la Pile, n'en utilisez plus qu'un; ou l'inverse.
 - si vous mémorisiez la première place libre, mémorisez la dernière place occupée; ou l'inverse.

Question 3. (applette)

(i) Créez un nouveau répertoire dans lequel vous recopierez votre classe Pile de la question 1.ii . Copiez également dans ce répertoire le source de cette "Applette" dans le fichier ApplettePile.java.

Si vous écrivez le bon fichier ApplettePile.html (voir TP1), vous devriez voir à peu près ça :

ApplettePile en action !

Et générez la documentation javadoc. (fournir cette documentation si vous ne faites pas la suite)

(générée par javadoc -d docApplettePile -version -author -private Pile.java ApplettePile.java)

(ii) Modifiez la classe ApplettePile.java afin de prendre en compte les exceptions susceptibles d'être levées et d'en informer l'utilisateur.
Vous devriez obtenir une applette avec le comportement ci-dessous :

ApplettePile avec la prise en compte des exceptions

Et générez la documentation javadoc. (fournir cette documentation si vous ne faites pas la suite)

(iii) Cette IHM reste perfectible; une extension simple serait d'invalider le bouton "empiler" lorsque la pile est pleine (appel de boutonEmpiler.setEnabled(false); ); de même pour le bouton "depiler".

Vous devriez obtenir une applette avec le comportement ci-dessous :

ApplettePile avec la gestion des boutons

Et n'oubliez pas de fournir la documentation javadoc.

* Optionnel signifie qu'il n'est pas obligatoire de "rendre" ces questions sur la page web dont vous avez enregistré l'URL, mais vous devez essayer de traiter toutes ces questions pendant le TP, et elles peuvent donner lieu à un bonus sur la note de TP.


Annexe 1. Le source de l'applette

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class ApplettePile extends Applet implements ActionListener{
  private TextField donnee = new TextField(6);
  private TextField sommet = new TextField(6);
  private Label     contenu = new Label("[]");

  private Pile p = new Pile(5);

  public void init(){
    
    Button    boutonEmpiler = new Button("empiler");
    Button    boutonDepiler = new Button("depiler");

    Panel enHaut = new Panel();
    enHaut.add(donnee);
    enHaut.add(boutonEmpiler);
    enHaut.add(boutonDepiler);
    enHaut.add(sommet);
    setLayout(new BorderLayout(5,5));
    add("North",enHaut);
    add("Center",contenu);
    enHaut.setBackground(Color.green);
    boutonEmpiler.addActionListener(this);
    boutonDepiler.addActionListener(this);
  }

  public void actionPerformed(ActionEvent ae){
    if ( ae.getActionCommand().equals("empiler") ) {
        p.empiler( donnee.getText() ); // Corrigez l'erreur de type
    } else { // donc "depiler"
	sommet.setText( ... ); // A compléter
    }
    contenu.setText( ... ); // A compléter
  }
}


--> Dernière mise à jour le par DB