WEBVTT

00:00:00.680 --> 00:00:02.370 align:middle
Bonjour. Alors dans cette
séquence, on va voir quelque

00:00:02.570 --> 00:00:05.700 align:middle
chose d'extrêmement
intéressant et important en Pharo,

00:00:06.130 --> 00:00:08.840 align:middle
qui est le does not
understand. Donc en fait j'imagine

00:00:09.040 --> 00:00:10.870 align:middle
que vous avez déjà eu des
débuggers qui sont ouverts avec

00:00:11.870 --> 00:00:12.910 align:middle
la méthode
doesNotUnderstand affichée.

00:00:14.010 --> 00:00:16.460 align:middle
Donc on va voir d'où elle
vient et à quoi elle sert.

00:00:17.330 --> 00:00:19.040 align:middle
Donc on va prendre un exemple, ici.

00:00:19.240 --> 00:00:20.000 align:middle
Donc je vais vous l'expliquer.

00:00:20.370 --> 00:00:21.620 align:middle
On a un objet ici, node1.

00:00:21.820 --> 00:00:26.000 align:middle
Cet objet on va lui
envoyer le message Coucou Stef.

00:00:26.170 --> 00:00:27.370 align:middle
Donc ici, c'est le symbole Steph.

00:00:28.340 --> 00:00:32.360 align:middle
Donc node1, si vous reprenez
le lookup, on va remonter à

00:00:32.560 --> 00:00:33.810 align:middle
la classe de cet objet.

00:00:34.230 --> 00:00:37.220 align:middle
Est-ce qu'il existe une
méthode coucou sur cette classe?

00:00:37.420 --> 00:00:39.300 align:middle
Non. Alors on va
remonter à la super classe.

00:00:39.500 --> 00:00:41.870 align:middle
Est-ce qu'il existe une
méthode coucou dans la face object?

00:00:42.070 --> 00:00:44.820 align:middle
Non. Alors que va
faire la machine virtuelle?

00:00:45.060 --> 00:00:47.170 align:middle
Elle va dire: je n'ai
pas trouvé de méthode

00:00:47.370 --> 00:00:49.420 align:middle
correspondant à l'envoi de
messages effectués sur l'objet

00:00:49.620 --> 00:00:50.950 align:middle
donc je fais réifier le message.

00:00:51.240 --> 00:00:55.480 align:middle
Donc réifier, j'en ai déjà parlé
dans la séquence sur l'introspection,

00:00:55.680 --> 00:00:57.880 align:middle
sur la réflexion. Donc
l'idée de réifier, c'est de

00:00:58.080 --> 00:01:01.310 align:middle
représenter sous la forme
d'un objet, un concept qui

00:01:01.510 --> 00:01:04.580 align:middle
normalement est implicite, donc
en l'occurrence ici le message.

00:01:05.000 --> 00:01:07.640 align:middle
Donc ici, on va créer un objet pour
représenter le message Coucou Stef.

00:01:08.060 --> 00:01:10.000 align:middle
Donc c'est une instance de
la classe message en Pharo.

00:01:10.620 --> 00:01:12.210 align:middle
Et puis la machine
virtuelle, ce qu'elle va faire, c'est

00:01:12.410 --> 00:01:15.010 align:middle
qu'elle va réenvoyer, elle
va refaire un envoi de message

00:01:15.230 --> 00:01:18.540 align:middle
à cet objet node1 ici,
sauf qu'elle va lui envoyer le

00:01:18.740 --> 00:01:22.560 align:middle
message doesNotUnderstand, et lui
passer cet objet message en paramètre.

00:01:22.940 --> 00:01:26.440 align:middle
Donc il y a une nouvelle
exécution de l'algorithme de lookup.

00:01:26.640 --> 00:01:29.240 align:middle
Cette fois, la machine
virtuelle va chercher est-ce qu'il

00:01:29.440 --> 00:01:31.870 align:middle
existe la méthode
doesNotUnderstand dans la classe Node?

00:01:32.070 --> 00:01:33.510 align:middle
Non. Alors elle remonte.

00:01:33.910 --> 00:01:35.250 align:middle
Donc on remonte dans la super classe.

00:01:35.450 --> 00:01:37.300 align:middle
Est-ce qu'il existe une méthode
doesNotUnderstand dans la classe objet?

00:01:37.500 --> 00:01:40.000 align:middle
Oui, elle est là. Donc là,
elle est sous forme abrégée

00:01:40.200 --> 00:01:42.760 align:middle
dnu, mais c'est la méthode
doesNotUnderstand, donc elle

00:01:43.000 --> 00:01:44.310 align:middle
va pouvoir être exécutée.

00:01:47.170 --> 00:01:48.470 align:middle
Donc ce qu'il faut
bien comprendre, c'est que

00:01:48.670 --> 00:01:50.950 align:middle
doesNotUnderstand c'est un
message qu'on va envoyer aux

00:01:51.150 --> 00:01:53.030 align:middle
objets, que la machine
virtuelle va envoyer aux objets

00:01:53.230 --> 00:01:56.050 align:middle
pour vous, quand un
envoi de message a échoué.

00:01:57.120 --> 00:01:59.830 align:middle
Donc toutes les classes
peuvent redéfinir cette méthode

00:02:00.030 --> 00:02:03.630 align:middle
doesNotUnderstand, pour
vraiment avoir son propre

00:02:03.830 --> 00:02:06.810 align:middle
comportement quand un message n'est
pas compris par l'une de ces instances.

00:02:07.440 --> 00:02:09.580 align:middle
Donc c'est vraiment
important, ça permet de construire

00:02:10.280 --> 00:02:12.280 align:middle
énormément de choses
grâce à cette méthode

00:02:12.480 --> 00:02:14.500 align:middle
doesNotUnderstand, grâce à
ce hook. Donc ça permet de

00:02:14.700 --> 00:02:17.850 align:middle
construire de la délégation
automatique, c'est utilisé

00:02:18.260 --> 00:02:20.410 align:middle
aussi dans la
 programmation distribuée et caetera.

00:02:21.280 --> 00:02:23.020 align:middle
Donc nous, on va voir
quelques usages possibles du

00:02:23.220 --> 00:02:25.030 align:middle
doesNotUnderstand
dans cette séquence.

00:02:25.710 --> 00:02:27.250 align:middle
Donc l'idée, par exemple,
imaginons que je veuille

00:02:27.450 --> 00:02:30.320 align:middle
rediriger tous les messages
reçus par un objet vers un autre.

00:02:31.150 --> 00:02:32.700 align:middle
Donc la délégation simple.

00:02:33.120 --> 00:02:35.450 align:middle
Donc pour ça, je vais
construire un objet Delegating,

00:02:35.650 --> 00:02:38.190 align:middle
donc qui va stocker la
cible, vers quel objet je dois

00:02:38.390 --> 00:02:41.000 align:middle
renvoyer tous les messages. Je vais
redéfinir la méthode doesNotUnderstand.

00:02:41.780 --> 00:02:43.800 align:middle
Je vous l'ai dit, en
paramètres elle prend un objet

00:02:44.170 --> 00:02:47.020 align:middle
message qui va contenir le
sélecteur du message qui n'avait

00:02:47.220 --> 00:02:49.180 align:middle
pas été compris, ainsi
que la liste des arguments.

00:02:49.660 --> 00:02:54.030 align:middle
Et puis je peux demander à ce
message de se rediriger, d'être

00:02:54.230 --> 00:02:58.870 align:middle
réenvoyé, donc je vais
utiliser sendTo self target, qui

00:02:59.070 --> 00:03:00.020 align:middle
est bien la variable d'instance.

00:03:00.800 --> 00:03:03.040 align:middle
Donc je vais réenvoyer ce
message à un autre objet.

00:03:04.350 --> 00:03:06.700 align:middle
Donc attention, cette
pratique c'est extrêmement

00:03:06.900 --> 00:03:10.450 align:middle
puissant, mais également
ça nuit un petit peu à la

00:03:11.060 --> 00:03:12.100 align:middle
lisibilité du code.

00:03:12.710 --> 00:03:17.490 align:middle
Vous l'avez ici. Il faut
vraiment aller lire le code pour

00:03:17.690 --> 00:03:19.930 align:middle
savoir qui est-ce qui va
recevoir le message in fine.

00:03:20.940 --> 00:03:22.810 align:middle
Par contre, c'est
extrêmement pratique pour la

00:03:23.010 --> 00:03:25.480 align:middle
construction d'outils ou la
construction de mécanismes un

00:03:25.680 --> 00:03:29.910 align:middle
peu avancés, comme je
vous l'ai dit précédemment.

00:03:30.110 --> 00:03:33.050 align:middle
Donc on va voir un autre
exemple ensemble, le loggingProxy.

00:03:34.170 --> 00:03:38.440 align:middle
L'idée de base c'est de
créer un objet minimal qui va

00:03:38.640 --> 00:03:42.470 align:middle
contenir très peu de
méthode, de customiser, de redéfinir

00:03:42.670 --> 00:03:46.900 align:middle
sa méthode
doesNotUnderstand. Et puis ensuite, ce qu'on

00:03:47.100 --> 00:03:50.230 align:middle
va faire, c'est qu'on va
échanger un objet métier grâce à

00:03:50.430 --> 00:03:52.250 align:middle
become avec cet
objet minimal, ce proxy.

00:03:54.900 --> 00:03:58.770 align:middle
Donc voilà comment on va
faire, je crée un objet proxy.

00:03:59.360 --> 00:04:02.800 align:middle
Donc cet objet proxy,
je vais mettre un sujet.

00:04:03.080 --> 00:04:05.670 align:middle
Donc le sujet, c'est l'objet
que je vais remplacer, donc

00:04:05.870 --> 00:04:08.070 align:middle
la cible, la target.

00:04:08.860 --> 00:04:12.080 align:middle
Et puis je vais, par exemple,
mettre un Counter d'invocation.

00:04:12.280 --> 00:04:16.360 align:middle
Donc à chaque fois qu'un message va
être reçu, on va incrémenter le Counter.

00:04:16.560 --> 00:04:18.250 align:middle
Dans initialize, je vais mettre à 0.

00:04:18.450 --> 00:04:20.110 align:middle
Le Counter d'invocation,
pour l'instant, n'a reçu aucun

00:04:20.310 --> 00:04:25.090 align:middle
message et puis le sujet
qui est-ce qu'on va remplacer.

00:04:26.520 --> 00:04:28.140 align:middle
Maintenant on va redéfinir
la méthode doesNotUnderstand

00:04:28.340 --> 00:04:31.300 align:middle
sur ce proxy, donc on va
dire à chaque fois qu'il reçoit

00:04:31.500 --> 00:04:34.550 align:middle
un message qu'il ne
comprend pas il va afficher sur le

00:04:34.750 --> 00:04:35.710 align:middle
transcript qu'il a reçu un message.

00:04:35.930 --> 00:04:38.290 align:middle
Il va incrémenter son
counter, j'ai reçu un nouveau

00:04:38.490 --> 00:04:41.660 align:middle
message, un de plus et puis
je vais transférer le message

00:04:41.860 --> 00:04:46.650 align:middle
à mon sujet. Donc comme
précédemment, je transfère le

00:04:46.850 --> 00:04:49.200 align:middle
message à quelqu'un d'autre.

00:04:49.400 --> 00:04:51.610 align:middle
Donc pour le sendTo, si
vous regardez l'implémentation

00:04:51.810 --> 00:04:54.580 align:middle
dans la classe Message c'est
tout bête, on avait déjà vu,

00:04:54.870 --> 00:04:57.000 align:middle
c'est la méthode
perform withArguments.

00:04:57.650 --> 00:05:00.530 align:middle
On en avait déjà parlé dans
une séquence précédente, donc

00:05:00.730 --> 00:05:01.490 align:middle
là il n'y a rien de nouveau.

00:05:03.020 --> 00:05:07.890 align:middle
Voyons maintenant un
exemple, comment est-ce qu'on peut

00:05:08.090 --> 00:05:09.010 align:middle
utiliser ce loggingProxy.

00:05:10.020 --> 00:05:14.690 align:middle
Donc on va créer une
instance, un objet point, et puis je

00:05:14.890 --> 00:05:18.280 align:middle
vais utiliser maintenant
become pour dire: tous ceux qui

00:05:18.480 --> 00:05:22.350 align:middle
pointent sur ce point, ils
vont pointer sans s'en rendre

00:05:22.550 --> 00:05:27.140 align:middle
compte sur un
loggingProxy, que j'ai instancié.

00:05:27.340 --> 00:05:30.500 align:middle
Et maintenant, si j'envoie
des messages à l'objet point,

00:05:31.000 --> 00:05:33.090 align:middle
donc attention on intègre
maintenant l'objet point vu qu'il

00:05:33.290 --> 00:05:36.000 align:middle
y a eu become, c'est devenu
l'instance du loggingProxy.

00:05:36.930 --> 00:05:39.030 align:middle
Donc à chaque fois que
je lui envoie un message,

00:05:39.940 --> 00:05:41.900 align:middle
forcément ça va
s'afficher sur le transcript.

00:05:42.720 --> 00:05:45.190 align:middle
Et puis le Counter
d'invocations va être incrémenté.

00:05:46.000 --> 00:05:48.280 align:middle
Vous vous souvenez, dans le
doesNotUnderstand c'est ce qu'on faisait.

00:05:49.050 --> 00:05:53.090 align:middle
Donc on peut voir qu'à la fin, le
Counter invocations, il vaut bien 3.

00:05:54.480 --> 00:05:56.260 align:middle
Donc il y a quelques
limites, par exemple dans le petit

00:05:56.460 --> 00:06:00.620 align:middle
framework de proxy, exemple
que je viens de présenter, il

00:06:00.820 --> 00:06:04.320 align:middle
y a des limites, on ne peut
pas forcément capturer par

00:06:04.520 --> 00:06:07.050 align:middle
exemple les messages qu'un objet
s'envoie à lui-même, ça va être difficile.

00:06:07.250 --> 00:06:10.430 align:middle
On ne peut pas utiliser un
become sur des classes, donc

00:06:10.630 --> 00:06:14.100 align:middle
les opérations réflexives
ont des limites en Pharo.

00:06:15.060 --> 00:06:17.290 align:middle
Par exemple, ce qui va être
compliqué aussi, imaginons

00:06:17.490 --> 00:06:21.210 align:middle
que l'objet à remplacer et le proxy
comprennent tous les 2 le même message.

00:06:21.760 --> 00:06:23.820 align:middle
Ce qui fait que quand je
vais envoyer le message au

00:06:24.020 --> 00:06:27.530 align:middle
proxy, il va répondre à la
place de le capturer avec un

00:06:27.730 --> 00:06:31.420 align:middle
doesNotUnderstand, et de le
transférer à son objet cible.

00:06:32.310 --> 00:06:34.800 align:middle
Donc, il y a d'autres
frameworks de proxy, plus puissants

00:06:35.000 --> 00:06:36.550 align:middle
qui existent en Pharo, qui
permettent de vraiment tout

00:06:36.750 --> 00:06:41.000 align:middle
capturer, mais ils sont
plus importants qu'un exemple

00:06:41.200 --> 00:06:41.960 align:middle
aussi petit que celui-là.

00:06:42.800 --> 00:06:45.800 align:middle
Donc une autre application,
un autre exemple d'utilisation

00:06:46.000 --> 00:06:47.950 align:middle
de cette technique, ça
peut être par exemple la

00:06:48.150 --> 00:06:52.050 align:middle
génération des
accesseurs ou même des méthodes

00:06:52.540 --> 00:06:56.080 align:middle
dynamiquement. Par
exemple, imaginons ici toujours

00:06:56.280 --> 00:06:59.380 align:middle
définie la méthode
doesNotUnderstand et puis je vais dire

00:06:59.580 --> 00:07:01.750 align:middle
: OK, il y a un message
qui a été reçu donc je vais

00:07:01.950 --> 00:07:06.250 align:middle
tester est-ce que j'ai des variables
d'instances qui incluent ce message?

00:07:06.450 --> 00:07:09.940 align:middle
Si oui, alors je vais
générer une nouvelle méthode donc

00:07:10.140 --> 00:07:12.570 align:middle
je vais utiliser compile
pour générer une nouvelle

00:07:12.770 --> 00:07:17.160 align:middle
méthode sur la
 classe, qui va répondre

00:07:17.360 --> 00:07:19.490 align:middle
directement la
valeur de cette variable.

00:07:19.690 --> 00:07:23.450 align:middle
Donc je suis en train de générer
l'accesseur en lecture d'une variable.

00:07:24.140 --> 00:07:27.420 align:middle
Et puis si vraiment si le
message qui a été envoyé ne

00:07:27.620 --> 00:07:31.380 align:middle
correspond pas à un nom
d'une variable d'instances, je

00:07:31.580 --> 00:07:33.710 align:middle
fais un super
doesNotUnderstand. Donc ça va nous

00:07:33.910 --> 00:07:37.170 align:middle
permettre
d'automatiquement remplir les accesseurs en

00:07:37.370 --> 00:07:41.440 align:middle
lecture, en fonction du fait qu'ils
ont été appelés ou pas sur un objet.

00:07:42.750 --> 00:07:45.620 align:middle
Donc en conclusion dans cette
séquence, on peut voir qu'on

00:07:45.820 --> 00:07:48.000 align:middle
va être capables
d'utiliser des objets minimaux.

00:07:48.180 --> 00:07:49.910 align:middle
Donc on a vu que ce n'était
pas des objets qui étaient

00:07:50.110 --> 00:07:52.040 align:middle
directement instance de
la classe Object mais de la

00:07:52.240 --> 00:07:54.200 align:middle
 classe proto object, donc c'est
vraiment des tout petits objets.

00:07:54.400 --> 00:07:56.770 align:middle
Ça peut être la base pour
des frameworks de proxy.

00:07:57.440 --> 00:07:59.070 align:middle
Grâce à la redéfinition de
la méthode doesNotUnderstand,

00:07:59.270 --> 00:08:03.180 align:middle
on va être capable de
capturer le fait qu'il y a un envoi

00:08:03.380 --> 00:08:04.790 align:middle
de message qui a raté,
et on va pouvoir avoir un

00:08:05.000 --> 00:08:06.900 align:middle
comportement, rediriger ce
message ailleurs et avoir un

00:08:07.100 --> 00:08:07.870 align:middle
traitement spécifique.

00:08:08.320 --> 00:08:11.380 align:middle
Donc c'est un hook qui est
extrêmement puissant, qui est

00:08:11.580 --> 00:08:13.460 align:middle
à la base de
beaucoup d'outils en Pharo.

00:08:15.190 --> 00:08:17.080 align:middle
Et par contre, il faut faire
attention, il faut vraiment

00:08:17.280 --> 00:08:20.470 align:middle
l'utiliser que quand c'est
réellement nécessaire, quand

00:08:20.670 --> 00:08:23.550 align:middle
vraiment on en a un besoin.
Donc ne mettez pas ça dans du

00:08:23.750 --> 00:08:26.750 align:middle
code métier, encore ça reste
une technique avancée de Pharo.

