Examen 2024-25
1. Mise en œuvre de modèles de conception
Pour mettre en œuvre en Java la classe Person à partir d’un modèle de conception UML,
Alice a suivi une stratégie de mise en œuvre qui fait appel à l’approche Accesseur/Mutateur, aussi connue comme Getter/Setter.
Le Listing suivant présente le résultat de sa mise en œuvre.[1]
public class Person {
private String name;
private static final String NAME_INITIAL_VALUE = "John Doe";
public String getName() {
return name;
}
public void setName(String name) {
if (null == name) throw new NullPointerException("Name must not be null");
this.name = name;
}
public void resetName() {
this.name = NAME_INITIAL_VALUE;
}
public boolean isNameSet() {
return !NAME_INITIAL_VALUE.equals(name);
}
}
Aidez Alice à réfuter la proposition de Bob en énumérant les avantages de la programmation défensive pour la méthode
setName().`
Solution
-
Il s’agit d’une méthode publique, ce qui veut dire que Alice ne peut pas contrôler les classes clientes de cette méthode. Imposer des pré-conditions aux clientes actuelles et futures de cette méthode n’est pas vraiment envisageable.
-
Tout comme la programmation assertive, le but de la programmation défensive est de vérifier toutes les entrées d’une méthode pour assurer son fonctionnement. Contrairement à la programmation assertive, les erreurs n’arrêtent pas l’exécution du programme et peuvent être traitées par les classes clientes.
-
Les assertions sont des prédicats qui vérifient des conditions qui ne doivent jamais se produire. Ici, l’appel de la méthode
setName()avec un argument nul peut se produire.
1.1. Refactorings
Carol, la chef de Alice, n’a pas apprécié son choix et lui demande de réécrire la classe \code{Person} en adoptant cette fois une approche Classes-Enveloppe. Pour s’assurer que le nouveau code préserve le comportement visible de l’ancien, Alice a commencé à établir une suite d’opérations de refactoring, qu’elle appliquera à son code initial.
Elle a déjà établi les 3 premières étapes :
-
Ajouter la classe
NameWrapper(refactoring AddEntity) -
Renommer le champ
nameenvalue(RenameEntity) -
Ajouter un champ privé
namede typeNameWrapperà la classePersonet l’initialiser ànew NameWrapper()(Add Entity) -
(…)
Aidez Alice à compléter sa suite d’opérations
Solution
-
Ajouter la classe
NameWrapper(refactoring AddEntity) -
Renommer le champ
nameenvalue(RenameEntity) -
Ajouter un champ privé
namede typeNameWrapperà la classePersonet l’initialiser ànew NameWrapper()(Add Entity) -
Modifier la visibilité du champ
NAME_INITIAL_VALUEàpackage(Change visibility) -
Déplacer le champ
NAME_INITIAL_VALUEà la classeNameWrapper(Move static field) -
Modifier la visibilité du champ
valueenpackage(Change Visibility) -
Déplacer le champ
valueà la classeNameWrapper(Move Instance Field); -
Déplacer la méthode
getName()à la classeNameWrapper(Move Instance Method) -
Déplacer la méthode
setName()à la classeNameWrapper(Move Instance Method) -
Déplacer la méthode
resetName()à la classeNameWrapper(Move Instance Method) -
Déplacer la méthode
isSetName()à la classeNameWrapper(Move Instance Method) -
Modifier la visibilité du champ
valueenprivate(Change Visibility)
Donnez le code des classes
PersonetNameWrapper, après les refactorings :
Solution
public class Person {
private NameWrapper name = new NameWrapper();
public String getName() {
return name.getName();
}
public void setName(String name) {
this.name.setName(name);
}
public void resetName() {
this.name.resetName();
}
public boolean isNameSet() {
return this.name.isNameSet();
}
}
Solution
public class NameWrapper {
static final String NAME_INITIAL_VALUE = "John Doe";
private String value;
public String getName() {
return value;
}
public void setName(String name) {
if (null == name) throw new NullPointerException("Name must not be null");
value = name;
}
public void resetName() {
value = NAME_INITIAL_VALUE;
}
public boolean isNameSet() {
return !NAME_INITIAL_VALUE.equals(value);
}
}