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 Project respecte 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.

Diagram

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.

Diagram

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.

8. Conception préliminaire

Dans le cadre de la conception basée sur les composants, qu’est-ce qu’une interface ?
Quelle est la différence entres les interfaces requises et fournies par un composant ?

9. Conception détaillée

Deux stratégies possibles de gestion d’erreurs sont l’utilisation d'Exceptions et de Codes d’état.
Énumérez les avantages et les inconvénients de ces deux approches.