Goto (informatique)
L’instruction goto
(littéralement va à) est une instruction présente dans de nombreux langages de programmation. Elle est utilisée pour réaliser des sauts inconditionnels dans un programme, changeant ainsi le flot de contrôle naturel du programme qui consiste à aller exécuter l'instruction suivante. L’exécution est alors envoyée à une autre instruction repérée par une étiquette ou label, qui est soit un numéro de ligne, soit une étiquette déclarée, selon le langage.
Pour les articles homonymes, voir Goto.
L’instruction goto
, directement héritée des instructions de saut des langages machines, était nécessaire dans les langages primitifs (Fortran pré-90, BASIC) comme instruction de base permettant de réaliser des boucles et autres structures de contrôles.
Depuis la révolution de la programmation structurée des années 1970, l’instruction goto
n’est plus guère appréciée des programmeurs modernes, car elle rend souvent les programmes plus difficiles à comprendre et à maintenir (on parle dans ce cas de programmation spaghetti). On utilise plus généralement des structures comme les conditionnelles (if .. then .. else ..) ou les boucles (for, while, etc.) qui font partie intégrante de tous les langages de programmation impératifs modernes.
Dans certains langages, d’autres instructions effectuent des sauts inconditionnels et remplacent quelques usages de l’instruction goto
. C’est le cas des instructions comme continue
ou break
, que l’on trouve dans les langages dérivés du C et qui ont l'avantage de ne pas détourner le flot naturel de contrôle vers une instruction qui se trouve plus loin dans l'ordre textuel du programme, et des exceptions. On peut obtenir un comportement similaire avec le call/cc
de Scheme, ou catch
...throw
en Ruby et Common Lisp (sans rapport avec les exceptions dans ces deux langages).
Edsger Dijkstra et Niklaus Wirth ont défendu l'idée selon laquelle l'instruction goto
ne peut que mener à du code illisible. D'autres, comme Linus Torvalds ou Robert Love (en), ont fait remarquer que même si elle incite à produire du code spaghetti, l'instruction goto
peut être appréciable et rendre au contraire le code plus lisible, lorsqu'elle est employée à bon escient[1]. D'ailleurs, dans leur livre The Elements of Programming Style (en), Kernighan et Plauger (en) indiquent comment écrire du code structuré en Fortran et en PL/I, tout en faisant intensivement appel à l'instruction goto
. Par ailleurs, l'usage de goto
peut être rendu plus clair avec des étiquettes suffisamment descriptives, ce qui est possible lorsque les étiquettes sont alphanumériques, comme en C, mais ce qui n'est pas le cas en BASIC (standard ANSI X3.113), Pascal (standard ISO 7185) ou en Fortran (toutes les versions du standard), qui ont des étiquettes numériques[2].
Langages
L’instruction goto
(ou équivalent) apparaît notamment dans les langages suivants :
- Ada[3]
- Assembleur (existe mais ne s'appelle pas ainsi, par exemple JMP pour l'assembleur 8086)
- BASIC
- TI-Basic
- C
- C++
- D
- C#
- Cobol
- Common Lisp[4]
- Fortran
- Go
- Pascal
- Perl
- PHP depuis la version 5.3 (avec quelques limitations)[5]
- Ruby, depuis la version 1.9, mais seulement sous forme de plaisanterie : les instructions
__goto__
et__label__
sont activées si la variableSUPPORT_JOKE
est définie lors de la compilation de Ruby[6].
En Java goto
est un mot réservé. Or comme l'instruction goto
n'existe pas, goto
devient un mot interdit et cela a pour effet, entre autres, d’empêcher l’emploi de goto
comme nom de variable.
Émulation
En 1966, le théorème de Böhm-Jacopini (en) a démontré que tout programme comportant des goto
pouvait être transformé en programme n’utilisant que des branchements conditionnels (if
, then
, else
) ou des boucles (while
condition do
instructions), éventuellement en dupliquant des portions de codes et/ou en utilisant des variables intermédiaires. Plus tard les deux auteurs ont montré que les branchements conditionnels pouvaient eux-mêmes être remplacés par des boucles.
Goto malgré tout
Dans des langages ne comportant pas de goto
, certains programmeurs restent convaincus (à tort ou à raison) de l’intérêt de les employer, néanmoins. Il s’est alors développé une méthode d’émulation. Concrètement, il s’agit de placer le label dans une variable que le code recherche durant son exécution:
% Début de programme goto = -1 % pas de saut while (goto < 0) { % zone sans libellé } if (goto == 0) { % Toute la partie de libellé 0 } else if (goto == 1) { % Toute la partie de libellé 1 } % ... else if (goto == n) { % Toute la partie de libellé n }
Les libellés peuvent être des chaînes ou des nombres, y compris des expressions et il est possible d’aller plus loin et de ne pas se restreindre à un ensemble de points et représenter les libellés par des ensembles d’intervalles, de plans ou d’hyperplans. L’inconvénient de cette méthode est alors qu’il faut attendre que toutes les instructions de la boucles while
soient exécutées pour que le saut inconditionnel soit réalisé, ce qui dégrade les performances.
Cette construction a été employée par Knuth[réf. nécessaire] pour démontrer qu'il était possible d'écrire du code non structuré sans goto. Il s'agit alors d'un antipattern, c'est-à-dire d'un exemple de ce qu'il ne faut pas faire[7].
Exceptions
Les fonctions setjmp
et longjmp
, disponibles sur certains systèmes d’exploitation, permettent aussi d’émuler l’instruction goto
. Mais ces instructions de saut inconditionnel sont surtout utilisées pour implémenter un système de gestion des exceptions.
L’utilisation d’exception est par exemple un pattern courant en Python pour sortir d’une double boucle :
try :
for i in range(10) :
for j in range(10) :
if TABLE[i][j] == 1:
raise StopIteration
except StopIteration :
pass
Critique
Bien que lors du meeting pré-ALGOL tenue en 1959[réf. nécessaire], Heinz Zemanek ait explicitement exprimé des doutes sur la nécessité du GOTO, à l'époque, personne n'y prête attention, y compris Edsger Dijkstra, qui deviendra plus tard un opposant emblématique de l'instruction GOTO[8]. Les années 1970 et 1980 ont connu une baisse de l'utilisation des GOTO en faveur de la « programmation structurée », en effet, l'instruction GOTO amenait à un « code spaghetti inmaintenable ». Certaines normes de style de programmation déconseillent l'utilisation des instructions GOTO[9]. Il a, cependant, suscité un débat important parmi les informaticiens, éducateurs, concepteurs de langage et les programmeurs d'applications qui ont vu un changement lent, mais régulier, de l'usage autrefois omniprésent du GOTO. La critique probablement la plus célèbre de l'instruction GOTO est une lettre à l'éditeur des Comm. of the ACM de 1968 dû à Edsger Dijkstra intitulée Go To Statement Considered Harmful[8],[10]. Dans cette lettre à l'éditeur, Dijkstra a fait valoir que les instructions GOTO devraient être supprimés dans les langages de niveau supérieur[Lequel ?] car ils compliquent la compréhension, la maîtrise, l'analyse, la vérification et la maintenance des programmes, tout en y introduisant des erreurs difficiles à diagnostiquer. Cette diatribe a initié un débat, notamment 19 ans après à une époque où les langages déclaratifs ont déjà pris de l'ampleur, une lettre GOTO Considered Harmful[11]. Un autre point de vue plus synchronique est présenté par Donald Knuth dans Structured Programming with go to Statements, où il analyse de nombreuses tâches de programmation, dans lesquelles il constate que, dans certaines d'entre elles, le GOTO est la construction de la langue la plus optimale à utiliser[12]. Des codeurs du noyau Linux comme Linus Torvalds ou Steve McConnell, se démarquent du point de vue de Dijkstra, indiquant que le GOTO peut amener à une l'amélioration de la performance du programme, de la taille et de la clarté du code, mais seulement lorsqu'il est utilisé de manière raisonnable[13],[14]. Selon John Regehr, en 2013, il y avait environ 100 000 instructions GOTO dans le code du noyau Linux[15]. En effet, le GOTO est souvent le résultat de code C produit automatiquement, par exemple dans la traduction d'un automate. En 2016, il est inexistant dans les langages de haut niveau. Le langage C est devenu plutôt un langage dans lequel d'autre logiciels produisent du code (voir l'article langage dédié).
Quel usage "raisonnable" pour le goto ?
- Les labels doivent être explicites.
- Le nombre des labels et des renvois doit être faible.
- Il faut envisager autre chose et faire autre chose si c'est plus simple : break, continue, fonctions...
Voir aussi
Liens externes
- Goto Perl, Linux Magazine no 72, mai 2005.
- (en) Edsger Dijkstra, Go To Statement Considered Harmful, (1968)
- (en) Donald Knuth, Structured programming with goto statements, (1974)
- (en) A. T. Arblaster, M. E. Sime, T. R. G. Green, Jumping to some purpose, The Computer Journal, volume 22 no 2, 1979
Références
- (en) Cet article est partiellement ou en totalité issu de l’article de Wikipédia en anglais intitulé « Goto » (voir la liste des auteurs).
- « Linux: Using goto In Kernel Code » (version du 28 novembre 2005 sur l'Internet Archive)
- Noter que les implémentations modernes de Pascal et BASIC permettent également des étiquettes alphanumériques.
- Ada 2012 Reference Manual - 5.8 Goto Statements
- Special Operator GO, Common Lisp HyperSpec
-
goto
sur le manuel de php.net - The Joke Is On Us: How Ruby 1.9 Supports the Goto Statement
- Goto Perl, Philippe Bruhat et Jean Forget 2005
- Dijkstra 1968.
- « GNU Pascal Coding Standards », sur www.gnu-pascal.de (consulté le )
- EWD 215: A Case against the GO TO Statement
- (en) Frank Rubin, « "GOTO Considered Harmful" Considered Harmful », Communications of the ACM, vol. 30, no 3, , p. 195–196 (DOI 10.1145/214748.315722, lire en ligne [archive du ] [PDF])
- (en) Donald Knuth, « Structured Programming with go to Statements », Computing Surveys, vol. 6, no 4, , p. 261–301 (DOI 10.1145/356635.356640, lire en ligne [archive du ], consulté le )
- http://kerneltrap.org/node/553
- (en) « Code Complete, First Edition », Stevemcconnell.com (consulté le )
- Use of Goto in Systems Code
Bibliographie
- (en) Edsger W. Dijkstra, « Letters to the editor: Go to statement considered harmful », Communications of the ACM, vol. 11, no 3, , p. 147–148 (DOI 10.1145/362929.362947, lire en ligne)
- (en) L. Ramshaw, « Eliminating go to's while preserving program structure », Journal of the ACM, vol. 35, no 4, , p. 893 (DOI 10.1145/48014.48021)
- Portail de la programmation informatique