1
00:00:00,610 --> 00:00:03,720
Bonjour. Ce cours va
traiter d'un sujet avancé.

2
00:00:04,120 --> 00:00:06,080
Ce que je voudrais vous
montrer c'est comment à la

3
00:00:06,280 --> 00:00:08,940
demande, on peut
transformer la pile d'exécution en un

4
00:00:09,140 --> 00:00:12,540
objet Pharo et le manipuler.
L'idée de ce cours n'est pas

5
00:00:12,740 --> 00:00:15,380
d'aller dans les détails, mais
vraiment de vous donner l'intuition.

6
00:00:17,090 --> 00:00:19,290
L'idée, c'est qu'on peut
manipuler la pile, on peut la

7
00:00:19,490 --> 00:00:21,260
naviguer, on peut la
changer. Je vais essentiellement

8
00:00:21,460 --> 00:00:23,000
vous montrer comment
on peut la naviguer.

9
00:00:23,540 --> 00:00:27,280
Il y a 2 chapitres que vous
pouvez lire, qui traitent un

10
00:00:27,480 --> 00:00:31,450
petit peu de ce sujet:
c'est le chapitre sur les blocks

11
00:00:31,850 --> 00:00:34,470
et le chapitre sur les
exceptions du livre "Deep into Pharo".

12
00:00:35,150 --> 00:00:37,390
Pour ceux qui sont
intéressés, il faut vraiment les lire

13
00:00:37,660 --> 00:00:39,080
parce que c'est
vraiment bien expliqué.

14
00:00:39,560 --> 00:00:42,080
Sinon, vous avez la classe
"Context", qui se trouve dans

15
00:00:42,280 --> 00:00:43,280
Pharo, qui représente la pile.

16
00:00:46,280 --> 00:00:47,140
J'ai pris le scénario suivant.

17
00:00:47,340 --> 00:00:50,100
Si vous regardez, on vous a fait
coder dans le débuggeur depuis le début.

18
00:00:50,380 --> 00:00:51,700
Qu'est-ce qui se
passe dans le débuggeur?

19
00:00:52,000 --> 00:00:53,800
Vous envoyez un message,
il n'est pas connu parce que

20
00:00:54,000 --> 00:00:55,870
vous ne l'avez pas défini,
vous êtes en train de faire

21
00:00:56,070 --> 00:00:58,690
tourner votre test unitaire,
vous arrivez dans le débugger.

22
00:00:58,910 --> 00:01:01,520
Dans le débugger, il vous demande
"Voulez-vous créer une méthode?"

23
00:01:01,720 --> 00:01:02,640
Oui, vous créez votre méthode.

24
00:01:02,930 --> 00:01:05,120
Là, le système compile la
méthode au vol et l'installe

25
00:01:05,320 --> 00:01:07,660
dans la classe puis
relance cette méthode.

26
00:01:08,090 --> 00:01:10,680
Cette méthode, en général,
va lever une exception parce

27
00:01:10,880 --> 00:01:14,820
que le système n'est pas
magique: avec l'exception

28
00:01:15,100 --> 00:01:18,030
"ShouldBeImplemented", il vous
dit que c'est à vous d'implémenter

29
00:01:18,280 --> 00:01:19,200
la méthode dans le débugger.

30
00:01:19,400 --> 00:01:22,220
Vous implémentez la
méthode dans le débugger, vous

31
00:01:22,420 --> 00:01:24,730
recompilez cette méthode au
vol, vous faites "Proceed",

32
00:01:24,930 --> 00:01:27,850
le système repart et
votre programme continue.

33
00:01:28,940 --> 00:01:32,320
En fait si on regarde dans ce
scénario, il y a 2 points vraiment importants.

34
00:01:32,910 --> 00:01:35,710
Il y a, d'une part, le fait
qu'on a recompilé la méthode

35
00:01:35,910 --> 00:01:38,350
au vol, plusieurs fois
d'ailleurs, mais ça c'est le

36
00:01:38,550 --> 00:01:39,940
travail du compilateur, on va dire.

37
00:01:40,900 --> 00:01:44,220
Mais surtout c'est qu'on a
transformé et modifié la pile

38
00:01:44,420 --> 00:01:48,640
d'exécution de façon à
pouvoir injecter des morceaux de

39
00:01:48,840 --> 00:01:51,620
piles de façon à ce qu'on
puisse continuer l'exécution,

40
00:01:51,820 --> 00:01:52,890
alors qu'au départ
on avait une erreur.

41
00:01:53,710 --> 00:01:55,760
Ce que je veux vous
montrer, c'est que finalement il ne

42
00:01:56,000 --> 00:01:58,450
s'agit pas juste de réifier
la pile ou rendre objet la

43
00:01:58,650 --> 00:02:00,460
pile, il ne s'agit pas juste
d'un exercice de style, c'est

44
00:02:00,660 --> 00:02:02,550
quelque chose qui va
permettre d'améliorer l'expérience

45
00:02:02,750 --> 00:02:05,450
utilisateur et de créer des
outils beaucoup plus puissants.

46
00:02:05,660 --> 00:02:08,410
Ce que je vais vous montrer
aussi que c'est utilisé dans

47
00:02:08,610 --> 00:02:10,430
Seaside pour servir
des applications Web.

48
00:02:11,150 --> 00:02:13,050
En fait, ce qu'il faut voir,
c'est que la pile Pharo, en

49
00:02:13,250 --> 00:02:15,650
général c'est une pile C, la
machine virtuelle a sa pile,

50
00:02:16,060 --> 00:02:19,110
et que, à la demande, on peut la
transformer en un objet vivant.

51
00:02:19,310 --> 00:02:20,940
Ce qui est sympa, c'est
qu'on peut naviguer cet objet

52
00:02:21,140 --> 00:02:25,380
vivant, mais aussi
qu'on peut le modifier.

53
00:02:25,790 --> 00:02:27,540
Quand je dis le "modifier",
ça veut dire que, quand je

54
00:02:27,740 --> 00:02:31,840
vais modifier cet objet "Pharo", ça
va modifier la pile C sous-jacente.

55
00:02:32,040 --> 00:02:34,070
Ça, c'est vraiment très puissant.

56
00:02:35,770 --> 00:02:38,840
C'est le support aussi pour
toutes les exceptions, c'est

57
00:02:39,040 --> 00:02:40,830
pour ça que je vous suggère de
lire le chapitre sur les exceptions.

58
00:02:42,320 --> 00:02:46,360
En effet, on va naviguer
cette pile pour chercher les

59
00:02:46,560 --> 00:02:51,100
Block Catch, qu'on
appelle les handlers, des

60
00:02:51,300 --> 00:02:54,860
exceptions. Et c'est aussi
la transformation de cette

61
00:02:55,060 --> 00:02:59,410
pile en objet permet de
construire des continuations, et

62
00:02:59,610 --> 00:03:02,730
donc de faire des serveurs
Web comme dans les langages

63
00:03:02,930 --> 00:03:04,480
fonctionnels, tels
que Scheme par exemple.

64
00:03:05,660 --> 00:03:07,000
Comment ça marche ?

65
00:03:07,200 --> 00:03:10,330
En fait, Pharo vous propose une
variable qui s'appelle thisContext.

66
00:03:11,100 --> 00:03:15,180
En général, on dit que Pharo
a 3 pseudo-variables: self,

67
00:03:15,380 --> 00:03:16,520
super et thisContext.

68
00:03:19,340 --> 00:03:21,090
Quand vous demandez la
valeur de thisContext, ça va

69
00:03:21,290 --> 00:03:24,130
retourner la pile
d'exécution que vous pouvez naviguer.

70
00:03:24,330 --> 00:03:26,410
C'est la pile qui est
affichée quand vous ouvrez un

71
00:03:26,610 --> 00:03:31,470
débugger, et c'est
basé sur thisContext.

72
00:03:31,670 --> 00:03:34,090
Donc, ce que je vous
suggère, c'est par exemple de vous

73
00:03:34,290 --> 00:03:37,070
amuser à définir une petite
méthode dans laquelle vous

74
00:03:37,270 --> 00:03:40,710
allez mettre un halt, ça
va vous ouvrir un débugger;

75
00:03:40,910 --> 00:03:42,360
mais vous pouvez aussi,
dans cette méthode, taper

76
00:03:42,610 --> 00:03:47,000
littéralement thisContext, et
vous allez pouvoir l'inspecter

77
00:03:47,200 --> 00:03:49,640
et vous allez avoir un inspecteur
sur la pile d'exécution elle-même.

78
00:03:50,720 --> 00:03:55,420
Là, je voudrais vous montrer 2
petits exemples d'utilisation

79
00:03:55,620 --> 00:03:57,480
de thisContext. Le
premier, c'est la déprécation.

80
00:03:58,430 --> 00:04:00,860
Quand on veut changer une
API en disant "N'utilisez plus

81
00:04:01,060 --> 00:04:04,650
cette API, utilisez cette API", que
va-t-on faire en tant que programmeur?

82
00:04:04,850 --> 00:04:07,770
En tant que programmeur, je
vais éditer ma méthode et je

83
00:04:08,000 --> 00:04:11,410
vais utiliser le message
"Deprecated on in", c'est ce que

84
00:04:11,610 --> 00:04:13,370
je vous avais montré dans
le cours sur les exceptions.

85
00:04:14,650 --> 00:04:19,150
Donc là, je veux juste
exprimer un petit message "Utilise

86
00:04:19,350 --> 00:04:24,150
Bar". Qu'est-ce que la
déprécation va afficher à l'

87
00:04:24,350 --> 00:04:28,690
utilisateur? Elle va
afficher "Message foo is deprecated

88
00:04:29,110 --> 00:04:33,000
in Pharo". Il faut voir ici
que moi, en tant qu'utilisateur,

89
00:04:33,200 --> 00:04:37,030
je n'ai pas écrit dans
quelle méthode j'étais, par

90
00:04:37,230 --> 00:04:40,750
contre, lui il sait identifier que
"foo", c'était la méthode appelante.

91
00:04:42,270 --> 00:04:45,230
C'est ça le point, dans
les arguments du message

92
00:04:45,430 --> 00:04:48,380
"Deprecated", je n'utilise pas
"foo" ou la méthode appelante.

93
00:04:49,130 --> 00:04:50,420
Maintenant, voyons
comment c'est implémenter.

94
00:04:52,610 --> 00:04:57,360
Le message "Deprecated" est
une exception, deprecation.

95
00:04:59,410 --> 00:05:02,020
Il va prendre les arguments,
la chaîne d'explications, la

96
00:05:02,220 --> 00:05:05,150
date et puis la version, mais en
plus il va rajouter l'expression

97
00:05:05,350 --> 00:05:06,220
"thisContext sender method".

98
00:05:06,920 --> 00:05:08,310
Qu'est-ce que ça veut dire ?

99
00:05:08,510 --> 00:05:12,440
thisContext, c'est la pile
au moment de l'exécution de la

100
00:05:12,640 --> 00:05:17,430
méthode Deprecated. Ça veut
dire que là, avec Sender, je

101
00:05:17,630 --> 00:05:20,510
vais pouvoir accéder à la
méthode appelante, ça, ça va me

102
00:05:20,710 --> 00:05:24,080
rendre "fou", puisque
c'était l'exemple, et je vais

103
00:05:24,280 --> 00:05:25,440
pouvoir lui demander
quelle est ta méthode.

104
00:05:25,650 --> 00:05:28,160
Donc, en fait,
thisContext sender method, ça va me

105
00:05:28,360 --> 00:05:30,950
retourner la méthode
compilée, puisque c'est un objet en

106
00:05:31,150 --> 00:05:34,350
Pharo bien sûr, la
méthode compilée à foo.

107
00:05:35,300 --> 00:05:38,390
Et donc l'exception va
pouvoir vraiment utiliser ce qu'il

108
00:05:38,590 --> 00:05:41,340
faut et aller extraire le
sélecteur de cette méthode,

109
00:05:41,540 --> 00:05:43,730
pour pouvoir faire un message
qui soit plus compréhensible.

110
00:05:44,340 --> 00:05:46,820
Donc ça, c'était juste
pour faire en sorte que les

111
00:05:47,020 --> 00:05:49,770
messages soient plus
compréhensibles pour l'utilisateur

112
00:05:50,000 --> 00:05:53,730
sans forcer le programmeur à coder en
dur à chaque fois d'où c'était appelé.

113
00:05:54,340 --> 00:05:56,370
Maintenant, je vais vous
montrer une autre fonctionnalité

114
00:05:57,220 --> 00:05:58,880
qui est vraiment
extrêmement puissante.

115
00:05:59,870 --> 00:06:03,880
Quand on a un problème,
souvent on veut débugger, on

116
00:06:04,080 --> 00:06:07,160
aimerait pouvoir mettre un
Breakpoint dans une méthode

117
00:06:07,360 --> 00:06:10,070
qui est extrêmement
utilisée. Ça peut être par exemple

118
00:06:10,270 --> 00:06:13,130
utilisé par un Framework, et vous
vous voulez juste débugger votre version.

119
00:06:13,610 --> 00:06:16,690
Vous ne voulez pas
arrêter tout le système, et les

120
00:06:16,890 --> 00:06:20,920
conditions qu'on a, comme
halt once, vont arrêter une

121
00:06:21,120 --> 00:06:23,110
fois, alors que ce que vous
voulez dire, c'est que vous n'aimeriez

122
00:06:23,310 --> 00:06:27,800
vous arrêter que si cette
méthode a été appelée par cette

123
00:06:28,000 --> 00:06:30,070
autre méthode.
Comment exprime-t-on ça?

124
00:06:31,240 --> 00:06:33,380
D'un point de vue des outils
du programmeur je vais juste

125
00:06:33,580 --> 00:06:35,080
exprimer ça de la manière
suivante: nous allons dire "Je

126
00:06:35,600 --> 00:06:38,310
veux m'arrêter seulement si
j'ai été appelé, si foo a été

127
00:06:38,510 --> 00:06:39,470
appelé par la
méthode testSetInitialized.

128
00:06:39,740 --> 00:06:42,710
Maintenant, voyons
comme on implémente ça.

129
00:06:43,000 --> 00:06:45,330
Vous voyez bien en effet que
dans tous les autres cas, il

130
00:06:45,530 --> 00:06:46,790
faut que cette
méthode ne s'arrête pas.

131
00:06:47,000 --> 00:06:48,890
Comment donc est-ce implémenté ?

132
00:06:49,090 --> 00:06:51,940
Vous pouvez le voir dans Pharo,
je vous invite à ouvrir le code.

133
00:06:52,260 --> 00:06:56,910
Vous avez Halt qui est une
exception, et vous avez la méthode "if".

134
00:06:57,820 --> 00:06:58,580
Qu'est ce qu'on fait ?

135
00:06:58,780 --> 00:07:00,040
Elle a plusieurs cas parce
que vous pouvez passer un

136
00:07:00,240 --> 00:07:01,860
block, on va juste
regarder le cas qui nous intéresse

137
00:07:02,060 --> 00:07:03,720
quand on a un symbole:
donc, il regarde la condition

138
00:07:03,920 --> 00:07:04,680
"est-ce que c'est un symbole ?",

139
00:07:04,880 --> 00:07:09,680
si oui, alors regarde si la
chaîne d'appel contient le

140
00:07:09,880 --> 00:07:11,400
symbole. Donc regardons.

141
00:07:12,560 --> 00:07:16,030
Voilà, on tombe sur cette
méthode-là, que fait cette méthode?

142
00:07:16,230 --> 00:07:18,940
Là, vous imaginez que vous
avez "testSetInitialized"

143
00:07:23,830 --> 00:07:24,590
qui est un argument ici.

144
00:07:26,290 --> 00:07:28,110
La première chose qu'elle
fait, déjà, c'est de dire "Je

145
00:07:28,840 --> 00:07:33,010
veux récupérer la pile
d'exécution", donc Context, en

146
00:07:33,210 --> 00:07:36,140
Pharo c'est souvent
synonyme de pile d'exécution, donc

147
00:07:36,340 --> 00:07:38,340
Context, je veux
avoir la pile d'exécution.

148
00:07:38,540 --> 00:07:41,660
Et maintenant, je vais
faire un WhileFalse, tant que je

149
00:07:41,860 --> 00:07:43,570
ne suis pas en haut de la
pile d'exécution… Alors,

150
00:07:43,770 --> 00:07:45,270
comment définir "en
haut de la pile exécution"?

151
00:07:45,470 --> 00:07:47,010
Ça veut dire qu'il n'y a
plus de Sender, il n'y a plus

152
00:07:47,210 --> 00:07:51,700
personne qui m'invoque. Donc en
haut, c'est quand l'invocation

153
00:07:51,900 --> 00:07:55,330
est nil. Donc tant que
l'invocation n'est pas nil, je

154
00:07:55,530 --> 00:07:59,860
vais passer d'un morceau
de pile à l'autre, donc vous

155
00:08:00,060 --> 00:08:02,420
avez vos morceaux de pile
comme ça, conceptuellement au

156
00:08:02,620 --> 00:08:05,400
moins, et vous allez monter de l'un
à l'autre, et là vous faites Sender.

157
00:08:06,930 --> 00:08:11,340
Et là on va regarder si le

158
00:08:11,540 --> 00:08:15,500
sélecteur, par exemple
quelque part ici je vais avoir

159
00:08:15,700 --> 00:08:20,300
"Test", est-ce que le
symbole d'appel de cette

160
00:08:20,500 --> 00:08:23,280
pile correspond à l'endroit
où je voudrais m'arrêter, où

161
00:08:23,480 --> 00:08:26,450
j'ai dit "Est-ce que je
suis appelé par TestSet?"

162
00:08:26,650 --> 00:08:29,120
Oui, si c'est le cas, je
m'arrête, je fais un signal

163
00:08:29,320 --> 00:08:31,170
parce que la classe
est une exception.

164
00:08:32,060 --> 00:08:35,140
Et donc, ce dont il faut bien se
rendre compte, c'est qu'implémenter

165
00:08:35,340 --> 00:08:38,100
ça dans un langage qui n'a
pas de réification de la pile

166
00:08:38,330 --> 00:08:41,540
c'est extrêmement compliqué.
Là vous l'avez en 5 lignes.

167
00:08:41,810 --> 00:08:43,800
Dans Pharo, ça paraît un
peu complexe peut-être à

168
00:08:44,000 --> 00:08:47,130
comprendre mais c'est super
puissant, c'est super compact

169
00:08:47,330 --> 00:08:49,550
et on ne peut faire ça que
parce qu'on a cette réification.

170
00:08:50,180 --> 00:08:52,660
Donc ce qu'il faut voir,
c'est qu'on ne va pas souvent se

171
00:08:52,860 --> 00:08:54,120
servir de thisContext parce que
c'est une fonctionnalité avancée.

172
00:08:54,320 --> 00:08:57,780
Maintenant, c'est super
important pour l'innovation.

173
00:08:58,000 --> 00:08:59,410
Ça peut être de l'innovation
au niveau des outils, c'est

174
00:08:59,610 --> 00:09:03,740
ce qu'on a montré avec ces
tests qui sont extrêmement

175
00:09:03,940 --> 00:09:06,320
compliqués à exprimer dans
d'autres langages, mais ça va

176
00:09:06,520 --> 00:09:09,030
être par exemple la possibilité
de représenter les continuations.

177
00:09:09,470 --> 00:09:11,080
Et donc c'est pour ça que la
personne qui a fait Seaside

178
00:09:11,280 --> 00:09:13,390
l'a fait dans l'ancêtre de
Pharo, parce qu'il pouvait

179
00:09:14,100 --> 00:09:16,410
manipuler la pile pour
représenter des continuations qui

180
00:09:16,610 --> 00:09:20,180
allaient être la base du
mécanisme Call and Answer, qu'on

181
00:09:20,380 --> 00:09:21,730
vous a présentés dans Seaside.

182
00:09:23,440 --> 00:09:25,280
Je vous ai présenté une
fonctionnalité assez avancée de

183
00:09:25,480 --> 00:09:26,760
Pharo, vous pouvez vous amuser avec.

