Bonjour. Donc dans le cours d'avant, on a regardé comme
on avait implémenté les booléens, not et or.
Et il nous restait en suspens la question 3: c'est
pourquoi diable a-t-on posé ces questions?
Donc c'est ce qu'on va regarder dans ce cours.
Donc, je vous rappelle l'implémentation.
Donc là, pour not qu'on avait vu, on avait vu qu'on avait deux objets.
On avait true et false, qui étaient instance de la classe
True et de la classe False.
Et quand on envoyait un message not, on cherchait au bon
endroit chacun dans sa classe respective et qu'on exécutait les méthodes.
Donc ça, pas de problème.
Donc maintenant, ce que j'avais dit, j'avais dit "mais en
fait si on regarde ce qu'on est en train de faire, c'est
que d'une part en fait, on laissait le receveur décider".
Ça veut dire qu'on ne prenait pas de décision.
Et que, on envoyait le message et que le message allait se résoudre.
Et donc c'étaient ces deux heuristiques qui étaient
"laisser le receveur décider" et "ne me demande pas, mais
dit de faire les choses". On le retrouvera encore.
Maintenant, regardons plus précisément l'exercice.
Donc qu'est-ce que ça illustre ?
Parce que vous n'allez sûrement jamais implémenter des
booléens dans votre vie. En tout cas, je vous le souhaite.
Et est-ce que c'est vraiment totalement inutile?
Quelle est la leçon ?
Quelles sont les leçons qui sont sous-jacentes?
Et je pense que c'est très important de vous poser cette
question, de se dire "oui, l'implémentation est comme ça.
Mais pourquoi? Qu'est-ce que ça illustre?"
Cela illustre en fait qu'à chaque fois que j'envoie un
message, en fait, j'ai une sorte de case statement
que vous retrouverez dans la programmation C ou ce genre de choses.
Envoyer un message, c'est faire un choix multiple.
Alors ce qui est intéressant, c'est qu'envoyer un
message, finalement, c'est un peu plus qu'un case parce
que c'est un case dynamique. En fait, il va dépendre des
classes qui sont chargées et des instances qui ont été créées.
Mais si on regarde ça veut dire que quand vous avez
programmé en Java, vous avez souvent écrit, je ne sais pas, moi, x.
f pour invoquer la méthode F.
Et moi ce que je suis en train de vous expliquer, c'est
que le point, là, c'est un opérateur de choix.
Et ça, c'est vraiment fondamental.
Et que ce choix est dynamique.
Et que souvent, on ne vous l'a pas présenté de cette manière.
Mais que c'est vraiment ce que l'exemple est en train d'illustrer
et d'une manière très forte en fait.
Si je résume, vous avez vraiment envoyé un message.
Ça fonctionne comme faire un case statement.
Mais c'est un case statement dynamique dans le sens où
cela va dépendre des classes qui ont été chargées.
Là, j'ai un exemple sur les booléens où il y a deux
instances et deux classes. Mais, il pourrait y en avoir
cinquante et ça fonctionnerait de la même manière.
À chaque fois que vous envoyez un message en fait, l'exécution,
la machine virtuelle parce que Pharo a une machine
virtuelle tout comme la machine virtuelle Java ou C Sharp.
La machine virtuelle, l'engin d'exécution va sélectionner
la bonne méthode dépendante de la classe du receveur.
Donc, envoyer un message c'est un mécanisme de choix.
Et vous à chaque fois que vous allez utiliser une
condition, vous allez vous substituer en fait à ce
mécanisme qui est implémenté dans la machine virtuelle qui fait un choix.
Et donc ce que les solutions avec not montrent, c'est:
utilisons le choix qui est donné par la machine virtuelle
pour implémenter nos programmes.
On n'a pas besoin d'utiliser un if en plus.
Puisqu'en fait, envoyer un message, c'est déjà faire un if ou une condition.
Donc la question maintenant qu'on peut se poser c'est:
si j'avais exprimé l'exercice de départ d'une manière
totalement différente, si j'avais dit: est-ce que vous
pouvez implémenter not dans la classe Booléen?
Ou or dans la classe Booléen ?
Vous n'auriez pas pu avoir cette solution.
Tiens, c'est étrange.
Donc ça veut dire qu’en fait, le fait qu'il y ait qu'une
classe ou plusieurs, ça a une influence vraiment
importante sur la manière dont je vais pouvoir concevoir mon application.
Et en effet, les classes vont jouer le rôle de
branches ou de choix.
Donc si vous avez le choix de choisir des yaourts, mais
que vous allez dans un magasin où il y en a qu'un, vous
choisirez ce yaourt-là. Là, c'est la même chose.
Cela veut dire que votre classe va représenter un choix
dans l'arbre d'héritage.
Donc, qu'est-ce que ça implique ?
Cela implique que quand je regarde un design où j'ai une
grosse classe bien grasse avec plein de méthodes et à la
place, je peux l'exprimer sous une forme de hiérarchie,
ce design-là est de meilleure qualité.
Pourquoi? Parce qu'il est déjà plus modulaire.
Je peux facilement rajouter un autre choix si j'ai envie.
Je peux étendre un autre champ.
Je peux dire "ah oui, celui-là, il n'était pas mal, mais
finalement je voudrais le raffiner pour en avoir à nouveau".
Et en plus, ça me permet de réduire la complexité.
Ça veut dire que je peux focaliser sur une seule classe
et pas un truc avec plein de conditions de partout.
Donc, si on regarde, on a d'un côté un opérateur de choix.
Et d'un autre, on a quelque chose qui exprime du choix.
Et quand on les met les deux ensemble, on obtient de la
conception-objet de bonne qualité.
Donc maintenant, ce qui est encore un peu plus
sympathique, c'est que si on regarde, la solution avec
les hiérarchies, elle est encore plus chouette que ça.
Parce que je peux packager mes solutions.
Ça veut dire, je peux dire "tiens, là, j'ai le package core.
Et puis là, j'ai un plug-in.
Je vais dire à mes clients "oui si tu veux.
Cette fonctionnalité-là, il faut que tu download dans l'autre ce plug-in.
Et que tu me payes bien sûr au passage".
Je vais charger dynamiquement ce code.
Et quand je créerai une instance de cette classe-là,
quand j'enverrai mon message opération ici, ça sera le
code du plug-in qui sera exécuté dans le système.
Et donc ça, c'est vraiment, pour nous, l'essence de la programmation-objet.
J'envoie un message et je vais sélectionner la bonne méthode.
Et je vais utiliser le fait que je sais que le système
sélectionne la bonne méthode pour avoir des
implémentations encore plus élégantes. Donc, qu'est-ce qu'on a regardé?
Qu'est-ce qu'on a vu en fait ?
On a vu qu'envoyer un message, ça laisse le receveur décider.
Donc, il y a un choix.
Le client lui n'a pas à prendre de décision.
Le code du client est beaucoup plus déclaratif.
Il n'y a pas de conditions.
Je donne des ordres "fais-ci, fais ça, ouvre, ferme".
Et pas "est-ce que tu es de cette classe-là?
Est-ce que tu es dans cet état-là pour que je te ferme?"
Ce n'est pas du tout le point.
Et différents receveurs peuvent être substitués dynamiquement.
Donc ça, on le verra dans un autre cours.
Mais c'est aussi sous-jacent.
Donc de manière générale, essayez d'éviter d'écrire des if.
Utiliser des messages et des objets quand vous pouvez.
Ce n'est pas tous les jours le cas, mais au moins
utilisez des messages et des objets quand vous le pouvez.
L'engin d'exécution, la machine virtuelle, à chaque fois
que vous envoyez un message fait un conditionnal switch pour vous.
Donc, utilisez-le. Et vous pouvez vous amuser à taper le AntiIfCampaign.
C'est une campagne que les programmeurs ont montée pour
éviter que les gens écrivent des if.
Donc, qu'est-ce qu'on a vu en fait dans ce cours?
On a vu deux choses.
On a vu que quand j'écris x.
f, je le fais en syntaxe Java et en syntaxe Pharo ça
serait F. Je fais un choix.
Je choisis la méthode F qui doit être exécutée en
dépendant du receveur.
Donc j'ai cet opérateur de choix.
Et j'ai une hiérarchie qui elle va représenter des choix potentiels.
Donc, c'est vraiment un squelette sur lequel le choix va pouvoir s'appuyer.
Et du coup, je n'ai pas de conditions.
Et j'ai des programmes qui sont plus extensibles.
Donc, voilà la fin du premier cours sur les concepts
objets tels qu'on peut les voir en Pharo.
Et, on en verra d'autres pendant les prochaines séances.