1
00:00:00,700 --> 00:00:03,520
Bonjour à tous. Dans cette
séquence, nous allons parler

2
00:00:04,340 --> 00:00:08,590
de la campagne anti if, et
en particulier pourquoi est-ce

3
00:00:08,790 --> 00:00:13,660
que renvoyer nul et
tester nul n'est pas terrible.

4
00:00:13,890 --> 00:00:16,800
Voici un exemple de code qui
n'est pas du tout objet, et

5
00:00:17,070 --> 00:00:20,840
on va voir que là on a une
méthode qui prend un animal en

6
00:00:21,040 --> 00:00:23,930
paramètre, et en fonction du
type de l'animal on va faire

7
00:00:24,130 --> 00:00:26,760
des choses différentes. Si
c'est un chien, on va lui

8
00:00:27,000 --> 00:00:29,370
demander de remuer la
queue. Si c'est un canard, on va

9
00:00:29,570 --> 00:00:30,450
lui demander de faire coin coin.

10
00:00:31,050 --> 00:00:33,260
Et si c'est un chat, on va lui
demander de faire autre chose.

11
00:00:34,190 --> 00:00:37,060
Pourquoi ce n'est pas bon et
pourquoi en général et l'utilisation

12
00:00:37,260 --> 00:00:41,870
de if, en particulier quand
c'est appliqué pour vérifier

13
00:00:42,670 --> 00:00:47,080
le type du receveur, pourquoi
est-ce que ça ce n'est pas très bon?

14
00:00:47,280 --> 00:00:49,510
Parce que si je veux
ajouter un nouvel animal, il va

15
00:00:49,710 --> 00:00:52,480
falloir que je cherche
partout dans tout le code du

16
00:00:52,680 --> 00:00:56,680
projet, tous les if qui
pourraient être intéressants.

17
00:00:57,000 --> 00:00:58,910
Donc, je vais devoir
modifier plein de codes un peu

18
00:00:59,110 --> 00:01:00,690
partout dans le projet, et ça
ce n'est vraiment pas terrible.

19
00:01:01,700 --> 00:01:03,630
Et puis en plus, parce
que les méthodes, à force de

20
00:01:03,830 --> 00:01:07,140
rajouter des cas, elles
vont grossir de plus en plus et

21
00:01:07,340 --> 00:01:09,170
elles vont être noyées dans
les détails, c'est-à-dire que

22
00:01:09,370 --> 00:01:12,530
si maintenant après avoir
ajouté plein d'animaux, la

23
00:01:12,730 --> 00:01:15,140
méthode va être très
longue et pour chaque animal, je

24
00:01:15,340 --> 00:01:16,940
peux avoir plein de
détails. Par exemple ici c'est

25
00:01:17,350 --> 00:01:19,140
quelque chose qui est
particulièrement simple mais si

26
00:01:19,340 --> 00:01:20,920
maintenant je me dis
peut-être que les chiens n'ont pas

27
00:01:21,120 --> 00:01:23,340
tous des queues, il va
falloir que je fasse un cas "Si le

28
00:01:23,540 --> 00:01:24,370
chien a une queue, je fais ça.

29
00:01:24,570 --> 00:01:26,870
Si le chien n'a pas de
queue, alors je fais ça " Le code

30
00:01:27,070 --> 00:01:31,510
va être de plus en plus gros et
de moins en moins compréhensible.

31
00:01:33,000 --> 00:01:35,860
Pour remplacer tous ces
trucs-là, on envoie des messages.

32
00:01:36,070 --> 00:01:38,250
C'est tout ce qu'on vous
répète depuis le début de ce

33
00:01:38,450 --> 00:01:40,160
cours-là, et c'est
vraiment la chose que vous devez

34
00:01:40,360 --> 00:01:43,920
retenir: l'envoi de
messages. On peut remplacer

35
00:01:44,120 --> 00:01:47,560
facilement le code
précédent par celui-ci où on

36
00:01:47,760 --> 00:01:50,300
implémente une méthode
showHappiness dans chaque classe

37
00:01:50,500 --> 00:01:52,760
qui nous intéresse, et c'est
chaque classe qui va décider

38
00:01:53,000 --> 00:01:56,420
comment est-ce que tel ou tel
animal va montrer qu'il est content.

39
00:01:56,740 --> 00:02:01,680
Ensuite une fois que
j'ai un animal, il me suffit

40
00:02:01,880 --> 00:02:06,730
d'envoyer le
message, showHappiness à l'

41
00:02:06,930 --> 00:02:10,570
animal, et une de ces
méthodes va être exécutée.

42
00:02:10,770 --> 00:02:14,780
Là, on voit bien que
c'est Pharo qui fait le if.

43
00:02:15,000 --> 00:02:18,100
C'est Pharo qui se dit "Si
mon animal est de ce type-là,

44
00:02:18,310 --> 00:02:20,060
alors c'est cette
méthode-là qui va s'exécuter.

45
00:02:20,260 --> 00:02:21,600
" Tout ça se fait
automatiquement, je n'ai pas besoin de

46
00:02:21,800 --> 00:02:22,750
l'écrire en tant que développeur.

47
00:02:23,120 --> 00:02:25,310
Donc, il n'y a aucune raison
d'écrire des if par rapport

48
00:02:25,510 --> 00:02:28,170
au type des objets,
c'est Pharo qui gère ça.

49
00:02:28,370 --> 00:02:30,760
Ça rend juste le code plus
compliqué à lire et moins évolutif.

50
00:02:32,580 --> 00:02:36,680
On va parler maintenant du
cas particulier du nil parce

51
00:02:36,880 --> 00:02:41,480
que si une méthode retourne
un nil, vous allez forcer les

52
00:02:41,680 --> 00:02:43,060
clients à utiliser if.

53
00:02:43,260 --> 00:02:46,010
Et on vient de voir qu'utiliser
if, c'était rarement une bonne idée.

54
00:02:47,020 --> 00:02:51,190
Ici, si je prends un exemple
de code qui dit l'idée c'est

55
00:02:51,390 --> 00:02:53,630
de faire quelque chose en
fonction d'un paramètre et en

56
00:02:53,830 --> 00:02:56,490
fonction d'un objet inférenceur,
peu importe ce que ce code-là fait.

57
00:02:58,400 --> 00:03:01,110
Par contre ici, je vois que
dans certains cas, il renvoie nil.

58
00:03:01,840 --> 00:03:05,000
Ce qui fait quand je vais
devoir utilise ce code, donc

59
00:03:05,200 --> 00:03:07,360
quand j'envoie le message
rulesForFact à un référenceur,

60
00:03:07,560 --> 00:03:09,040
il va falloir que je teste.

61
00:03:09,240 --> 00:03:11,150
Est-ce que
rulesForFact m'a renvoyé Nil?

62
00:03:11,350 --> 00:03:12,750
Si oui alors je fais ça.

63
00:03:13,000 --> 00:03:14,470
Si ce n'est pas nil,
alors je fais autre chose.

64
00:03:14,680 --> 00:03:16,740
Dans ce cas-là en
particulier, on peut se rendre compte

65
00:03:16,940 --> 00:03:20,270
que ici comme on a un
pluriel et ici on a un pluriel,

66
00:03:20,470 --> 00:03:23,620
probablement que cette
méthode-là va renvoyer une collection.

67
00:03:24,200 --> 00:03:27,710
Pour éviter nil, une bonne
solution souvent c'est que

68
00:03:27,910 --> 00:03:29,860
quand on a une méthode qui
retourne une collection, c'est

69
00:03:30,060 --> 00:03:32,800
de retourner une collection vide,
ça marche vraiment très souvent.

70
00:03:33,390 --> 00:03:35,780
Et retourner une collection
vide plutôt que de retourner

71
00:03:36,000 --> 00:03:38,250
nil, ça facilite
vraiment l'écriture du code.

72
00:03:38,910 --> 00:03:42,000
Parce que maintenant les
clients ont juste à itérer sur

73
00:03:42,200 --> 00:03:43,720
la collection, si elle est
vide il ne va rien se passer,

74
00:03:43,920 --> 00:03:44,740
c'est exactement ça qui était prévu.

75
00:03:46,470 --> 00:03:51,150
Pour les cas exceptionnels,
par exemple vous avez un flux

76
00:03:51,350 --> 00:03:53,910
d'écriture de fichiers et
puis votre flux n'a pas été

77
00:03:54,110 --> 00:03:56,100
ouvert en écriture, et
donc il y a une erreur.

78
00:03:56,580 --> 00:03:59,200
Plutôt que retourner nil,
vous informez le système de la

79
00:03:59,400 --> 00:04:01,450
situation exceptionnelle
en levant une exception.

80
00:04:02,260 --> 00:04:05,310
En Pharo, on appelle ça
"signaler une exception".

81
00:04:06,110 --> 00:04:08,760
On crée une instance d'une
 classe exception ou d'une

82
00:04:08,960 --> 00:04:11,040
sous-classe et on
envoie un signal, ce

83
00:04:13,660 --> 00:04:17,750
qui permet d'éviter que
directement le client de la

84
00:04:17,950 --> 00:04:20,260
méthode, ici de la méthode
nextPutAll, ait besoin de

85
00:04:20,460 --> 00:04:22,250
tester "Si c'est nil,
probablement que quelque chose s'est

86
00:04:22,450 --> 00:04:23,730
mal passé, alors il
faut que je fasse ça.

87
00:04:24,220 --> 00:04:26,940
" Là, soit le client décide
de traiter l'exception, soit

88
00:04:27,140 --> 00:04:28,810
c'est le client du client qui
décide de traiter l'exception,

89
00:04:29,010 --> 00:04:31,570
soit c'est le client du
client du client, et caetera.

90
00:04:32,030 --> 00:04:33,660
On n'est pas obligé de
faire ça à tous les niveaux, on

91
00:04:33,860 --> 00:04:36,200
peut décider d'un niveau qui
nous intéresse pour capturer

92
00:04:36,400 --> 00:04:37,520
l'exception et en
faire quelque chose.

93
00:04:38,520 --> 00:04:40,960
Ça évite tout un tas de if.

94
00:04:41,160 --> 00:04:44,610
Un autre cas où on trouve
des vérifications par rapport à

95
00:04:44,810 --> 00:04:48,040
la valeur nil, c'est dans
les variables d'instances qui

96
00:04:48,240 --> 00:04:51,460
ne sont pas initialisées.
Si vous avez du code qui dit

97
00:04:51,660 --> 00:04:55,400
"Si ma variable est encore à
nil, alors je fais ça", dans

98
00:04:55,600 --> 00:04:58,620
ces cas-là il vaut mieux
initialiser la variable tout de

99
00:04:58,820 --> 00:05:01,620
suite avec une valeur qui
va marcher dans tous les cas.

100
00:05:02,130 --> 00:05:05,920
Là, ma variable members
qui est censée contenir une

101
00:05:06,120 --> 00:05:08,850
collection, plutôt que la
laisser à nil je l'initialise à

102
00:05:09,050 --> 00:05:10,250
une collection vide dès le départ.

103
00:05:10,900 --> 00:05:13,000
Ça encore une fois ça
marche très souvent.

104
00:05:14,220 --> 00:05:18,800
Quand vous voulez donner une
valeur à une variable et que

105
00:05:19,000 --> 00:05:22,150
c'est coûteux de calculer la
valeur de cette variable-là,

106
00:05:22,600 --> 00:05:26,530
vous pouvez attendre le dernier
moment avant de calculer cette valeur-là.

107
00:05:26,730 --> 00:05:28,950
Peut-être qu'elle ne sera
jamais calculée et donc que

108
00:05:29,150 --> 00:05:30,240
vous aurez gagné du
temps d'exécution.

109
00:05:31,420 --> 00:05:34,750
Dans ces cas-là, on utilise
l'initialisation paresseuse

110
00:05:35,160 --> 00:05:39,010
et c'est au moment où on va
avoir besoin d'une valeur qu'on

111
00:05:39,210 --> 00:05:41,440
va regarder si la valeur est
encore à nil, alors je mets

112
00:05:41,640 --> 00:05:45,950
quelque chose dedans. Si
elle n'est plus à nil, je

113
00:05:46,150 --> 00:05:47,220
retourne directement sa valeur.

114
00:05:48,000 --> 00:05:52,360
Ce qui fait qu'ici, j'ai un if par
rapport à nil mais je n'en ai qu'un.

115
00:05:53,110 --> 00:05:56,830
Tous les autres
utilisateurs de la variable vont passer

116
00:05:57,030 --> 00:06:00,080
par cette méthode et
n'auront pas à tester si c'est nil.

117
00:06:01,580 --> 00:06:05,960
Parfois, il y a des cas
où il va falloir tester.

118
00:06:06,160 --> 00:06:09,000
Il va falloir vérifier
est-ce que j'ai quelque chose à

119
00:06:09,200 --> 00:06:12,040
faire ou pas, c'est ce
qu'on trouve dans cet exemple.

120
00:06:12,830 --> 00:06:15,580
L'idée de ça c'est qu'on
a une palette d'outils.

121
00:06:16,140 --> 00:06:19,580
Si on a un outil qui est
sélectionné, on peut faire quelque chose.

122
00:06:19,780 --> 00:06:22,620
Si aucun outil n'est
sélectionné, on ne peut rien faire.

123
00:06:26,700 --> 00:06:30,390
Si selectedTool retourne
nil, il n'y a pas d'outil

124
00:06:30,590 --> 00:06:31,510
sectionné, donc on ne fait rien.

125
00:06:31,780 --> 00:06:34,690
Si selectedTool retourne
quelque chose, alors on va

126
00:06:34,890 --> 00:06:39,610
demander à ce
quelque chose de faire une

127
00:06:39,810 --> 00:06:44,190
action. Une bonne façon de
remplacer ça, c'est d'utiliser

128
00:06:44,390 --> 00:06:45,530
le design pattern null Object.

129
00:06:46,060 --> 00:06:48,870
Ce que je fais c'est que
plutôt qu'avoir les 2 cas, j'ai

130
00:06:49,070 --> 00:06:51,320
un outil, je n'ai pas
d'outil, on ne va avoir qu'un seul

131
00:06:51,520 --> 00:06:54,390
cas j'ai un outil et un
des outils ne fera rien.

132
00:06:54,590 --> 00:06:56,720
Et ce sera l'outil qui ne fera
rien qui sera sélectionné par défaut.

133
00:06:57,330 --> 00:06:59,030
Là, je crée un
outil qui ne fait rien.

134
00:06:59,260 --> 00:07:01,710
Quand je lui demande de faire
des actions, il ne fait rien.

135
00:07:03,110 --> 00:07:05,700
Et par défaut, dans ma palette
d'outils je vais sectionner ce truc-là.

136
00:07:06,550 --> 00:07:08,280
Plutôt que de ne rien
sélectionner, je sélectionne un

137
00:07:08,480 --> 00:07:11,950
outil qui ne fait rien.
C'est le design pattern Null

138
00:07:12,150 --> 00:07:14,550
Object, pour en savoir plus vous
avez ses références qui sont ici.

139
00:07:15,700 --> 00:07:19,540
En conclusion. Les messages
marchent toujours mieux que les if.

140
00:07:19,790 --> 00:07:22,940
Les if, vous allez vous en
servir dans certains cas, mais

141
00:07:23,370 --> 00:07:25,670
souvent vous allez pouvoir
vous en passer et envoyer des

142
00:07:25,870 --> 00:07:27,330
messages sera souvent mieux.

143
00:07:29,940 --> 00:07:32,660
Évitez de retourner la
valeur nil parce que ça force les

144
00:07:32,860 --> 00:07:36,520
vérifications avec if: si
la valeur est nulle, alors je

145
00:07:36,720 --> 00:07:40,000
fais ça; si la valeur n'est
pas nulle, alors je fais ça.

146
00:07:40,170 --> 00:07:40,930
"

147
00:07:41,130 --> 00:07:43,000
Initialisez vos variables
soit dès la création de l'objet,

148
00:07:43,200 --> 00:07:44,270
soit de façon paresseuse.

149
00:07:45,740 --> 00:07:48,210
Si vous pouvez, créez des
objets qui représentent un

150
00:07:48,410 --> 00:07:50,450
comportement par défaut ou
une absence de comportement.

151
00:07:51,120 --> 00:07:52,610
Tout ce que je viens de vous
raconter, c'est valable pour

152
00:07:52,810 --> 00:07:55,330
Pharo, mais c'est valable
aussi pour tous les langages objet.

153
00:07:56,480 --> 00:07:58,460
C'est important de garder
tout ce que je viens de vous

154
00:07:58,660 --> 00:08:00,340
raconter en tête quel que soit
le langage que vous utilisez.

