1
00:00:00,680 --> 00:00:02,370
Bonjour. Alors dans cette
séquence, on va voir quelque

2
00:00:02,570 --> 00:00:05,700
chose d'extrêmement
intéressant et important en Pharo,

3
00:00:06,130 --> 00:00:08,840
qui est le does not
understand. Donc en fait j'imagine

4
00:00:09,040 --> 00:00:10,870
que vous avez déjà eu des
débuggers qui sont ouverts avec

5
00:00:11,870 --> 00:00:12,910
la méthode
doesNotUnderstand affichée.

6
00:00:14,010 --> 00:00:16,460
Donc on va voir d'où elle
vient et à quoi elle sert.

7
00:00:17,330 --> 00:00:19,040
Donc on va prendre un exemple, ici.

8
00:00:19,240 --> 00:00:20,000
Donc je vais vous l'expliquer.

9
00:00:20,370 --> 00:00:21,620
On a un objet ici, node1.

10
00:00:21,820 --> 00:00:26,000
Cet objet on va lui
envoyer le message Coucou Stef.

11
00:00:26,170 --> 00:00:27,370
Donc ici, c'est le symbole Steph.

12
00:00:28,340 --> 00:00:32,360
Donc node1, si vous reprenez
le lookup, on va remonter à

13
00:00:32,560 --> 00:00:33,810
la classe de cet objet.

14
00:00:34,230 --> 00:00:37,220
Est-ce qu'il existe une
méthode coucou sur cette classe?

15
00:00:37,420 --> 00:00:39,300
Non. Alors on va
remonter à la super classe.

16
00:00:39,500 --> 00:00:41,870
Est-ce qu'il existe une
méthode coucou dans la face object?

17
00:00:42,070 --> 00:00:44,820
Non. Alors que va
faire la machine virtuelle?

18
00:00:45,060 --> 00:00:47,170
Elle va dire: je n'ai
pas trouvé de méthode

19
00:00:47,370 --> 00:00:49,420
correspondant à l'envoi de
messages effectués sur l'objet

20
00:00:49,620 --> 00:00:50,950
donc je fais réifier le message.

21
00:00:51,240 --> 00:00:55,480
Donc réifier, j'en ai déjà parlé
dans la séquence sur l'introspection,

22
00:00:55,680 --> 00:00:57,880
sur la réflexion. Donc
l'idée de réifier, c'est de

23
00:00:58,080 --> 00:01:01,310
représenter sous la forme
d'un objet, un concept qui

24
00:01:01,510 --> 00:01:04,580
normalement est implicite, donc
en l'occurrence ici le message.

25
00:01:05,000 --> 00:01:07,640
Donc ici, on va créer un objet pour
représenter le message Coucou Stef.

26
00:01:08,060 --> 00:01:10,000
Donc c'est une instance de
la classe message en Pharo.

27
00:01:10,620 --> 00:01:12,210
Et puis la machine
virtuelle, ce qu'elle va faire, c'est

28
00:01:12,410 --> 00:01:15,010
qu'elle va réenvoyer, elle
va refaire un envoi de message

29
00:01:15,230 --> 00:01:18,540
à cet objet node1 ici,
sauf qu'elle va lui envoyer le

30
00:01:18,740 --> 00:01:22,560
message doesNotUnderstand, et lui
passer cet objet message en paramètre.

31
00:01:22,940 --> 00:01:26,440
Donc il y a une nouvelle
exécution de l'algorithme de lookup.

32
00:01:26,640 --> 00:01:29,240
Cette fois, la machine
virtuelle va chercher est-ce qu'il

33
00:01:29,440 --> 00:01:31,870
existe la méthode
doesNotUnderstand dans la classe Node?

34
00:01:32,070 --> 00:01:33,510
Non. Alors elle remonte.

35
00:01:33,910 --> 00:01:35,250
Donc on remonte dans la super classe.

36
00:01:35,450 --> 00:01:37,300
Est-ce qu'il existe une méthode
doesNotUnderstand dans la classe objet?

37
00:01:37,500 --> 00:01:40,000
Oui, elle est là. Donc là,
elle est sous forme abrégée

38
00:01:40,200 --> 00:01:42,760
dnu, mais c'est la méthode
doesNotUnderstand, donc elle

39
00:01:43,000 --> 00:01:44,310
va pouvoir être exécutée.

40
00:01:47,170 --> 00:01:48,470
Donc ce qu'il faut
bien comprendre, c'est que

41
00:01:48,670 --> 00:01:50,950
doesNotUnderstand c'est un
message qu'on va envoyer aux

42
00:01:51,150 --> 00:01:53,030
objets, que la machine
virtuelle va envoyer aux objets

43
00:01:53,230 --> 00:01:56,050
pour vous, quand un
envoi de message a échoué.

44
00:01:57,120 --> 00:01:59,830
Donc toutes les classes
peuvent redéfinir cette méthode

45
00:02:00,030 --> 00:02:03,630
doesNotUnderstand, pour
vraiment avoir son propre

46
00:02:03,830 --> 00:02:06,810
comportement quand un message n'est
pas compris par l'une de ces instances.

47
00:02:07,440 --> 00:02:09,580
Donc c'est vraiment
important, ça permet de construire

48
00:02:10,280 --> 00:02:12,280
énormément de choses
grâce à cette méthode

49
00:02:12,480 --> 00:02:14,500
doesNotUnderstand, grâce à
ce hook. Donc ça permet de

50
00:02:14,700 --> 00:02:17,850
construire de la délégation
automatique, c'est utilisé

51
00:02:18,260 --> 00:02:20,410
aussi dans la
 programmation distribuée et caetera.

52
00:02:21,280 --> 00:02:23,020
Donc nous, on va voir
quelques usages possibles du

53
00:02:23,220 --> 00:02:25,030
doesNotUnderstand
dans cette séquence.

54
00:02:25,710 --> 00:02:27,250
Donc l'idée, par exemple,
imaginons que je veuille

55
00:02:27,450 --> 00:02:30,320
rediriger tous les messages
reçus par un objet vers un autre.

56
00:02:31,150 --> 00:02:32,700
Donc la délégation simple.

57
00:02:33,120 --> 00:02:35,450
Donc pour ça, je vais
construire un objet Delegating,

58
00:02:35,650 --> 00:02:38,190
donc qui va stocker la
cible, vers quel objet je dois

59
00:02:38,390 --> 00:02:41,000
renvoyer tous les messages. Je vais
redéfinir la méthode doesNotUnderstand.

60
00:02:41,780 --> 00:02:43,800
Je vous l'ai dit, en
paramètres elle prend un objet

61
00:02:44,170 --> 00:02:47,020
message qui va contenir le
sélecteur du message qui n'avait

62
00:02:47,220 --> 00:02:49,180
pas été compris, ainsi
que la liste des arguments.

63
00:02:49,660 --> 00:02:54,030
Et puis je peux demander à ce
message de se rediriger, d'être

64
00:02:54,230 --> 00:02:58,870
réenvoyé, donc je vais
utiliser sendTo self target, qui

65
00:02:59,070 --> 00:03:00,020
est bien la variable d'instance.

66
00:03:00,800 --> 00:03:03,040
Donc je vais réenvoyer ce
message à un autre objet.

67
00:03:04,350 --> 00:03:06,700
Donc attention, cette
pratique c'est extrêmement

68
00:03:06,900 --> 00:03:10,450
puissant, mais également
ça nuit un petit peu à la

69
00:03:11,060 --> 00:03:12,100
lisibilité du code.

70
00:03:12,710 --> 00:03:17,490
Vous l'avez ici. Il faut
vraiment aller lire le code pour

71
00:03:17,690 --> 00:03:19,930
savoir qui est-ce qui va
recevoir le message in fine.

72
00:03:20,940 --> 00:03:22,810
Par contre, c'est
extrêmement pratique pour la

73
00:03:23,010 --> 00:03:25,480
construction d'outils ou la
construction de mécanismes un

74
00:03:25,680 --> 00:03:29,910
peu avancés, comme je
vous l'ai dit précédemment.

75
00:03:30,110 --> 00:03:33,050
Donc on va voir un autre
exemple ensemble, le loggingProxy.

76
00:03:34,170 --> 00:03:38,440
L'idée de base c'est de
créer un objet minimal qui va

77
00:03:38,640 --> 00:03:42,470
contenir très peu de
méthode, de customiser, de redéfinir

78
00:03:42,670 --> 00:03:46,900
sa méthode
doesNotUnderstand. Et puis ensuite, ce qu'on

79
00:03:47,100 --> 00:03:50,230
va faire, c'est qu'on va
échanger un objet métier grâce à

80
00:03:50,430 --> 00:03:52,250
become avec cet
objet minimal, ce proxy.

81
00:03:54,900 --> 00:03:58,770
Donc voilà comment on va
faire, je crée un objet proxy.

82
00:03:59,360 --> 00:04:02,800
Donc cet objet proxy,
je vais mettre un sujet.

83
00:04:03,080 --> 00:04:05,670
Donc le sujet, c'est l'objet
que je vais remplacer, donc

84
00:04:05,870 --> 00:04:08,070
la cible, la target.

85
00:04:08,860 --> 00:04:12,080
Et puis je vais, par exemple,
mettre un Counter d'invocation.

86
00:04:12,280 --> 00:04:16,360
Donc à chaque fois qu'un message va
être reçu, on va incrémenter le Counter.

87
00:04:16,560 --> 00:04:18,250
Dans initialize, je vais mettre à 0.

88
00:04:18,450 --> 00:04:20,110
Le Counter d'invocation,
pour l'instant, n'a reçu aucun

89
00:04:20,310 --> 00:04:25,090
message et puis le sujet
qui est-ce qu'on va remplacer.

90
00:04:26,520 --> 00:04:28,140
Maintenant on va redéfinir
la méthode doesNotUnderstand

91
00:04:28,340 --> 00:04:31,300
sur ce proxy, donc on va
dire à chaque fois qu'il reçoit

92
00:04:31,500 --> 00:04:34,550
un message qu'il ne
comprend pas il va afficher sur le

93
00:04:34,750 --> 00:04:35,710
transcript qu'il a reçu un message.

94
00:04:35,930 --> 00:04:38,290
Il va incrémenter son
counter, j'ai reçu un nouveau

95
00:04:38,490 --> 00:04:41,660
message, un de plus et puis
je vais transférer le message

96
00:04:41,860 --> 00:04:46,650
à mon sujet. Donc comme
précédemment, je transfère le

97
00:04:46,850 --> 00:04:49,200
message à quelqu'un d'autre.

98
00:04:49,400 --> 00:04:51,610
Donc pour le sendTo, si
vous regardez l'implémentation

99
00:04:51,810 --> 00:04:54,580
dans la classe Message c'est
tout bête, on avait déjà vu,

100
00:04:54,870 --> 00:04:57,000
c'est la méthode
perform withArguments.

101
00:04:57,650 --> 00:05:00,530
On en avait déjà parlé dans
une séquence précédente, donc

102
00:05:00,730 --> 00:05:01,490
là il n'y a rien de nouveau.

103
00:05:03,020 --> 00:05:07,890
Voyons maintenant un
exemple, comment est-ce qu'on peut

104
00:05:08,090 --> 00:05:09,010
utiliser ce loggingProxy.

105
00:05:10,020 --> 00:05:14,690
Donc on va créer une
instance, un objet point, et puis je

106
00:05:14,890 --> 00:05:18,280
vais utiliser maintenant
become pour dire: tous ceux qui

107
00:05:18,480 --> 00:05:22,350
pointent sur ce point, ils
vont pointer sans s'en rendre

108
00:05:22,550 --> 00:05:27,140
compte sur un
loggingProxy, que j'ai instancié.

109
00:05:27,340 --> 00:05:30,500
Et maintenant, si j'envoie
des messages à l'objet point,

110
00:05:31,000 --> 00:05:33,090
donc attention on intègre
maintenant l'objet point vu qu'il

111
00:05:33,290 --> 00:05:36,000
y a eu become, c'est devenu
l'instance du loggingProxy.

112
00:05:36,930 --> 00:05:39,030
Donc à chaque fois que
je lui envoie un message,

113
00:05:39,940 --> 00:05:41,900
forcément ça va
s'afficher sur le transcript.

114
00:05:42,720 --> 00:05:45,190
Et puis le Counter
d'invocations va être incrémenté.

115
00:05:46,000 --> 00:05:48,280
Vous vous souvenez, dans le
doesNotUnderstand c'est ce qu'on faisait.

116
00:05:49,050 --> 00:05:53,090
Donc on peut voir qu'à la fin, le
Counter invocations, il vaut bien 3.

117
00:05:54,480 --> 00:05:56,260
Donc il y a quelques
limites, par exemple dans le petit

118
00:05:56,460 --> 00:06:00,620
framework de proxy, exemple
que je viens de présenter, il

119
00:06:00,820 --> 00:06:04,320
y a des limites, on ne peut
pas forcément capturer par

120
00:06:04,520 --> 00:06:07,050
exemple les messages qu'un objet
s'envoie à lui-même, ça va être difficile.

121
00:06:07,250 --> 00:06:10,430
On ne peut pas utiliser un
become sur des classes, donc

122
00:06:10,630 --> 00:06:14,100
les opérations réflexives
ont des limites en Pharo.

123
00:06:15,060 --> 00:06:17,290
Par exemple, ce qui va être
compliqué aussi, imaginons

124
00:06:17,490 --> 00:06:21,210
que l'objet à remplacer et le proxy
comprennent tous les 2 le même message.

125
00:06:21,760 --> 00:06:23,820
Ce qui fait que quand je
vais envoyer le message au

126
00:06:24,020 --> 00:06:27,530
proxy, il va répondre à la
place de le capturer avec un

127
00:06:27,730 --> 00:06:31,420
doesNotUnderstand, et de le
transférer à son objet cible.

128
00:06:32,310 --> 00:06:34,800
Donc, il y a d'autres
frameworks de proxy, plus puissants

129
00:06:35,000 --> 00:06:36,550
qui existent en Pharo, qui
permettent de vraiment tout

130
00:06:36,750 --> 00:06:41,000
capturer, mais ils sont
plus importants qu'un exemple

131
00:06:41,200 --> 00:06:41,960
aussi petit que celui-là.

132
00:06:42,800 --> 00:06:45,800
Donc une autre application,
un autre exemple d'utilisation

133
00:06:46,000 --> 00:06:47,950
de cette technique, ça
peut être par exemple la

134
00:06:48,150 --> 00:06:52,050
génération des
accesseurs ou même des méthodes

135
00:06:52,540 --> 00:06:56,080
dynamiquement. Par
exemple, imaginons ici toujours

136
00:06:56,280 --> 00:06:59,380
définie la méthode
doesNotUnderstand et puis je vais dire

137
00:06:59,580 --> 00:07:01,750
: OK, il y a un message
qui a été reçu donc je vais

138
00:07:01,950 --> 00:07:06,250
tester est-ce que j'ai des variables
d'instances qui incluent ce message?

139
00:07:06,450 --> 00:07:09,940
Si oui, alors je vais
générer une nouvelle méthode donc

140
00:07:10,140 --> 00:07:12,570
je vais utiliser compile
pour générer une nouvelle

141
00:07:12,770 --> 00:07:17,160
méthode sur la
 classe, qui va répondre

142
00:07:17,360 --> 00:07:19,490
directement la
valeur de cette variable.

143
00:07:19,690 --> 00:07:23,450
Donc je suis en train de générer
l'accesseur en lecture d'une variable.

144
00:07:24,140 --> 00:07:27,420
Et puis si vraiment si le
message qui a été envoyé ne

145
00:07:27,620 --> 00:07:31,380
correspond pas à un nom
d'une variable d'instances, je

146
00:07:31,580 --> 00:07:33,710
fais un super
doesNotUnderstand. Donc ça va nous

147
00:07:33,910 --> 00:07:37,170
permettre
d'automatiquement remplir les accesseurs en

148
00:07:37,370 --> 00:07:41,440
lecture, en fonction du fait qu'ils
ont été appelés ou pas sur un objet.

149
00:07:42,750 --> 00:07:45,620
Donc en conclusion dans cette
séquence, on peut voir qu'on

150
00:07:45,820 --> 00:07:48,000
va être capables
d'utiliser des objets minimaux.

151
00:07:48,180 --> 00:07:49,910
Donc on a vu que ce n'était
pas des objets qui étaient

152
00:07:50,110 --> 00:07:52,040
directement instance de
la classe Object mais de la

153
00:07:52,240 --> 00:07:54,200
 classe proto object, donc c'est
vraiment des tout petits objets.

154
00:07:54,400 --> 00:07:56,770
Ça peut être la base pour
des frameworks de proxy.

155
00:07:57,440 --> 00:07:59,070
Grâce à la redéfinition de
la méthode doesNotUnderstand,

156
00:07:59,270 --> 00:08:03,180
on va être capable de
capturer le fait qu'il y a un envoi

157
00:08:03,380 --> 00:08:04,790
de message qui a raté,
et on va pouvoir avoir un

158
00:08:05,000 --> 00:08:06,900
comportement, rediriger ce
message ailleurs et avoir un

159
00:08:07,100 --> 00:08:07,870
traitement spécifique.

160
00:08:08,320 --> 00:08:11,380
Donc c'est un hook qui est
extrêmement puissant, qui est

161
00:08:11,580 --> 00:08:13,460
à la base de
beaucoup d'outils en Pharo.

162
00:08:15,190 --> 00:08:17,080
Et par contre, il faut faire
attention, il faut vraiment

163
00:08:17,280 --> 00:08:20,470
l'utiliser que quand c'est
réellement nécessaire, quand

164
00:08:20,670 --> 00:08:23,550
vraiment on en a un besoin.
Donc ne mettez pas ça dans du

165
00:08:23,750 --> 00:08:26,750
code métier, encore ça reste
une technique avancée de Pharo.

