1 00:00:00,040 --> 00:00:00,080 "Une nouvelle façon de modéliser le monde" 2 00:00:00,120 --> 00:00:00,160 Stéphane Ducasse, research direction, Inria. 3 00:00:00,800 --> 00:00:01,840 -Dans ce cours, je vous montrerai 4 00:00:02,160 --> 00:00:04,480 que la programmation objet et la conception objet 5 00:00:04,800 --> 00:00:07,480 représentent le monde d'une manière décentralisée. 6 00:00:07,880 --> 00:00:13,080 D'abord, il faut voir qu'il n'y a pas un modèle central et unique du monde. 7 00:00:14,040 --> 00:00:18,200 Si on compare la notion de risque dans une banque et dans une assurance, 8 00:00:18,520 --> 00:00:20,400 on pourrait croire que c'est la même chose, mais non. 9 00:00:20,720 --> 00:00:24,000 L'assurance, la notion de risque, c'est son business intégral. 10 00:00:24,320 --> 00:00:27,080 Alors que dans la banque, le risque est juste que vous ne remboursiez pas, 11 00:00:27,400 --> 00:00:28,800 donc ils prennent des précautions. 12 00:00:29,120 --> 00:00:30,840 Donc, le monde... 13 00:00:31,160 --> 00:00:35,680 Vous allez avoir différents modèles pour modéliser une même chose. 14 00:00:36,000 --> 00:00:39,880 Maintenant, il y a différentes façons d'aborder la modélisation 15 00:00:40,200 --> 00:00:41,360 et de créer ces modèles. 16 00:00:41,680 --> 00:00:44,200 Dans le passé, des approches étaient dirigées par les données, 17 00:00:44,520 --> 00:00:47,440 étaient plus favorables aux bases de données relationnelles. 18 00:00:47,760 --> 00:00:50,600 Il y a eu de la programmation objet, ce qu'on étudie dans ce cours, 19 00:00:50,920 --> 00:00:53,120 de la programmation procédurale et d'autres. 20 00:00:54,240 --> 00:00:56,280 Là, on va comparer ces deux approches. 21 00:00:56,600 --> 00:00:58,600 L'approche orientée, qu'est-ce que c'est ? 22 00:00:58,920 --> 00:01:01,360 C'est un paradigme. Ce n'est pas une technologie. 23 00:01:01,680 --> 00:01:05,160 C'est une façon différente de simuler et de représenter le monde 24 00:01:05,480 --> 00:01:07,600 pour en tirer les objectifs qu'on a. 25 00:01:07,920 --> 00:01:11,520 L'idée, c'est d'organiser cette modélisation du monde 26 00:01:11,840 --> 00:01:17,560 avec une représentation d'organisations décentralisée. 27 00:01:17,880 --> 00:01:19,360 L'idée, à ce moment-là, 28 00:01:19,680 --> 00:01:24,280 c'est d'essayer de contrôler la complexité de ces systèmes 29 00:01:24,600 --> 00:01:26,360 et de permettre leur meilleure réutilisation. 30 00:01:26,680 --> 00:01:27,800 C'est ce qu'on va voir. 31 00:01:29,320 --> 00:01:32,360 D'abord, on va faire une comparaison 32 00:01:32,680 --> 00:01:38,080 entre une modélisation procédurale et une modélisation objet. 33 00:01:40,240 --> 00:01:43,400 Si on regarde la modélisation procédurale, 34 00:01:43,720 --> 00:01:46,560 elle va faire un focus sur les données et les procédures. 35 00:01:46,880 --> 00:01:49,320 Les données sont partagées entre toutes les procédures. 36 00:01:49,640 --> 00:01:51,920 Les données sont accessibles par tous les clients 37 00:01:52,240 --> 00:01:55,680 et les procédures connaissent toutes les structures des données. 38 00:01:56,000 --> 00:02:00,280 Il n'y a pas cette distance qu'il y a entre un message et une méthode 39 00:02:00,600 --> 00:02:01,880 comme dans la modélisation objet. 40 00:02:02,200 --> 00:02:04,760 Il n'y a pas de notion de liaison tardive. 41 00:02:05,920 --> 00:02:09,920 Donc, ça veut dire qu'on a besoin d'un grand nombre de procédures. 42 00:02:10,240 --> 00:02:13,880 Il n'y a pas la possibilité d'avoir deux procédures qui ont le même nom 43 00:02:14,200 --> 00:02:16,720 et qui auraient des comportements différents, 44 00:02:17,040 --> 00:02:20,800 comme on l'a vu dans la programmation objet lors des cours précédents. 45 00:02:22,160 --> 00:02:24,360 Donc, prenons un exemple. 46 00:02:25,040 --> 00:02:28,320 Si on modélise une image ou un diagramme 47 00:02:28,640 --> 00:02:30,720 qui serait composé de formes géométriques... 48 00:02:31,040 --> 00:02:35,360 Là, j'ai un diagramme avec un rectangle, un carré et un cercle 49 00:02:35,680 --> 00:02:39,280 et je voudrais calculer l'aire de ce diagramme. 50 00:02:39,840 --> 00:02:42,640 Dans une vision procédurale du monde, 51 00:02:42,960 --> 00:02:46,440 je vais définir une procédure qui s'appelle pictureArea 52 00:02:46,760 --> 00:02:49,480 et dans cette procédure, que vais-je faire ? 53 00:02:49,800 --> 00:02:52,120 Je vais parcourir la liste 54 00:02:52,440 --> 00:02:56,160 des formes géométriques qui composent le diagramme 55 00:02:56,480 --> 00:02:57,720 et à chaque fois, je vais regarder. 56 00:02:58,040 --> 00:03:00,000 Je vais dire : "Si c'est un carré, je sais le calculer. 57 00:03:00,320 --> 00:03:03,120 Je vais faire côté multiplié par côté. 58 00:03:03,440 --> 00:03:06,560 Si c'est un rectangle, je vais faire longueur multipliée par largeur. 59 00:03:06,880 --> 00:03:09,720 Si c'est un cercle, je vais calculer pi r²." 60 00:03:10,040 --> 00:03:12,400 Et je vais rendre la chose. Là, je l'ai écrit en Java. 61 00:03:12,720 --> 00:03:16,320 On peut très bien développer de façon procédurale dans un langage objet. 62 00:03:16,640 --> 00:03:19,560 Rien ne nous en empêche. Là, on a la même définition en Pharo. 63 00:03:19,880 --> 00:03:24,320 On va faire une boucle et regarder pour chacune des formes géométriques 64 00:03:24,640 --> 00:03:25,680 et on va calculer ça. 65 00:03:26,000 --> 00:03:27,960 Quel est le désavantage de cette approche ? 66 00:03:28,280 --> 00:03:31,440 Il y en a plusieurs. Le premier, c'est que la définition est monolithique. 67 00:03:31,760 --> 00:03:35,280 Elle n'est pas embêtante en elle-même, mais ses applications le sont. 68 00:03:35,600 --> 00:03:37,680 Ça signifie que je ne peux pas la réutiliser. 69 00:03:38,000 --> 00:03:40,560 Je ne peux pas réutiliser la fonction pictureArea 70 00:03:40,880 --> 00:03:42,600 si j'ajoute une nouvelle forme. 71 00:03:43,240 --> 00:03:45,680 Si demain, je mets une étoile dedans, 72 00:03:46,000 --> 00:03:49,240 je vais devoir modifier le code de pictureArea. 73 00:03:49,560 --> 00:03:51,280 En plus, je ne peux pas réutiliser 74 00:03:51,600 --> 00:03:55,400 la définition de l'aire dans un carré ou un rectangle, 75 00:03:55,720 --> 00:03:58,360 puisque tout est défini au même endroit. 76 00:03:59,280 --> 00:04:02,720 Le modèle objet, d'un autre côté, est complètement différent. 77 00:04:03,040 --> 00:04:07,360 Il va déléguer le calcul de l'aire à d'autres entités. 78 00:04:07,680 --> 00:04:11,920 Donc, la classe Diagramme, Picture, que va-t-elle faire ? 79 00:04:12,240 --> 00:04:17,600 Elle va juste faire une boucle sur chacune des formes géométriques 80 00:04:17,920 --> 00:04:21,160 et demander à chaque forme géométrique de calculer une aire, son aire. 81 00:04:21,480 --> 00:04:25,280 Chaque forme géométrique va définir une méthode aire 82 00:04:25,600 --> 00:04:28,000 qui va lui retourner la bonne définition. 83 00:04:28,600 --> 00:04:29,880 Quel est l'avantage ? 84 00:04:30,200 --> 00:04:34,360 Déjà, je peux ajouter une forme géométrique sans aucun problème. 85 00:04:34,680 --> 00:04:38,400 Il suffit juste que j'ajoute une classe avec le message aire 86 00:04:38,720 --> 00:04:40,360 et que je crée les objets de cette classe. 87 00:04:40,680 --> 00:04:46,240 Je peux réutiliser, là, la méthode aire de la classe Picture. 88 00:04:46,800 --> 00:04:49,560 Donc, là, j'ai vraiment de la réutilisation. 89 00:04:49,880 --> 00:04:52,240 On voit qu'on a un calcul décentralisé. 90 00:04:52,560 --> 00:04:56,960 Ça signifie que la classe Diagramme va demander aux autres classes 91 00:04:57,280 --> 00:05:00,840 de faire un calcul pour elle. 92 00:05:02,920 --> 00:05:07,000 Si on regarde, il y a vraiment un point central. 93 00:05:07,320 --> 00:05:12,800 C'est que si même dans la vision objet, 94 00:05:13,120 --> 00:05:15,320 j'avais défini des méthodes avec des noms différents, 95 00:05:15,640 --> 00:05:19,880 je n'aurais pas pu avoir le bénéfice entier de l'approche objet. 96 00:05:20,200 --> 00:05:25,440 Ce qui est important, c'est que chacune des formes géométriques 97 00:05:25,760 --> 00:05:29,160 se met d'accord et offre la même interface au client. 98 00:05:29,480 --> 00:05:34,440 Ça signifie que chacune des formes va offrir la méthode aire, 99 00:05:34,760 --> 00:05:38,000 ce qui va permettre au client de ne pas avoir à faire de distinction 100 00:05:38,800 --> 00:05:40,480 et du coup, qu'on puisse le réutiliser. 101 00:05:40,800 --> 00:05:42,000 Ça s'appelle le polymorphisme. 102 00:05:42,320 --> 00:05:46,280 Différents objets vont pouvoir répondre 103 00:05:46,600 --> 00:05:49,480 à un même message avec différentes exécutions. 104 00:05:50,000 --> 00:05:52,160 Ça, c'est tout d'un coup très puissant. 105 00:05:52,720 --> 00:05:57,960 Donc, qu'est-ce qu'une application dans un système objet ? 106 00:05:58,280 --> 00:06:02,600 C'est un ensemble d'entités qui vont collaborer et interagir. 107 00:06:02,920 --> 00:06:04,360 Les entités sont des objets. 108 00:06:04,680 --> 00:06:07,640 On a vu que les objets ont un comportement et un état. 109 00:06:07,960 --> 00:06:10,480 Que cet état est privé et n'est accessible que des méthodes. 110 00:06:10,800 --> 00:06:13,720 Que ces objets interagissent avec des messages 111 00:06:14,040 --> 00:06:15,720 et que ces messages sont résolus dynamiquement 112 00:06:16,040 --> 00:06:21,120 et que la méthode correspondante va être exécutée lors de l'exécution. 113 00:06:21,840 --> 00:06:25,560 Et le dernier point que j'ai mentionné, c'est que ces messages 114 00:06:25,880 --> 00:06:27,960 forment souvent des familles polymorphiques 115 00:06:28,280 --> 00:06:30,680 qui me permettront de réutiliser le code. 116 00:06:31,560 --> 00:06:34,400 Donc, les messages, je le disais, ont une entité unique. 117 00:06:34,720 --> 00:06:40,120 Le point central, c'est qu'ils doivent exposer des interfaces polymorphiques 118 00:06:40,440 --> 00:06:43,000 qui seront substituées par d'autres objets. 119 00:06:43,840 --> 00:06:45,680 Maintenant, j'aimerais aborder 120 00:06:46,000 --> 00:06:48,000 trois points essentiels de la programmation objet 121 00:06:48,320 --> 00:06:51,000 qui sont les pierres angulaires de la programmation objet. 122 00:06:51,320 --> 00:06:55,600 La première, c'est l'encapsulation. On l'a vue dans un autre cours. 123 00:06:55,920 --> 00:06:59,680 C'est l'idée qu'en tant que client, je vais envoyer un message à un objet 124 00:07:00,000 --> 00:07:03,320 et l'objet contrôle la manière dont il encode l'information 125 00:07:03,640 --> 00:07:05,640 et la manière dont il va faire du calcul. 126 00:07:05,960 --> 00:07:08,480 Cette encapsulation est vraiment importante, 127 00:07:08,800 --> 00:07:11,440 car je pourrai substituer un objet par un autre 128 00:07:11,760 --> 00:07:13,280 sans que le client soit impacté 129 00:07:13,600 --> 00:07:17,560 et c'est très important, car ça favorisera la réutilisation. 130 00:07:17,880 --> 00:07:22,680 Cette encapsulation va permettre, par exemple, une composition d'objets. 131 00:07:23,000 --> 00:07:26,160 En tant que client, qu'un objet fasse tout le calcul 132 00:07:26,480 --> 00:07:28,840 ou qu'il distribue son calcul à d'autres objets, 133 00:07:29,160 --> 00:07:32,920 ça ne m'importune pas à partir du moment où je ne sais pas que ça se passe 134 00:07:33,240 --> 00:07:35,680 et que je ne suis pas impacté par les décisions de cet objet. 135 00:07:36,000 --> 00:07:40,400 Donc, l'encapsulation et la composition d'objets vont de pair. 136 00:07:40,720 --> 00:07:44,880 La composition d'objets va permettre 137 00:07:45,200 --> 00:07:48,800 l'explicitation d'un calcul souvent de manière plus simple. 138 00:07:50,320 --> 00:07:52,880 L'autre pierre angulaire, c'est cette notion de distribution 139 00:07:53,200 --> 00:07:55,760 ou de décentralisation. 140 00:07:56,080 --> 00:08:00,880 L'idée, c'est que quand je vais calculer quelque chose, 141 00:08:01,200 --> 00:08:06,160 ça va être le résultat de plusieurs objets qui exécutent des sous-tâches. 142 00:08:07,000 --> 00:08:09,280 C'est favorisé par la liaison tardive 143 00:08:09,600 --> 00:08:13,960 qui va dire, en fait : "Je saurai quelle est la méthode à exécuter 144 00:08:14,280 --> 00:08:17,200 lors de l'exécution et ce sera basé sur la classe du receveur." 145 00:08:17,520 --> 00:08:20,720 C'est renforcé par cette notion de polymorphisme 146 00:08:21,040 --> 00:08:24,640 qui va faire que plusieurs objets vont pouvoir être substituables 147 00:08:25,440 --> 00:08:27,480 et proposer la même interface. 148 00:08:27,800 --> 00:08:31,880 Donc, cet ensemble de points va favoriser cette idée 149 00:08:32,200 --> 00:08:35,120 qu'on aura un système qui sera plus décentralisé 150 00:08:35,440 --> 00:08:38,640 et qui va pouvoir maximiser de la réutilisation. 151 00:08:38,960 --> 00:08:41,920 Dans l'exemple qu'on avait pris avec le diagramme, 152 00:08:42,240 --> 00:08:46,000 le comportement du calcul de l'aire du diagramme 153 00:08:46,320 --> 00:08:49,400 est indépendant du calcul de l'aire de chacun de ces éléments. 154 00:08:49,720 --> 00:08:51,160 Donc, on le réutilise. 155 00:08:52,120 --> 00:08:55,160 Le dernier point-clé de la programmation objet 156 00:08:55,480 --> 00:08:58,240 que je ne montre pas dans ce cours mais que je veux évoquer, 157 00:08:58,560 --> 00:09:00,800 c'est l'idée que je pourrai définir des abstractions 158 00:09:01,120 --> 00:09:02,800 par extension d'autres abstractions. 159 00:09:03,200 --> 00:09:06,360 Imaginons qu'on ait une classe qui représente des collections. 160 00:09:06,680 --> 00:09:09,960 Je pourrai définir une autre classe, qui est une OrderedCollection, 161 00:09:10,280 --> 00:09:11,600 par extension de la collection. 162 00:09:11,920 --> 00:09:15,600 Je pourrai définir la classe Tableau par extension de la classe Collection. 163 00:09:15,920 --> 00:09:19,200 Par extension, je vais réutiliser 164 00:09:19,520 --> 00:09:22,720 tous les comportements que j'ai définis dans la classe Collection 165 00:09:23,040 --> 00:09:26,400 et je pourrai spécialiser ces comportements dans chaque classe. 166 00:09:26,720 --> 00:09:31,200 Donc, l'héritage est ce mécanisme qui permet une définition incrémentale 167 00:09:31,520 --> 00:09:33,240 d'une abstraction par rapport à une autre. 168 00:09:33,560 --> 00:09:35,880 Et c'est très important dans la programmation objet. 169 00:09:36,200 --> 00:09:38,640 Dans le cadre de ce cours, je le traite après, 170 00:09:38,960 --> 00:09:42,440 mais je voulais dire que c'est vraiment un point essentiel. 171 00:09:42,760 --> 00:09:44,120 Finalement, qu'a-t-on vu ? 172 00:09:44,440 --> 00:09:47,960 On a vu que dans une conception objet, un programme, 173 00:09:48,280 --> 00:09:51,360 c'est des entités qui collaborent et envoient des messages. 174 00:09:51,680 --> 00:09:54,640 Que les objets, ces entités encapsulent les données 175 00:09:54,960 --> 00:09:59,440 et contrôlent l'interface qu'elles exposent à leurs clients. 176 00:09:59,760 --> 00:10:03,800 La liaison tardive permet de sélectionner la bonne méthode à exécuter 177 00:10:04,120 --> 00:10:07,920 et va éviter à un client de devoir faire des vérifications 178 00:10:08,240 --> 00:10:10,680 avant d'exécuter un message. 179 00:10:11,000 --> 00:10:16,480 Et ce mécanisme-là est renforcé si les objets qui offrent un même service 180 00:10:16,800 --> 00:10:19,320 le décrivent par des méthodes qui ont le même nom, 181 00:10:19,640 --> 00:10:22,760 ce qui va faire que le client va pouvoir simplement donner les ordres 182 00:10:23,080 --> 00:10:25,440 sans avoir à devoir choisir quel ordre il doit donner 183 00:10:25,760 --> 00:10:28,160 pour chaque objet avec lequel il interagit.