Contrôle continu 2024-25
1. Testabilité
Considérez l’interface TaskManager, dont le code est donné ci-dessous :
public interface TaskManager {
TaskId createTask(String description, Date due, String tag);
void deleteTask(TaskId id);
List<TaskId> retrieveAllTasksForUser(String username);
List<TaskId> retrieveAllTasksForTag(String tag);
TaskId nextTask();
}
Cette interface est fournie par un composant appelé GTDManager et pose un problème de testabilité :
la méthode nextTask(), qui rend la tache dont l’échéance est la plus proche pour la data courante,
est très difficile à tester, car les tests ne peuvent pas modifier la date actuelle.
Proposez une solution pour améliorer la testabilité du composant
GTDManager, en rendant contrôlable la date utilisée par le composant.
2. Principe de substitution de Liskov
Considérez les classes Collection et ReadOnlyCollection,
dont un extrait du code source est présenté ici :
class Collection<T> {
private int size = 0;
protected Object[] elements = new Object[1000];
public void add(T element) {
elements[size++] = element;
}
}
class ReadOnlyCollection<T> extends Collection<T> {
public void add(T element) {
}
}
Est-ce que ces classes respectent le principe de substitution de Liskov ? Si oui, expliquez pourquoi. Si non, explique pourquoi et proposez une solution qui respecte ce principe.
3. Inversion de dépendance
Considérez le code suivant :
interface Task {
TaskId id();
}
class SimpleTask implements Task {
private TaskId id;
public TaskId id() {
return id;
}
}
class Project {
List<SimpleTask> tasks = new ArrayList<SimpleTask>();
}
Est-ce que la classe
Projectrespecte le principe de l’inversion de dépendance ? Si oui, expliquez pourquoi. Si non, explique pourquoi et proposez une solution qui respecte ce principe.
4. Ségrégation d’interfaces
Considérez le code l’interface GTDManager, dont le comportement des méthodes est indiqué par leur nom :
public interface GTDManager {
// Task methods
TaskId createTask(String description, Date due, String tag);
void deleteTask(TaskId id);
List<TaskId> retrieveAllTasksForUser(String username);
List<TaskId> retrieveAllTasksForTag(String tag);
TaskId nextTask();
// Connection methods
boolean login(String username, String password);
void disconnect(String username);
}
Est-ce que cette interface respecte le principe de la ségrégation d’interfaces ? Si oui, expliquez pourquoi. Si non, explique pourquoi et proposez une solution qui respecte ce principe.
5. Couplage
Considérez les deux options (A et B) d’implémentation de l’interface UserManager :
interface UserManagerA {
String getUser(String name);
}
interface UserManagerB {
User getUser(String name);
}
Laquelle de ces options aura un couplage plus fort avec les classes clientes ? Pourquoi ?
6. Créateur
Le diagramme de classes ci-dessous montre les associations entre trois classes,
GTDController, Project et Task.
La première sert de point d’entrée au sous-système :
il permet d’accéder aux projets, tâches, ainsi qu’à d’autres éléments non affichés ici.
Selon le principe d’affectation de responsabilités (GRASP) Créateur et en vous basant seulement sur les informations présentes dans ce diagramme, laquelle de ces trois classes doit être responsable de la création d’instances de la classe
Task? Justifiez votre réponse et expliquez votre solution.
7. Spécialiste de l’information
Le diagramme de classes ci-dessous est une représentation partielle du métier d’une société de services en informatique. Les développeurs, employés de cette société, participent à plusieurs projets. Chaque projet concerne au plus un client.
On souhaite implémenter une opération capable de retrouver tous les clients d’un développeur, mais on ne sait pas très bien dans quelle classe placer cette opération.
Selon le principe d’affectation de responsabilités (GRASP) "spécialiste de l’information", laquelle ou lesquelles de ces classes doit contenir cette opération ?
Justifiez votre réponse et expliquez votre solution.