Coder en Smalltalk avec le Pingouin <author>Jason Steffler <!-- Compléter: Linux Gazette n°51 - Traducteur: Carine Bournez --> <!-- L'article sera coupé ici... --> <sect>Coder en Smalltalk avec le Pingouin <p>Par Jason Steffler <tt><url url="mailto:jagwar@magma.ca" name="jagwar@magma.ca"></tt> <!-- La traduction --> <sect1>Introduction <p> Depuis que VisualWorks Non Commercial (VWNC) a été distribué gratuitement pour Linux, l'intérêt de la communauté Linux pour Smalltalk va croissant. Le but de cet article est de fournir, aux fans de Linux qui n'y sont pas familiers, une introduction à Smalltalk et de partager quelques connaissances sur les caractéristiques de ce langage qui charme tant de programmeurs. Il existe déjà nombre de <ref id="tut-ref" name="tutoriels et de références">. Cet article ne se veut pas un tutoriel ou une référence à la programmation OO (<em/Orientée Objet/) ni à Smalltalk, mais seulement un petit aperçu pour aiguiser l'appétit. Cela ne suppose pas de connaissance préalable de l'OO, et l'article peut aussi bien être lu indépendamment qu'en codant. Beaucoup d'exemples cités sont valables pour toutes les implantations de Smalltalk. Bien que ces diverses mises en oeuvre partagent les mêmes caractéristiques de base, il existe des variations entre elles, plus particulièrement quand du code d'interface utilisateur entre en jeu. Il y a un bon nombre d'implantations de Smalltalk pour Linux disponibles librement<sup><ref id="fn1" name="1"></sup>~: <url url="http://www.qpsf.edu.au/software/GNU/smalltalk.html" name="GNU Smalltalk">, <url url="http://www.informatik.uni-stuttgart.de/stx/stx.html" name="Smalltalk/X">, <url url="http://minnow.cc.gatech.edu/squeak.1" name="Squeak"> et <url url="http://www.cincom.com/visualworks/downloads.html" name="VisualWorks Non Commercial"> <sup><ref id="fn2" name="2"></sup>. En particulier, Squeak a fait de très jolies choses récemment, mais ici les exemples sont écrits avec VWNC, parce que j'y suis plus habitué. De plus, et bien qu'il y ait une version plus récente disponible, je vais utiliser VWNC~v3.0, ceci dans un but d'illustration~: c'est en effet la version pour laquelle on trouve le plus d'outils/extensions disponibles librement. Cet article apporte quelques informations de base sur Smalltalk, la récupération et l'installation de VWNC3, les caractéristiques de Smalltalk (avec des exemples) et des références. Pour résumer les caractéristiques en question, Smalltalk~: <itemize> <item>est un environnement OO pur, encourageant la programmation OO, <item>peut sauvegarder l'état exact de l'environnement de développement (IDE), <item>est un langage qui s'écrit avec de vrais mots (<em/littéral/), <item>est compilé en pseudo-code et ce de manière incrémentale, <item>est un environnement portable~: une fois écrit, ça tourne partout (machine virtuelle/IHM), <item>peut inspecter et manipuler des objets en temps réel, <item>fournit un haut degré de réfléxivité (démarrage avec une application lancée, extensions), <item>possède un ramasse-miettes (<em/garbage collection/), pas de pointeurs explicites. </itemize> <sect1>Un peu de culture <p> <em>Petite anecdote Java/Smalltalk méconnue</em>~: l'équipe d'Oak du début voulait utiliser le Smalltalk VisualWorks dans son travail, mais a fini par inventer Java~; la licence de VisualWorks à cette époque s'étant révélée trop coûteuse pour eux<sup><ref id="fn3" name="3"></sup>. Smalltalk existe depuis un bon moment. Il a été créé au centre de recherche de Xerox de Palo Alto (PARC) au début des années 70, dans le but de fournir un environnement pour les enfants qui commencent à apprendre à programmer. Donc, sa syntaxe est très simple et l'environnement est arrivé à un haut niveau de maturité. La puissance de Smalltalk prend ses racines dans sa grande bibliothèque de <ref id="glossaire" name="classes">, qui peut être une arme à double tranchant. Il n'y a pas besoin de réinventer la roue pour faire le moindre travail, mais par contre, on peut passer beaucoup de temps au début de l'apprentissage à chercher la bonne roue à réutiliser<sup><ref id="fn4" name="4"></sup>. Une autre épée à double tranchant~: l'environnement purement OO, qui encourage donc les gens à passer au paradigme OO bien plus que tout autre langage basé sur des objets (OB)<sup><ref id="fn5" name="5"></sup> (je reviendrai sur ce sujet). Les gens qui font le pas tendent à s'attacher énormément à Smalltalk et trouvent cet environnement de travail très amusant, productif<sup><ref id="fn6" name="6"></sup> et théoriquement pur. Les gens qui ne font pas l'effort de franchir le pas ont tendance à l'éviter et restent vers des langages OB où il est plus facile de s'en sortir en faisant du code procédural déguisé en code OO. (Non Dorothy, ce n'est pas parce que tu utilises un compilateur C++ que tu écris du code OO). Bien que de nombreuses personnes décrivent Smalltalk comme utile seulement dans les grands <ref id="glossaire" name="marchés verticaux">, il est extrêmement flexible puisqu'aussi utilisé dans de très petits <ref id="glossaire" name="marchés horizontaux">. Il a été utilisé pour écrire des applications<sup><ref id="fn7" name="7"></sup> pour les systèmes de gestion de grands réseaux, les systèmes cliniques d'hôpitaux, les palm~pilots, les micro-contrôleurs, les logiciels de gestion de matériel. Mais finissons-en avec les informations culturelles, passons aux exemples réels. <sect1>Installation <p> VWNC3 peut être obtenu sur un <url url="http://www.cincom.com/visualworks/vwv3beta-form.html" name="site de téléchargement gratuit">. Vous devez donner vos nom, adresse, ville, état, code postal et e-mail pour continuer. Ensuite, lorsque vous cliquez sur le bouton <bf/J'accepte/ (N.~d.~t.~: <em/I~Accept/ sur le site), le téléchargement des 20,954~kilo-octets du fichier <tt/vw.exe/ commence immédiatement. Ce n'est pas le mécanisme de téléchargement le plus sympathique au monde, en particulier le fait que les versions Windoze et Linux soient toutes deux dans une archive auto-extractible sous Windoze, mais ça marche. Téléchargez le fichier où vous voulez que le répertoire parent se trouve, puis dézippez en tapant <tt/unzip vw.exe/. Le fichier zip se décompressera dans Vwnc3. Pour ma part, j'ai un double boot, donc j'ai téléchargé dans mon répertoire <tt>/dos</tt> et l'ai dézippé là, pour pouvoir l'utiliser aussi depuis Windoze, ce qui me donne un répertoire de base <tt>/dos/vwnc3/</tt>. (Sinon, vous pouvez spécifier une variable d'environnement <tt/VISUALWORKS/ avec le chemin d'accès). Pour le démarrer, il est possible de copier la machine virtuelle dans le répertoire <tt/image/, ou faire un lien symbolique. Comme je l'ai mis dans ma partition dos, je vais faire une copie~: <tscreen><verb> cp /dos/vwnc3/bin/linux86/visualnc /dos/vwnc3/image/visualnc </verb></tscreen> J'ai remarqué que la machine virtuelle n'était pas exécutable par défaut, donc corrigeons cela~: <tscreen><verb> chmod 555 visualnc </verb></tscreen> Ensuite, pour démarrer l'image, il faut la passer en argument à la machine virtuelle~: <tscreen><verb> cd /dos/vwnc3/image visualnc visualnc.im </verb></tscreen> Un écran de rappel de licence apparaît à chaque fois qu'on lance VWNC, cliquez <bf/J'accepte/ (<em/I~Accept/) pour continuer. La fenêtre qui apparaît en haut est appelée <ref id="glossaire" name="Transcript"> (<em/Transcription/), et la fenêtre d'en bas est le <ref id="glossaire" name="Workspace"> (<em/Espace~de~Travail/). Ensuite, il faut indiquer à l'image où se trouvent les fichiers système dont elle a besoin. Pour cela, cliquez sur <bf/File>Set~VisualWorks~Home/ dans la fenêtre Transcript. Dans le dialogue qui s'affiche, saisissez le nom du répertoire parent~: <tt>/dos/vwnc3/</tt>. Les fenêtres Transcript et Workspace ressemblent à~: <!-- img src="gx/steffler/transcript01.jpg" height=158 width=421--> <url url="gx/steffler/transcript01.jpg" name="Fig. 1 - fenêtre VWNC Transcript"> <!-- img src="gx/steffler/workspace01.jpg" height=308 width=423--> <url url="gx/steffler/workspace01.jpg" name="Fig. 2 - fenêtre VWNC Workspace par défaut"> <!-- ndt: je suppose qu'il y a erreur, c'est bien Workspace et non Transcript comme indiqué dans l'original --> L'espace de travail du début contient quelques informations qui valent la peine d'être lues, mais cette lecture n'est pas nécessaire pour continuer à suivre cet article. <em>Note à propos des souris~:</em> Smalltalk suppose que vous ayiez une souris à 3 boutons. Si ce n'est pas le cas, vous pouvez simuler un troisième bouton sur une souris à deux boutons en cliquant les deux boutons en même temps (N.~d.~t.~: encore faut-il avoir activer cette possibilité dans la configuration de son serveur X). <sect1>Quelques caractéristiques notables de Smalltalk <p> <sect2>Sauvegarder votre travail <p> Là encore se trouve une épée à double tranchant~: ce qui est fantastique, c'est de pouvoir sauvegarder votre IDE, <em/tout/ est sauvegardé <em/exactement/ dans l'état où vous l'avez laissé. Les fenêtres ouvertes, à l'endroit où elles se trouvaient, ce qui était en surbrillance, les <ref id="glossaire" name="objets"> qui existaient, tout. Une photo est prise et sauvegardée sous la forme d'une image (N.~d.~t.~: une image Smalltalk bien sûr, pas de celles que l'on regarde~!). Il n'est pas nécessaire de recharger un fichier texte dans un éditeur de texte et de retrouver l'endroit où vous vous étiez arrêté. Le revers de la médaille c'est que si vous avez une liaison de base de données corrompue ou que vous avez écrasé des objets qui ne devaient pas l'être, c'est sauvegardé dans l'image. Donc, il est nécessaire de connaître l'état de votre environnement au moment de la sauvegarde. Ceci étant dit, vous pouvez enregistrer votre code séparément de l'image et le recharger dans une image propre si vous rencontrez des problèmes (une bonne idée, en fait). Une manière simple de sauvegarder le code est d'utiliser un fichier de sortie. Essayons une sauvegarde (qui par la même occasion sauvegardera la localisation du fichier système que vous venez de spécifier). Déplacez les fenêtres comme vous le voulez, puis sauvegardez votre image, sélectionnez <bf/File>Save~As.../ Il est préférable de sauver l'image sous un nom différent de l'image vierge, pour pouvoir revenir à l'image propre et recharger le code en cas de problèmes. Je vais sauver l'image sous le nom <em/TestImage/. Après la sauvegarde, essayez de fermer l'image <bf/File>Exit~VisualWorks...>Exit/. Ensuite, pour redémarrer, prenez garde à passer la nouvelle image à la machine virtuelle. Notez que, lorsque vous sauvez votre image, la date et l'heure sont affichées sur la fenêtre Transcript, comme ci-dessous~: <!-- img src="gx/steffler/transcript02.jpg" height=158 width=421 --> <url url="gx/steffler/transcript02.jpg" name="Fig. 3 - Fenêtre Transcript après la sauvegarde de 'TestImage'"> Je pourrais encore dire des tas d'autres choses sur la sauvegarde (Perm~Save~As, Filing~out, Change~log, Envy), mais pour ne pas trop rallonger, je vais couper court et changer de sujet. <sect2>Tout est objet <p> C'était mon mantra pendant les 6 premiers mois où j'ai appris Smalltalk. Comme la plupart des programmeurs à ce moment-là, j'avais une culture de programmation procédurale et il était très difficile de chambouler cet esprit. C'est là qu'entre en jeu l'infâme paradigme. La fenêtre Transcript est un objet, les menus de cette fenêtre sont des objets, les boutons sont des objets, la fenêtre Workspace est un objet,~etc. Mais avant d'entrer dans le détail, commençons par le vénérable exemple «~Hello~World~»~: <em/Exemple~1~: Hello World/ <itemize> <item>Ouvrez un nouvel espace de travail (en cliquant sur <bf/Tools>Workspace/) <item>Dans la fenêtre Workspace, tapez~: <tt/Transcript cr. Transcript show: 'Hello World.'/ <item>Bravo, vous venez d'écrire votre premier code Smalltalk. Voyons maintenant comme il marche bien~: <item>Mettez cette ligne de code en surbrillance, cliquez avec le bouton du milieu et sélectionnez <bf/do~it/ (ceci évalue le code Smalltalk que vous venez d'écrire) <item>Vous devriez voir le texte 'Hello~World' dans la fenêtre Transcript~: <!-- img src="gx/steffler/transcript03.jpg" height=158 width=421 --> <url url="gx/steffler/transcript03.jpg" name="Fig. 4 - L'exemple Hello World"> <item>Analysons le code Smalltalk~: <table> <tabular ca="ll|ll"> Transcript cr. | Ce code permet de manipuler l'objet Transcript et lui demande d'afficher un retour chariot sur lui-même. @ Transcript show: 'Hello World' | Manipule l'objet Transcript et lui demande d'écrire 'Hello~World' sur lui-même. </tabular> </table> <item>Vous pouvez aussi afficher 'Hello~World' sur la ligne de commande, ouvrir une fenêtre et écrire 'Hello~World' dedans, ou encore concevoir une interface utilisateur et placer 'Hello~World' dessus. Mais là encore, nous n'allons pas nous attarder. <item><tt/cr/, tout comme <tt/show:/, est un message envoyé à l'objet Transcript. Ce sont seulement des messages auxquels Transcript sait comment répondre. Ils ne font pas partie de la syntaxe de Smalltalk. <item>Ce dernier point est important à retenir pour les programmeurs en non-OO, <it/on envoie des messages aux objets pour leur demander de faire quelquechose/. </itemize> Notez que vous venez d'exécutez votre premier code Smalltalk <it/sans le compiler/. Vous n'avez pas sauvegardé votre code, ni compilé, ni édité les liens avant de le lancer. «~Ben alors, c'est un langage interprété~», dites-vous. Eh bien non, pas vraiment. Pour être précis, c'est un langage compilé incrémentalement en pseudo-code. Je vais y revenir <ref id="compilIncrementalePseudocode" name="dans un moment">. Pour l'instant, retenez juste que vous codez et exécutez du Smalltalk sans peine. Maintenant, passons à l'exemple suivant~: <em/Exemple~2~: Affichage de la date/ <itemize> <item>Dans votre espace de travail, tapez~: <tt/Date today/ <item>Mettez cette ligne de code en surbrillance, cliquez avec le bouton du milieu et sélectionnez <bf/print~it/ (ceci évalue le code Smalltalk que vous venez d'écrire et affiche le résultat). <item>Vous devriez voir affichée la date courante, comme~: <!-- img src="gx/steffler/workspace02.jpg" height=180 width=346 --> <url url="gx/steffler/workspace02.jpg" name="Fig. 5 - Affichage de la date du jour"> <table> <tabular ca="ll|ll"> Date today | Demande à la classe Date quel jour nous sommes. </tabular> </table> <item>Ok, voyons un peu plus en détails ce que <tt/Date today/ évalue. Mettez en surbrillance cette ligne de code (sans la date qui a été affichée), cliquez avec le bouton du milieu et sélectionnez <bf/inspect~it/. Vous devriez voir~: <!-- img src="gx/steffler/aDate01.jpg" height=116 width=264 --> <url url="gx/steffler/aDate01.jpg" name="Fig. 6 - Un Inspector sur une date"> <item>C'est ce qu'on appelle un <ref id="glossaire" name="inspecteur"> (<em/Inspector/), qui d'ailleurs, est également un objet. Les objets Inspector permettent de jeter un oeil aux objets. Si vous cliquez sur <bf/self/ dans l'Inspector, vous aurez une représentation textuelle de la date~: <!-- img src="gx/steffler/aDate02.jpg" height=116 width=264 --> <url url="gx/steffler/aDate02.jpg" name="Fig. 7 - Inspector affichant une représentation textuelle de la date"> <item>Ça vous dit quelquechose~? C'est parce que dans la Fig.~5, lorsque vous avez fait afficher <tt/Date today/, vous avez en fait affiché une représentation textuelle de l'objet Date. Si vous cliquez sur l'un des deux autres attributs de cette date, vous verrez que <bf/day/ stocke le numéro du jour dans l'année (1->365, normalement), et <bf/year/ stocke l'année concernée. <item>Tous les objets ont une représentation sous forme de texte, même si ce n'est que son type (bien que cela ne soit pas très utile). <item>L'inspecteur est un concept très puissant. Vous avez juste demandé à Date la date courante, et vous avez manipulé un objet date. Non seulement vous pouvez regarder cet objet, mais vous pouvez aussi travailler avec et le modifier. Par exemple, cliquez sur <bf/day/, et saisissez n+1 à la place de la valeur actuelle. Dans la Fig.~7, le 6 février est le <f>37<sup/e/</f> jour de l'année, donc je saisis 38. Puis cliquez avec le bouton du milieu et choisissez <bf/accept/. Vous remarquerez qu'aucun changement ne semble avoir eu lieu, mais ce que vous avez accompli va faire que l'objet représentera maintenant la date du <f>n+1<sup/e/</f> jour de l'année. Maintenant, si vous cliquez sur <bf/self/ de la date, vous verrez que la date affichée est celle du lendemain~: <!-- img src="gx/steffler/aDate03.jpg" height=116 width=264 --> <url url="gx/steffler/aDate03.jpg" name="Fig. 8 - Inspector affichant la date du lendemain"> </itemize> Finalement, non seulement on peut coder et exécuter immédiatement, mais en plus on peut attraper des objets et les manipuler directement avec effet instantané. Ces deux possibilités sont une partie de ce qui fait de Smalltalk un environnement productif. On peut coder&tester en temps réel. Si on ne comprend pas ce qui se passe, on peut attraper l'objet pour regarder son état et le manipuler pour voir comment il se comporte. Après une compilation du projet, s'il y a un bug lors des tests, on peut coder rapidement un correctif et le charger dans l'environnement de test --~pas besoin de recompiler. Autre chose à noter~: la <ref id="glossaire" name="littéralité de Smalltalk">. Pour avoir la date du jour, nous avons juste demandé à <tt/Date/ de donner <tt/today/. Bien que Smalltalk soit un langage très littéral, il y a évidemment des limites quelquepart, par exemple on ne peut pas demander à <tt/Date/ d'avoir <tt/tomorrow/. Ceci étant dit, la syntaxe générale de Smalltalk est très simple et facile à lire. Gardez ceci à l'esprit pendant la lecture des prochains exemples de code. Continuons donc avec le <f>3<sup/e/</f> exemple de cette section, qui évoque le changement d'état d'esprit nécessaire pour aborder l'OO~: <em/Exemple~3~: Illustration du paradigme du changement/ <itemize> <item>Dans votre espace de travail, tapez~: <tt/1 + 2 * 3/ <item>Maintenant, avant d'évaluer ce code, pensez à ce que sera la réponse. Vous pensez probablement à 7. Bien, mettez le code en surbrillance et faites <tt/print it/. <item>Vous remarquerez que la réponse est 9~: <!-- img src="gx/steffler/workspace03.jpg" height=180 width=346 --> <url url="gx/steffler/workspace03.jpg" name="Fig. 9 - Résultat du passage de message"> <item>C'est amusant, combien de programmeurs non-OO partent en sanglotant quand je leur montre cela. «~Quoi~! pas de priorité d'opérateurs, quel langage débile~! Je vais me cantonner au C++ parce que je peux le comprendre~!~» Sérieusement, ça m'est arrivé plein de fois. <item>Cependant, la réalité dépend de vos oeillères~; quand j'ai écrit la réponse 7 tout à l'heure, j'avais le 9 en tête parce que je pensais en 00 et pas d'une manière procédurale. <item>La raison est (répétez après moi)~: <it/tout est objet/. Dans cet exemple, les chiffres 1, 2 et 3 sont tous des objets. Les opérateurs~: <tt/+/ et <tt/*/ sont justes des <it/messages/ qui sont envoyés aux objets. Le raisonnement est donc que si <tt/+/ et <tt/*/ sont des messages, pourquoi auraient-ils une priorité par rapport aux autres messages~? Tous les messages du même type sont traités de la même manière par Smalltalk. <item>Pour voir par vous-même, mettez <tt/1/ en surbrillance, cliquez le bouton du milieu et choisissez <tt/inspect/. Vous obtiendrez un inspecteur sur SmallInteger, qui est le type d'objet qu'est 1. <!-- img src="gx/steffler/aSmallInt01.jpg" height=120 width=231 --> <url url="gx/steffler/aSmallInt01.jpg" name="Fig. 10 - Inspection de l'objet 1"> <item>Donc, le code est évalué de cette manière~: <itemize> <item>(le nombre 1) reçoit la demande de (+) avec (le nombre 2) <item>(le nombre 1) l'exécute, renvoie l'objet~: (le nombre 3) <item>(le nombre 3) reçoit la demande de (*) avec (le nombre 3) <item>(le nombre 3) l'exécute et renvoie l'objet~: (le nombre 9) </itemize> <item>Pour évaluer le code comme on l'entendrait dans l'esprit procédural, on peut utiliser des parenthèses~: <tt/1+(2*3)/ <item>«~OK, pourquoi ne peut-on pas mettre la date affichée, <bf/February 6, 2000/, en surbrillance et l'inspecter pour voir l'objet date~?~» Bonne question. Une réponse simple est que certains types d'objets peuvent être créés (instanciés) juste en inspectant une répresentation textuelle de ces objets, d'autres types d'objets ne le peuvent pas. Les entiers (Integers) font partie de ceux que l'on peut instancier en inspectant une représentation textuelle. </itemize> <sect1>Compilation incrémentale en pseudo-code <label id="compilIncrementalePseudocode"> <p> Comme je l'ai déjà mentionné, Smalltalk est compilé en pseudo-codes, de manière incrémentale. Certaines personnes le décrivent comme un croisement entre langages compilés et langages interprétés. Voici ce qui se passe quand on fait ou que l'on affiche quelquechose~: <enum> <item>le compilateur Smalltalk traduit le code Smalltalk en pseudo-codes, <item>les pseudo-codes sont passés à la machine virtuelle pour l'exécution et <item>les pseudo-codes sont exécutés et le résultat est renvoyé. </enum> Bon, ça semble plutôt interprêté, non~? Mais ce que nous avons fait jusqu'ici n'est pas de la programmation normale en Smalltalk. Rappelez-vous que les espaces de travail ne sont que des bacs à sable temporaires. Normalement, lorsque vous programmez, vous validez du code Smalltalk (sauvegarde dans l'image) et le code <it/reste compilé en pseudo-code/. Normalement, lorsque vous programmez, vous validez le code en <ref id="glossaire" name="méthodes"> pour une classe puis~: <enum> <item>le compilateur Smalltalk traduit le code Smalltalk en pseudo-codes, <item>les pseudo-codes sont sauvés avec cette classe, <item>quand un message est envoyé à une classe, les pseudo-codes appropriés pour la méthode est envoyé à la machine virtuelle pour exécution et <item>les pseudo-codes sont exécutés et le résultat est renvoyé. </enum> Le résultat net est qu'à chaque fois que vous faites un changement dans vos classes, ce petit changement est sémantiquement vérifié, compilé et prend effet immédiatement. C'est assez sympathique de faire un petit changement et de le voir immédiatement répercuté sur le comportement du programme. Java est similaire en ce qu'il est compilé en pseudo-code, mais différent en ce qu'il n'est pas <it/incrémentalement/ compilé. Donc en programmation Java, il faut tout recompiler (ou en partie si l'on utilise make) et refaire les liens, à chaque fois que l'on veut prendre en compte une modification. <sect1>Machine Virtuelle et Portabilité <p> La machine virtuelle est bien ce que cela veut dire --~un ordinateur virtuel qui sait comment exécuter du pseudo-code Smalltalk. Elle est généralement implémentée en C (Squeak est une exception notable à cela, la machine virtuelle est elle-même écrite en Smalltalk puis exportée en C par programme). C'est la machine virtuelle qui permet une telle portabilité entre les différents types de machines. Smalltalk a suivi le paradigme «~une fois écrit, ça marche partout~» depuis des <it/décennies/~! Pour vous donner un aperçu de ceci, sélectionnez <bf/File>Settings/. Dans le dialogue qui apparaît, choisissez le <bf/Look~Selection/ de <bf/Macintosh/, puis validez. <!-- img src="gx/steffler/settings01.jpg" height=365 width=439 --> <url url="gx/steffler/settings01.jpg" name="Fig. 11 - Sélection de l'apparence Mac"> Maintenant vous remarquerez que votre système en entier fonctionne avec l'allure du Mac. La première fois que j'ai vu cela en 95, j'en ai été soufflé. Je venais de passer un an sur un pénible portage de OpenWindows à Motif pour des parties d'applications en C. Puis quelqu'un me montre comment on peut <em/porter/ son application de SunOS à Solaris et à MacOS en un clic~! <!--img src="gx/steffler/transcript04.jpg" height=158 width=421 --> <url url="gx/steffler/transcript04.jpg" name="Fig. 12 - Fenêtre Transcript avec l'apparence Mac"> Gardez à l'esprit que la fenêtre ci-dessus tourne sur une machine Linux~! J'utilise fréquemment cette fonctionnalité au bureau lorsqu'on développe pour WIndoze, parce que je préfère l'apparence de Motif. <sect1>Réflexivité <p> C'est en cela que je considère Smalltalk réellement puissant~: sa <ref id="glossaire" name="réflexivité">. 98% de Smalltalk est écrit en Smalltalk, ce qui rend l'environnement facile à personnaliser, étendre, ou perfectionner (Squeak est l'exception, puisqu'écrit en Smalltalk à 100%). Alors il est facile de voir comment Smalltalk est écrit et de l'adapter à vos besoins. En fait, c'est la base du développement en Smalltalk. Vous <it/commencez avec une application qui tourne/, vous ajoutez des extensions spécifiques à votre affaire, ôtez les parties qui ne vous servent pas, et livrez l'application. Voici un exemple simple montrant comment étendre Smalltalk~: <em/Exemple~4~: Ajout de menus inspecter à toutes les fenêtres/ <itemize> <item>Vous vous rappelez quand j'ai dit que Transcript et Workspace sont des objets~? Vous devriez donc pouvoir les inspecter n'est-ce pas~? Ok, cependant ce n'est pas si simple, dans l'environnement tel qu'il est par défaut, de prendre n'importe quelle fenêtre pour l'inspecter. Nous allons ajouter une extension simple pour permettre ceci. <item>Ouvrez un navigateur de classe <bf/Browse>All~Classes/ <item>Vous avez maintenant sous les yeux un navigateur de classes, ou navigateur système. <!-- img src="gx/steffler/classBrowser01.jpg" height=352 width=644 --> <url url="gx/steffler/classBrowser01.jpg" name="Fig. 13 - Navigateur de classes vide"> <item>En observant les colonnes de gauche à droite et de haut en bas, vous voyez~: les <ref id="glossaire" name="catégories">, les <ref id="glossaire" name="classes">, les <ref id="glossaire" name="protocoles">, les <ref id="glossaire" name="méthodes">, et le code de méthodes. De plus, vous verrez deux radio-boutons~: le premier fait naviguer du côté instance, l'autre du côté classe. (Nous allons faire une méthode d'instance et une méthode de classe). <item>Cliquez avec le bouton du milieu sur la colonne catégorie et sélectionnez <bf/Find~Class.../, puis entrez <bf/StandardSystemController/ dans le dialogue qui s'affiche <item>Après que le navigateur ait mis la classe <bf/StandardSystemController/ en surbrillance, cliquez sur le protocole <bf/menu~messages/ dans la colonne protocole, et sur la méthode <bf/back/ dans la colonne méthode. Vous devriez voir~: <!-- img src="gx/steffler/classBrowser03.jpg" height=352 width=644 --> <url url="gx/steffler/classBrowser03.jpg" name="Fig. 14 - Navigateur de classes avec une méthode sélectionnée"> <item>Résumons~: Les catégories sont des groupes de classes. La catégorie <bf/Interface-Framework/ est sélectionnée. La classe <bf/StandardSystemController/ est aussi sélectionnée. Les protocoles sont des groupes de méthodes. Nous sommes donc actuellement dans le groupe <bf/menu~messages/. Les méthodes contiennent le code implanté. Nous avons sélectionné la méthode <bf/back/. <item>Nous allons ajouter une méthode dans le protocole <bf/menu~messages/. Pour ceci, mettez en surbrillance tout le contenu de la méthode courante et effacez-le. Ne vous inquiétez pas, la méthode n'a pas disparu et ne sera pas effacée pour autant. C'est juste une façon simple de créer une nouvelle méthode dans le protocole actuellement sélectionné. <item>Tapez alors le code~: <tscreen><verb> inspectView self view model inspect. </verb></tscreen> <item>puis, pour sauver la méthode, cliquez avec le bouton du milieu et choisissez <bf/accept/. <item>Vous verrez que la méthode que vous venez de créer apparaît maintenant dans le navigateur. Elle a déjà été compilée et est prête à être exécutée. Vous devriez voir~: <!-- img src="gx/steffler/classBrowser04.jpg" height=352 width=644 --> <url url="gx/steffler/classBrowser04.jpg" name="Fig. 15 - Méthode inspectView ajoutée"> <item>Ensuite, nous devons ajouter une méthode du côté classe. Cliquez sur le radio-bouton <bf/class/ dans le navigateur de classes <item>puis cliquez sur le protocole <bf/class~initialization/ et la méthode <bf/flushMenus/. <item>Comme précédemment, effacez le texte pour la méthode (la méthode <bf/flushMenus/ ne sera pas détruite) et tapez~: <tscreen><verb> initializeForAdditions "initialize the menu." "self initializeForAdditions" ScheduledBlueButtonMenu := Menu labels: relabel as...\refresh\move\resize\front\back\collapse\close\inspect'with CRs lines: #(1 7 8) values: #( #newLabel #display #move #resize #front #collapse #close #inspectView). </verb></tscreen> <item>Après avoir saisi ceci, cliquez avec le bouton du milieu et choisissez <bf/accept/ pour la méthode. Vous devriez alors voir~: <!--img src="gx/steffler/classBrowser04.jpg" height=352 width=644 --> <url url="gx/steffler/classBrowser04.jpg" name="Fig. 16 - Méthode initializeForAdditions ajoutée"> <item>OK, voici maintenant la partie bien pensée. Cliquez avec le bouton droit sur la colonne méthode, vous devriez voir le menu de la fenêtre~: <!-- img src="gx/steffler/classBrowserWindowMenu01.jpg" height=192 width=101 --> <url url="gx/steffler/classBrowserWindowMenu01.jpg" name="WindowMenu"> <item>À ce moment-là, le code a été compilé en pseudo-code. Mais comme c'est du code d'initialisation, il n'a pas encore été exécuté. On peut l'exécuter directement depuis le navigateur~; placez le texte <bf/self~initializeForAdditions/ en surbrillance, cliquez avec le bouton du milieu et <bf/do~it/. <item>Puisque le code a été exécuté, vous devriez voir <bf/inspect/ ajouté en bas du menu de fenêtre~: <!-- img src="gx/steffler/classBrowserWindowMenu02.jpg" height=217 width=101 --> <url url="gx/steffler/classBrowserWindowMenu02.jpg" name="WindowMenu modifié"> <item>Maintenant nous pouvons inspecter n'importe quelle fenêtre pour laquelle ce menu est défini. Essayez d'inspecter ce navigateur de classe que nous étions en train d'utiliser. Cliquez avec le bouton droit et choisissez <bf/inspect/. Vous verrez un inspecteur sur le navigateur de classe. Si vous sélectionnez l'attribut <bf/className/, vous verrez que le nom de classe correspond à la classe sélectionnée à cet instant~: <!-- img src="gx/steffler/aClassBrowser01.jpg" height=282 width=324 --> <url url="gx/steffler/aClassBrowser01.jpg" name="Sélection de classe"> </itemize> Remarque~: nous avons juste fait une extension de l'image de base. C'est un changement de manière de coder qui devrait être suivi avec précautions. <sect1>Ramasse-Miettes <p> <!-- Yea, though I walk through the valley of doomed schedules, I shall fear no deallocating... --> Quand je marche dans la vallée des délais désespérés, je ne crains aucune libération car Smalltalk est avec moi. <!-- ndt : Psaumes 23, 4 - moi et la bible ça fait plus que 2, merci Olivier pour la référence et merci google pour la recherche --> Ramasse-Miettes~: alias Victor, Nettoyeur. Smalltalk possède un ramasse-miettes, ce qui veut dire que les objets qui ne sont plus référencés sont nettoyés pour libérer la mémoire. Je me souviens de m'être arraché les cheveux plus d'une fois en programmant en C++, à chercher des fuites de mémoire. Ceci parce qu'en C++ c'est au développeur de s'occuper de la mémoire. Si vous ne libérez pas la mémoire utilisée, votre application continuera sans fin à prendre de plus en plus de mémoire jusqu'à ce que la machine n'en ait plus et plante. En parlant de plantages de machine, vous remarquerez que nous n'avons jamais manipulé de pointeurs. C'est parce que Smalltalk n'a pas de pointeurs. (Bon, techniquement ce n'est pas correct. Chaque référence de variable est en fait un pointeur sur un objet, mais en Smalltalk le développeur est libéré du poids de la maintenance manuelle des pointeurs). <sect1>Résumé <p> J'espère avoir été capable de faire un tour concis et informatif de Smalltalk, abordable pour des programmeurs non OO. J'ai montré que Smalltalk~: <itemize> <item>est un environnement OO pur, encourageant la programmation OO, <item>peut sauvegarder l'état exact de l'environnement de développement (IDE), <item>est un langage littéral, <item>est compilé en pseudo-code incrémentalement, <item>est un environnement portable~: une fois écrit, ça tourne partout (machine virtuelle/IHM), <item>peut inspecter et manipuler des objets en temps réel, <item>fournit un haut degré de réfléxivité (démarrage avec une application lancée, extensions), <item>possède un ramasse-miettes, pas de pointeurs explicites. </itemize> Il y a bien d'autres choses que j'aurais voulu aborder dans cet article, mais les contraintes de longueur ne me le permettent pas~: <itemize> <item>l'aide en ligne, <item>le débogueur, <item>les nombres (essayez d'imprimer <tt/1000000 factorial/ --~<em/factorielle~100000/~-- dans un espace de travail. Si vous avez le temps d'attendre la fin du calcul, puisque la taille de nombres est limitée uniquement par la quantité de mémoire), ou essayez d'inspecter <tt>12/7</tt>), <item>les paquets --~un mécanisme de partage de code, <item>le navigateur de réimplantations (Refactoring Browser) --~Mon outil de programmation préféré, <item>HotDraw --~une structure de travail réutilisable pour le dessin, <item>le test de structures --~automatiser le test, <item>le changement dynamique d'éléments de fenêtres pendant le fonctionnement. </itemize> <sect1>Glossaire<label id="glossaire"> <p> <table> <tabular ca="ll|ll"> Catégorie | Un groupe de classes. @ Classe | Un type d'objet. @ Marché horizontal | Un marché qui a tendance à avoir un public large avec un faible impact dessus. Un logiciel prêt-à-cuire s'adresse à un marché horizontal. Par exemple, une suite bureautique~: si ça plante, repartez sur votre dernière sauvegarde. @ Inspecteur | Un type d'interface graphique pour un objet, permettant d'observer et de manipuler les objets. @ Littéralité | Une définition simple de la littéralité est le degré de lisibilité/simplicité du langage. La programmation littérale est une programmation "pour-le-développeur-qui-passe-après-vous". @ Méthode | Un morceau de code Smalltalk pour un objet. @ Objet | Un groupe de données et d'opérations en relation. Son comportement est représenté par ses opérations sur ses données. @ Protocole | Un groupe de méthodes. @ Réflexivité | Manipulation d'un environnement dans lui-même. Dans Smalltalk, 98% étant écrit en Smalltalk, il est facile de personnaliser, étendre et adapter l'environnement. (Squeak est une exception, car écrit à 100% en Smalltalk). @ Transcript | La fenêtre principale de l'IDE, d'où les autres fenêtres (navigateurs, workspaces,~etc.) sont lancées. Conserve aussi une liste active des messages système. @ Workspace | Un bloc-notes où les développeurs peuvent faire des essais avec du code. @ Marché vertical | Un marché qui a tendance à avoir un public restreint avec un très fort impact dessus. Par exemple, un système de gestion de réseau pour une société de télécommunications~: si ça plante, la société perd un million de dollars chaque minute. </tabular> </table> <sect1>Autres Références<label id="tut-ref"> <p> <enum> <item> Une <url url="http://max.cs.kzoo.edu/~eatkins/smtlk/smhist.html" name="histoire de Smalltalk"> <item> Une <url url="http://www.qks.com/Information_Desk/history.asp" name="courte histoire de Smalltalk"> <item> <url url="http://www.goodstart.com" name="GoodStart"> <item> WikiWikis~: <enum> <item><url url="http://www.iam.unibe.ch/~scg/cgi-bin/Smalltalk.cgi" name="Smalltalk"> <item><url url="http://minnow.cc.gatech.edu/squeak.1" name="Squeak"> <item><url url="http://wiki.cs.uiuc.edu/VisualWorks/" name="VisualWorks"> </enum> <item> Groupe de discussion~: comp.lang.smalltalk <item> Archives Smalltalk libres~: <enum> <item><url url="http://st-www.cs.uiuc.edu/" name="Smalltalk">(UIUC --~le papy des archives Smalltalk) <item><url url="http://www.squeak.org/" name="Squeak"> <item><url url="http://www.listserv.gmd.de/archives/vswe-l.html" name="VSE"> (en Allemand) </enum> <item> Tutoriels~: <enum> <item><url url="http://www.squeak.org/#tutorials" name="Squeak"> <item><url url="http://cyclone.cs.clemson.edu/~lab428/VW/VWTableOfContents.html" name="VisualWorks"> </enum> <item> <url url="http://www.panasoft.com/stlinks/" name="Plein de liens sur Smalltalk"> <item> <url url="http://www.dnsmith.com/SmallFAQ/" name="La Smalltalk FAQ de Dave"> (il y a beaucoup de trucs ici et même si c'est un peu dépassé, c'est AMHA la meilleure. Dave, ce serait génial si jamais tu trouvais le temps de finir ça). <item> <url url="http://www.extremeprogramming.org/" name="eXtreme Programming"> (qui est à l'origine un projet Smalltalk) </enum> <sect2>Notes de bas de page <p> <enum> <item><label id="fn1">Chaque implantation a ses propres restrictions de licence. À ma connaissance, seul GNU Smalltalk et Squeak ont une licence de type GNU copyleft.<p> <item><label id="fn2">Ces deux dernières implantations sont les plus récentes.<p> <item><label id="fn3">Dans <url url="http://x37.deja.com/getdoc.xp?AN=564595555&CONTEXT=949863157.89849870&hitnum=0" name="l'article"> <tt>http://x37.deja.com/getdoc.xp?AN=564595555&CONTEXT=949863157.89849870&hitnum=0</tt> <tscreen> Author:<newline> Eric Clayberg<newline> <clayberg@instantiations.com><newline> <newline> Patrick Logan <patrick@c837917-a.potlnd1.or.home.com><newline> wrote in message<newline> news:hTN84.453$HT1.6388@news.rdc1.wa.home.com...<newline> ><newline> > I wish the original Oak team had chosen to adopt Smalltalk<newline> > rather than invent Java<newline> <newline> They tried to, but ParcPlace wanted too much on a per-copy royalty basis...sigh<newline> <newline> <em> > J'espérais que l'équipe originale de Oak ait choisie de garder Smalltalk<newline> > plutôt que d'inventer Java.<newline> <newline> Ils ont essayé, mais ParcPlace voulait trop de royalties pour chaque copie...sniff. </em> </tscreen> <p> <item><label id="fn4">Bah~! Les vrais programmeurs réinventent toujours la roue, ça fait pousser le poil aux pattes~!... héhé, je suis tombé dans le panneau trop souvent toutes ces années. Le plus souvent, les roues réinventées ont tendance à être carrées. C'est trop moche que les écoles encouragent cette mentalité pendant l'apprentissage théorique. (fin de digression).<p> <item><label id="fn5">C'est une terminologie vague qui diffère selon les gens avec qui l'on parle. Dans mon idée, un langage basé sur des objets (OB) est un langage non-OO qui a évolué vers l'orienté-objets (C++, OO-COBOL,~etc.). Certaines personnes les appellent langages OO bâtards.<p> <item><label id="fn6">Quelques numéros sur la productivité de <url url="http://www.spr.com/library/0langtbl.htm#Smalltalk" name="Software Productivity Research"> (Un échantillon du rapport moyen instructions/fonctions du source~:~Smalltalk~:~21, C~:~128, C++~:~53, Visual Basic 5~:~29).<p> <item><label id="fn7"><url url="http://www.goodstart.com/whoswho.html" name="GoodStart - who's using Smalltalk"> --~http://www.goodstart.com/whoswho.html </enum> <p>Copyright 2000, Jason Steffler. Paru dans le numéro 51 de la Linux Gazette de Mars 2000. <p>Traduction française de Carine Bournez. </sect> </article>