Université de la Manouba École Nationale des Sciences de l’Informatique Examen
Classe : II2 Module : GL1 Enseignantes : H. H. BEN GHEZALA, N. BEN YAHIA, H. BENALI, S. ZBIDI
Durée : 2 heures Documents : non autorisés Date : 19 Janvier 2013
Question de cours (5pts) (0.5 * 10) 1. Qu’est-ce qu’un modèle ? En donner deux types. 2. Qu’est-ce qu’un langage ? En donner deux types. 3. Qu’est-ce qu’une méthode ? Par quoi est-elle définie ? 4. Quelle différence y-a-t-il entre une méthode et un modèle ? 5. Choisir la ou les bonnes réponses (chaque réponse non justifiée ne sera pas notée)
5.1 Un processus de développement :
a) Fixe un cadre rigoureux pour le développement de projet de taille importante. b) Est une perte de temps. c) Doit s’appliquer à la lettre. d) Peut être itéré. e) Peut s’appuyer sur plusieurs modèles de processus.
5.2 C’est le rôle d’un chef de projet :
a) De programmer les composants d’un logiciel. b) De vérifier le bon déroulement des tâches. c) D’organiser l’enchaînement des tâches. d) De fournir une visibilité globale sur un projet. e) D’écrire la spécification du logiciel.
5.3 Parmi les choix suivants, indiquez lesquels sont des principes de conception :
a) Transaction. b) Abstraction. c) Raffinement. d) Itération. e) Modularité.
5.4 Le couplage faible permet de :
a) comprendre le fonctionnement d'une classe sans en analyser d'autres b) modifier une classe sans affecter les autres. c) améliorer la maintenabilité.
5.5 La duplication de code :
a) est un indicateur de mauvaise conception. b) rend la maintenance plus difficile. c) peut conduire à l'introduction d'erreurs lors de la maintenance.
5.6 Une bonne cohésion implique que :
a) Une méthode doit être responsable d'une et une seule tâche bien définie. b) Chaque méthode effectue sa tâche de façon indépendante du reste du programme. c) Une classe doit représenter une seule entité bien définie.
Exercice 1 (3pts) (2pts + 1pt) Le cahier des charges d'une application de location de cassettes vidéo précise que : –
le client peut
•
louer et rapporter des cassettes; les locations sont enregistrées ainsi que les clients
le gérant peut
• ajouter/supprimer des cassettes au catalogue • changer les prix des cassettes au tarif
l'application
–
–
• calcule le prix d'une location selon le tarif des cassettes empruntées et la durée de l'emprunt • génère des états de caisse en fin de journée.
1/6
1. Utiliser les diagrammes de flots de données pour spécifier les fonctionnalités de cette application :
a) Dessiner le diagramme de contexte.
b) Raffiner ce diagramme en faisant apparaître une fonction de gestion des locations de
cassettes, entourée d'autres fonctions, flots et stockages.
c) Raffiner à un deuxième niveau la fonction de gestion des locations de cassettes.
2. Donner une architecture fonctionnelle de l’application de location de cassettes vidéo en précisant
clairement la circulation et les échanges des données.
Exercice 2 : Couplage/Cohésion (4pts)
2/6
1. Quels sont les problèmes de cohésion liés au code C1. Proposer une solution pour corriger C1.
(2pts)
Publicité
2. Quels sont les problèmes de couplage liés au code C2. Proposer une solution pour corriger C2.
(2pts)
C1
C2
public static void circonferenceCercle() { // Lecture du rayon System.out.print("Entrer le rayon du cercle: "); double rayon = Keyboard.readDouble(); while(Keyboard.error() || rayon < 0) { System.err.println("Mauvaise valeur de rayon."); System.out.print("Entrer le rayon du cercle: "); rayon = Keyboard.readDouble(); } // Calcul du circonference double circonference = 2 * Math.PI * rayon; // Affichage du circonference System.out.println("La circonference); }
circonference
est
" +
public class Triangle { // Colonne courante, ligne courante et nombre total de lignes public static int colonne, ligne, total; // Affiche un triangle de nbLignes lignes. public static void afficheTriangle(int nbLignes) { total = nbLignes; for(ligne = 0; ligne < total; ++ligne) { colonne = 0; afficheEspaces(); afficheLettres(); System.out.println(); } } // Affiche les espaces au debut de la ligne courante. public static void afficheEspaces() { while(colonne < ligne) { System.out.print(’ ’); ++colonne; } } // Affiche les ´etoiles de la ligne courante. public static void afficheLettres() { while(colonne < total) { System.out.print((char)(’a’ + ligne)); ++colonne; } } }
Problèmes de cohésion • trois taches indépendantes : lecture, calcul et affichage. • répétition du code • Problèmes de réutilisation et de maintenabilité Solution : Fractionnement en méthodes plus cohésives et plus réutilisables // Lit le rayon (positif) d’un cercle au clavier. public static double lireRayon() { System.out.print("Entrer le rayon du cercle: "); double rayon = Keyboard.readDouble(); while(Keyboard.error() || rayon < 0) { System.err.println("Mauvaise valeur de rayon."); System.out.print("Entrer le rayon du cercle: "); rayon = Keyboard.readDouble(); } return rayon; } // Calcule la circonference d’un cercle de rayon donne. public static double circonferenceCercle(double rayon) { return 2 * Math.PI * rayon; } // Affiche la circonference d’un cercle public static void afficheCirconference(double circonference) {
3/6
System.out.println("La circonference est " + circonference); }
Problèmes de couplage • ces méthodes ne sont pas réutilisables • maintenabilité: le changement d’une méthode ou variable affectera le comportement d’autres méthodes • afficheEspaces() et afficheLettres() dépendent des variables globales colonne, ligne et total • afficheEspaces() dépend d’afficheTriangle() • afficheLettres() dépend d’afficheEspaces() et d’afficheTriangle()
Solution : Ecrire des méthodes indépendantes Eviter autant que possible les variables globales (statiques de classe) Réécrire afficheEspaces() pour enlever son couplage public static void afficheEspaces(int combien) { int i; for(i = 0; i < combien; ++i) System.out.print(’ ’); } Réécrire afficheLettres() pour enlever son couplage et Généraliser afficheEspaces() pour repeteCaracteres() public static void repeteCaracteres(char c, int combien) { int i; for(i = 0; i < combien; ++i) System.out.print(c); } Réécrire afficheTriangle() pour enlever son couplage public static void afficheTriangle(int nbLignes) { int ligne; for(ligne = 0; ligne < nbLignes; ++ligne) { repeteCaracteres(’ ’, ligne); repeteCaracteres((char)(’a’ + ligne), nbLignes - ligne); System.out.println(); } }
Exercice 3 : Couplage (4pts) (1 + 3pts)
1. Expliquer le principe des différents niveaux de couplage suivants : contenu, global, contrôle,
structure de données, données.
2. Pour chacun des scénarios A, B et C (pages 3, 4, 5) identifiez le niveau de couplage parmi les cinq niveaux précédents. Justifiez vos réponses en indiquant les éléments qui ont motivé votre choix.
Scénario A et B : couplage globale (utilisation des variables globales (extern string gEntete; extern string gPiedDePage; )) Scénario C : couplage de données (utilisation des variables locales string gEntete = "";string gPiedDePage = "Copyright 2004"; )
NB : Si on souhaite qu’un objet (une fonction, une variable, etc.) soit utilisable dans tous les fichiers du projet, il faut le déclarer externe, en utilisant le mot-clé « extern ».
Exercice 4 : Tests (4pts) (1 * 4)
4/6
Soit le programme suivant :
lire(x) lire(y) z = 0 signe = 1 si x < 0 alors signe = -1 x = - x finsi si y < 0 alors signe = - signe y = - y finsi tant que x >= y faire x = x - y z = z + 1 fin z = signe * z
1. Dessiner le graphe de contrôle associé à ce programme en numérotant ses nœuds.
2. Par quelle suite de nœuds faut-il passer pour satisfaire le critère de couverture des instructions ?
Donner un jeu d’essai minimum qui satisfasse ce critère.
5/6
3. Par quelle suite de nœuds faut-il passer pour satisfaire le critère de couverture des arcs ? Donner
un jeu d’essai minimum qui satisfasse ce critère.
4. On appelle critère de couverture des i-chemins, le critère qui garantit que l’on passe sur tous les chemins possibles en répétant de 0 à i fois chaque boucle. Par quelle suite de nœuds faut-il passer pour satisfaire le critère de couverture des 1-chemins? Donner un jeu d’essai minimum qui satisfasse ce critère.
6/6
Scénario A
Module Menu
Module Imprime
//---Menu.h--------------------------- #ifndef MENU_H #define MENU_H
//---Imprime.h--------------------------- #ifndef IMPRIMME_H #define IMPRIMME_H
#include <string>
Publicité
#include <ostream>
void Imprime(ostream &ost, int x);
#endif
//---Imprime.cpp------------------------- #include <ostream> using namespace std;
#include "menu.h"
void Imprime(ostream &ost, int x) { ost << gEntete << endl; Calcul_et_affiche(ost, x); ost << gPiedDePage << endl; }
extern string gEntete; extern string gPiedDePage;
#endif
//---Menu.cpp------------------------- #include <iostream> #include <string> using namespace std;
#include "imprime.h"
string gEntete = ""; string gPiedDePage = "Copyright 2004";
void menu(void) { for(;;) {
cout << endl
<< "Menu:" << endl << " 1- Changer l'entete" << endl << " 2- Changer le pied de page" << endl << " 3- Imprimer" << endl << " 4- Quitter" << endl;
char c; cin >> c; switch( c) { case '1':
cout << "Entete: " << endl; cin >> gEntete; break; case '2':
cout << "Pied de page: " << endl; cin >> gPiedDePage; break; case '3':
cout << "Quel mois: " << endl; int x; cin >> x; Imprime(cout, x); break; case '4': return;
}
} }
7/6
Scénario B
Module Menu
Module Imprime
//---Menu.cpp------------------------- #include <iostream> #include <string> using namespace std;
//---Imprime.h---------------------------
#ifndef IMPRIMME_H #define IMPRIMME_H
#include "imprime.h"
#include <ostream>
extern string gEntete; extern string gPiedDePage;
void Imprime(ostream &ost, int x);
#endif
//---Imprime.cpp------------------------- #include <ostream> #include <string> using namespace std;
string gEntete = ""; string gPiedDePage = "Copyright 2004";
void Imprime(ostream &ost, int x) { ost << gEntete << endl; // Calcul_et_affiche(ost, x); ost << gPiedDePage << endl; }
void menu(void) { for(;;) {
cout << endl
<< "Menu:" << endl << " 1- Changer l'entete" << endl << " 2- Changer le pied de page" << endl << " 3- Imprimer" << endl << " 4- Quitter" << endl;
Publicité
char c;
cin >> c;
switch( c) { case '1':
cout << "Entete: " << endl; cin >> gEntete; break; case '2':
cout << "Pied de page: " << endl; cin >> gPiedDePage; break; case '3':
cout << "Quel mois: " << endl; int x; cin >> x; Imprime(cout, x); break; case '4': return;
}
} }
8/6
Scénario C
Module Menu
Module Imprime
//---Imprime.h---------------------------
#ifndef IMPRIMME_H #define IMPRIMME_H
#include <ostream> #include <string>
void Imprime(ostream &ost, int x, string entete, string piedDePage);
#endif
//---Imprime.cpp------------------------- #include <ostream> #include <string> using namespace std;
void Imprime(ostream &ost, int x, string entete, string piedDePage) { ost << entete << endl; // Calcul_et_affiche(ost, x); ost << piedDePage << endl; }
//---Menu.cpp------------------------- #include <iostream> #include <string> using namespace std;
#include "imprime.h"
string gEntete = ""; string gPiedDePage = "Copyright 2004";
void menu(void) { for(;;) {
cout << endl
<< "Menu:" << endl << " 1- Changer l'entete" << endl << " 2- Changer le pied de page" << endl << " 3- Imprimer" << endl << " 4- Quitter" << endl;
char c;
cin >> c;
switch( c) { case '1':
cout << "Entete: " << endl; cin >> gEntete; break; case '2':
cout << "Pied de page: " << endl; cin >> gPiedDePage; break; case '3':
cout << "Quel mois: " << endl; int x; cin >> x; Imprime(cout, x,
gEntete, gPiedDePage);
break; case '4': return;
}
} }
9/6