GLO-4002 - Site du cours 2024

Temps estimé: 10 minutes

Exercices : OO et abstractions

Question 1

Le cycle de vie d'une classe tel que vu dans le cours commence lorsque celle-ci est créée (par le constructor) et se termine lorsque celle-ci est détruite (comme par un destructor en C/C++).

Vrai ou faux?

Faux.

Le cycle de vie vu dans le cours n'est pas relié au cycle de vie d'une instance d'une classe (bien que ce concept existe).

Nous parlons plutôt du cycle de vie d'une classe du point de vue de ce qu'elle représente dans le système.

Si par exemple dans notre code nous avons les classes TimeSheet et InsurancePlan, il est réaliste de penser que ces classes peuvent changer pour des raisons distinctes.

Une façon de le voir serait de se demander "quel acteur nous demandera des changements à ces classes?". Si TimeSheet est une demande du département de comptabilité et que InsurancePlan est une demande des ressources humaines, ces objets n'ont pas le même cycle de vie.

Question 2

L'effet d'avalanche va toujours dans le sens contraire des flèches (dans un UML-ish).

Vrai

Question 3

Quel choix parmi les suivants est un mauvais choix d’abstraction :

  1. L’utilisation d’une abstraction entre l’application et Mysql.
  2. L’utilisation d’une abstraction “Companion” pour regrouper les chats et chiens.
  3. Regrouper toutes les classes d’une application sous une classe abstraite afin de partager des méthodes utilitaires et attributs communs.

3

Question 4

Quelle est la chose la plus importante que l’OO a apporté de nouveau?

Dites pourquoi, dans vos mots, c'est si important.

La gestion des dépendances

Dans mes mots (i.e. plusieurs autres bonnes réponses possibles)

La gestion des dépendances car le sens de la dépendances peut être contrôlé et placé dans le sens inverse de celui de l'exécution. Cela permet de créer des implémentations (plugins) tout en gardant le client agnostic de l'implémentation concrète. Cela permet également de minimiser la probabilité de changement au client (avalanche).

Bref, on contrôle de manière explicite et "simple" le sens des dépendances pour contrôler la propagation des changements.

Question 5

On a vu dans le cours qu’une interface est un contrat. On a aussi vu le principe des dépendances stables.

Pourquoi disons-nous que dépendre d’un contrat rend la dépendance plus stable?

Une interface exprime une intention, elle dit le quoi mais pas le comment. Ca dit “saveUser”, mais ça ne force pas l’utilisation de MySql, par exemple. Une classe inclut le quoi et le comment est donc moins stable.

Question 6

Imaginons dans un premier temps une classe A qui dépend de B. Ensuite imaginons une classe A qui dépend d’une interface <I> dont B est un enfant.

Dessinez ces 2 cas dans un diagramme UML en traçant une flèche pour le flot d'exécution et une pour le flot de compilation

Sans interface:

asdf

Avec interface:

asdf

Question 7

Java est dit un langage fortement OO. Serait-ce possible de faire un programme en Java qui suiverait le paradigme procédurale?

Oui. Devoir faire un new d’une classe (ou même de plusieurs) ne veut pas dire que le code suit un paradigme OO.

Question 8

Un système médical a une classe ConfigurationSysteme et une classe Patient. La classe ConfigurationSysteme est instanciée une fois au début du programme et reste en mémoire tant que le système est ouvert (style Singleton). Cette classe a un cycle de vie plus grand que Patient qui est instancié au besoin, alors il serait correct que Patient dépende directement de ConfigurationSysteme.

Note: les deux classes sont concrètes.

Vrai ou faux? Pourquoi?

Faux.

(1) le cycle de vie dont l'on parle ici est celui de l'instanciation et ce n'est pas ce cycle de vie qui nous intéresse pour déterminer la dépendance mais plutôt le cycle de vie en terme de modifications (rappel: analogie de la lampe).

(2) Il est peu probable que Patient et configurationSysteme changent souvent en même temps pour les mêmes raisons.

(3) ConfigurationSysteme risque d'avoir beaucoup de couplage vers lui. Donc s'il change ça peut partir une bonne "avalanche".

Mais comme rien n'est jamais noir ou blanc, on pourrait cependant invoquer le fait que les ConfigurationSysteme sont stables, changeront pas et qu'elles sont indépendantes les unes des autres et donc que la probabilité d'avalanche est faible. Dans ce cas, avec cette justification, on pourrait répondre Vrai.

Question 9

Qu’est-ce qu’une “leaky abstraction”?

Recherchez des articles sur ce concept et donnez un exemple concret.

Cet exemple force l'utilisation de "MySQL" par son type. Ça devient impossible de changer à MongoDB sans tout modifier.

public interface AdsPersistence {
    MysqlResultSet findAllAds();
}

Un exemple plus subtil :

public interface Automobile {
   void openDoor();
   void addFuel();
}

Si notre système doit aussi gérer des automobiles électriques, on est cuit.

Question 10

Est-ce qu'une même classe peut répondre à plusieurs contrats (i.e. est-ce qu'une classe peut dépendre de plusieurs interface)? C'est possible dans la majorité des langages, mais est-ce une bonne pratique du point de l'OO?

Tout à fait! Nous verrons plus tard dans le cours comment définir les interfaces en fonction de ses clients. Résumé rapide: il est généralement préférable d'avoir plusieurs interfaces en fonction des clients qui utilisent celles-ci et non une seule "grosse" interface qui répond aux besoins de tous. Ceci dit, en "arrière-plan", ça peut être la même classe qui répond à tous ces besoins.

Notez que de faire ainsi est beaucoup plus flexible aussi. Si on décide d'avoir 2 classes plus tard (une pour chacune des interfaces), les utilisateurs des interfaces n'y verront que du feu.

Essayez-le dans un bout de code! Ou prennez au moins le temps de vous imaginer la transition et voir pourquoi ceci n'a pas d'impact.