IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Goto, une instruction pas comme les autres


Sujet :

C

  1. #1
    Expert éminent sénior

    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Août 2011
    Messages : 283
    Points : 18 071
    Points
    18 071
    Par défaut Goto, une instruction pas comme les autres
    Goto, une instruction pas comme les autres
    Le débat autour de l’instruction refait surface

    Suite à la découverte récente de bugs à la fois sous Linux et sous iOS/OS X, tous les deux dus à une utilisation de l’instruction Goto du langage C, la question de l’utilisation de cette instruction refait surface.

    Goto est une instruction héritée des premiers langages informatiques, époque où certaines instructions très connues actuellement n’existaient pas, comme les boucles et les structures de contrôle. Néanmoins, même à l’âge moderne de l’informatique et après avoir été décriée par plusieurs informaticiens de renom à l’instar de Djikistra, cette instruction est encore utilisée et cela même au sein des géants de l’informatique comme Apple ; à titre d’exemple la recherche du mot clé Goto sur un portail tel que GitHub débouche sur des millions de résultats.

    Alors dans quel cas cette instruction est encore utilisée ? Parmi les cas de figure évoqués existent la sortie d’une boucle imbriquée ce qui épargne le recours à plusieurs break, l’amélioration de la lisibilité du code et le traitement des erreurs ou encore l’optimisation manuelle du code pour améliorer les performances.

    Toutefois, alors qu’une utilisation parcimonieuse dans les deux premiers cas semble correcte, cela s’avère incorrect pour le dernier cas, selon Jeff Law et Jason Merril, tous les deux ingénieurs chez Red Hat et membres du comité du compilateur GCC. En effet ils expliquent que l’optimisation manuelle du code n’est plus à l’ordre du jour car les compilateurs modernes sont suffisamment développés pour se charger gracieusement de cette tâche, en transformant le code en entrée en une série de blocs de base et en se reposant sur l’utilisation d’un graphe de flot de contrôle (GFC). Résultat des courses aucune distinction entre un code bien structuré et un code en spaghetti (qui résulte d’une addiction au goto).

    Autre argument en faveur de cette thèse, l’article du célèbre Donald Knuth sur le sujet à savoir « Structured Programming with Go To Statements », où il explique qu’une optimisation prématurée du code ne peut déboucher que sur une utilisation malsaine de Goto.

    Au final, la recommandation de l’utilisation du Goto n’est toujours pas à l’ordre du jour, mais cette instruction héritée des premiers âges de l’informatique garde encore sa place dans des cas précis où certains langages, à l’image du langage C, affichent des manques et des carences, ce qui ne cadre pas avec un quelconque souci d’optimisation manuelle du code.

    Source : billet de Larry Seltzer

    Et vous ?

    Qu’en pensez-vous ?

  2. #2
    Modérateur

    Avatar de Bktero
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Juin 2009
    Messages
    4 481
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Loire Atlantique (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués

    Informations forums :
    Inscription : Juin 2009
    Messages : 4 481
    Points : 13 678
    Points
    13 678
    Billets dans le blog
    1
    Par défaut
    On va sérieusement relancer un débat sur goto là ?

    J'ai utilisé goto pour la première fois avant-hier dans un code avec pas mal de if imbriqués. Un nouveau cas s'est présenté et je voulais sauter directement à la gestion d'erreur. J'ai voulu mettre un breakpoint à cet endroit et mon IDE m'a envoyé promener. J'ai alors réécris ma boucle proprement. Et je ne compte pas retenter ma chance. Il y a eu des milliers de débats sur goto dans le monde. La plupart de temps avec des gens qui ne s'en sont jamais servi. goto peut avoir ses intérêts dans certains cas qui sont assez bien identifiés. Mais le fait que quasiment personne ne s'en sert montre qu'on peut presque toujours faire autrement. L'optimisation manuelle du code ne concerne même pas goto en particulier. Le compilateur est là pour optimiser du code qui doit être bien pensé. "Premature optimization is the root of all evil" est valable pour toute optimisation, pas uniquement goto.

    .....

    Mince, j'avais pas tilté qu'on était vendredi

    EDIT : je viens de regarder le code sur drdobbs.com.... L'erreur vient aussi (surtout !) du fait qu'il n'y a pas de crochets accolades autour des if. DES ***** DE CROCHETS ACCOLADES !

  3. #3
    Expert éminent sénior

    Homme Profil pro
    Étudiant
    Inscrit en
    Août 2011
    Messages
    283
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Étudiant
    Secteur : High Tech - Produits et services télécom et Internet

    Informations forums :
    Inscription : Août 2011
    Messages : 283
    Points : 18 071
    Points
    18 071
    Par défaut
    Citation Envoyé par Bktero Voir le message
    On va sérieusement relancer un débat sur goto là ?
    Il s'agit surtout de souligner un mauvais cas d'utilisation, à savoir pretexter l'utilisation du Goto par souci d'optimisation

    Citation Envoyé par Bktero Voir le message
    EDIT : je viens de regarder le code sur drdobbs.com.... L'erreur vient aussi (surtout !) qu'il n'y a pas de crochets autour des if. DES ***** DE CROCHETS !
    Effectivement oui

  4. #4
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 616
    Points
    23 616
    Par défaut
    Citation Envoyé par Arsene Newman Voir le message
    Suite à la découverte récente de bugs à la fois sous Linux et sous iOS/OS X, tous les deux dus à une utilisation de l’instruction Goto du langage C, la question de l’utilisation de cette instruction refait surface.
    Ce n'est pas lié au goto, mais au fait qu'une ligne s'est trouvée dupliquée. 'faudrait voir à ne pas troller plus encore qu'on le fait déjà à ce sujet. Il aurait bien pu se passer la même chose avec un point-virgule mal placé, ce qui est assez fréquent en C.

    Goto est une instruction héritée des premiers langages informatiques, époque où certaines instructions très connues actuellement n’existaient pas, comme les boucles et les structures de contrôles. Néanmoins, même à l’âge moderne de l’informatique et après avoir été décrié par plusieurs informaticiens de renom à l’instar de Djikistra, cette instruction est encore utilisée et cela même au sein des géants de l’informatique comme Apple, à titre d’exemple la recherche du mot clé Goto sur un portail tel que GitHub débouche sur des millions de résultats.
    Paradoxalement, c'est en BASIC 512 et en GW BASIC que j'ai rencontré les pires incompatibilités avec, parce que le langage était interprété et que la fin d'une boucle DO…LOOP ou FOR…NEXT était matérialisée par une instruction, laquelle pouvait en plus être éventuellement soumise à un IF. Les structures de boucles en cours étaient alors stockées dans la pile et faire un goto ne nettoyait donc pas cette pile. Ça restait tout-à-fait légal, d'ailleurs, puisque rien ne nous interdisait de re-sauter vers l'intérieur de la boucle, même si tout cela était sale. En C, ça l'est moins justement parce que les bornes sont définies à la compilation et que le tout est résolu en une série de JMP (donc des gotos) une fois compilé.

    Alors dans quel cas cette instruction est encore utilisée ? Parmi les cas de figure évoqués existent la sortie d’une boucle imbriquée ce qui épargne le recours à plusieurs break, l’amélioration de la lisibilité du code et le traitement des erreurs ou encore l’optimisation manuelle du code pour améliorer les performances.
    Outre ceux cités, j'ai personnellement deux cas en tête :

    1. La possibilité de sauter dans une boucle pour la faire démarrer ailleurs qu'au début, ce qui permet de gérer efficacement les cas du style « 1 + le reste » très utilisés en informatique et dans les séries mathématiques. Par exemple, pour écrire une suite de chiffres séparés par des tirets :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    x=1; goto debut;
    while (x<=5)
    {
        putchar ('-');
        debut:
        printf ("%d",x);
        x++;
    }
    … et qui donne « 1-2-3-4-5 ». Ceci nous permet d'éviter un « if() » au sein de la boucle, évalué à chaque tour simplement pour traiter le premier cas. Je me suis rendu compte a posteriori que c'était l'exemple donné dans la norme pour illustrer goto.

    On remarque que ça pourrait tout-à-fait être un modèle de boucle à part entière : de même qu'il existe « continue » en C pour provoquer le saut immédiat vers la fin de la boucle et lui faire faire une itération, on pourrait tout-à-fait imaginer un mot-clé « start » servant à faire cela.

    2. Les automates finis à états. Le goto est par nature l'âme d'un AFD, puisqu'il s'agit de sauter d'un état prédéterminé à un autre. Si le cheminement du traitement est déterminé à l'avance, il est tout-à-fait possible d'écrire :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    etat1:
        traitement1();
        if (condition) goto etat2;
        if (condition) goto etat3;
        if (condition) goto etat5;
        goto etat6;
     
    etat2:
        traitement2();
        if (condition) goto etat6;
        if (condition) goto etat4;
        if (condition) goto etat1;
        goto etat2;
     
    …
    … dans de telles conditions, on va avoir tendance à écrire un switch() et à stocker l'état en cours dans une variable, ce qui transpose inutilement au runtime ce qui est statique à la base.

    Ce que l'on reproche au goto, donc, c'est surtout d'être généralement incompatible avec la programmation structurée. Mais ça, c'est un paradigme qui doit être pensé par le programmeur avant tout. De la même façon qu'il est possible d'avoir une approche orientée objet en C même si le langage n'est pas spécialement conçu pour cela au départ, il est possible d'écrire un programme propre avec des gotos si le programmeur le souhaite. L'ennui est qu'il est généralement impossible de le faire admettre à son entourage direct et qu'en entreprise, il est plus facile d'écrire du code sale mais « orthodoxe » plutôt qu'avoir à justifier son goto.

    Toutefois alors qu’une utilisation parcimonieuse dans les deux premiers cas semble correcte, cela ne s’avère pas correcte pour le dernier cas selon Jeff Law et Jason Merril tous les deux ingénieurs chez Red Hat et membre du comité du compilateur GCC, en effet ils expliquent que l’optimisation manuelle du code n’est plus à l’ordre du jour car les compilateurs modernes sont suffisamment développés pour se charger gracieusement de cette tâche, en transformant le code en entrée en une série de blocs de base et en se reposant sur l’utilisation d’un graphe de flot de contrôle (GFC), résultat des courses aucune distinction entre un code bien structuré et un code en spaghetti (qui résulte d’une addiction au goto).
    Il faudrait commencer par arrêter d'associer systématiquement goto et code spaghetti. D'abord parce qu'à la longue, ça devient pénible, ensuite et surtout parce que rien n'empêche un programmeur d'écrire du code spaghetti sans goto. Et précisément, une grande maladie, contemporaine cette fois, consiste à éliminer tous les gotos et les remplacer par n'importe quoi d'autre, sans se soucier de savoir si c'est réellement plus efficace (même au niveau global) et surtout si ce n'est pas pire.

    Ensuite, au niveau du compilateur, c'est vrai mais dans une certaine mesure également. Il est vrai que les compilateurs sont devenus particulièrement performants mais le fait est qu'on leur prête souvent des pouvoirs magiques et que les gens qui se penchent réellement sur la qualité du code produit sont bien peu nombreux.

    Au final, la recommandation de l’utilisation du Goto n’est toujours pas à l’ordre du jour mais cette instruction héritée des premiers âges de l’informatique garde encore sa place dans des cas précis où certains langages à l’image du langage C affichent des manques et des carences, ce qui ne cadre pas avec un quelconque souci d’optimisation manuelle du code.
    goto, c'est comme l'utilisateur root sous Unix : c'est l'instruction omni-potente. Il faut juste veiller à ne pas l'utiliser pour se sortir d'une impasse (et c'est surtout ça qu'il faut surveiller à mon avis) mais ça permet d'implémenter facilement ce qui n'a pas été prévu au départ.

    Citation Envoyé par Bktero Voir le message
    Mais le fait que quasiment personne ne s'en sert montre qu'on peut presque toujours faire autrement.
    Un vrai débat de fond, voire un sujet d'études scientifique, serait d'auditer un grand nombre de programmes chez les codeurs de tous niveaux et vérifier si, à chaque fois, la solution alternative adoptée est réellement meilleure. Mais ça…

  5. #5
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Bktero Voir le message
    goto peut avoir ses intérêts dans certains cas qui sont assez bien identifiés. Mais le fait que quasiment personne ne s'en sert montre qu'on peut presque toujours faire autrement. L'optimisation manuelle du code ne concerne même pas goto en particulier.
    Même un if then else sera compilé avec des goto, le but premier des langages ( structurés ) est de simplifier le code source en supprimant les goto qui pique les yeux...


    Citation Envoyé par Obsidian Voir le message
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    x=1; goto debut;
    while (x<5)
    {
        putchar ('-');
        debut:
        printf ("%d",x);
        x++;
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    etat1:
        traitement1();
        if (condition) goto etat2;
        if (condition) goto etat3;
        if (condition) goto etat5;
        goto etat6;
     
    etat2:
        traitement2();
        if (condition) goto etat6;
        if (condition) goto etat4;
        if (condition) goto etat1;
        goto etat2;
     
    …
    Ok pour le deuxième mais le premier se réécrit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    printf ("%d",1);
    x=2;
    while (x<5)
    {
        putchar ('-');
        printf ("%d",x);
        x++;
    }
    je ne vois pas l’intérêt du goto.

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    187
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 187
    Points : 434
    Points
    434
    Par défaut
    Mes souvenirs en C sont un peu rouillés mais un truc du genre revient un peu au même que l'exemple en 1 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    x=1;
    for(;;)
    {
        printf ("%d",x);
        x++;
        if (x==5) break;
        putchar ('-');
    }
    EDIT : arf, valkirys, plus rapide que moi et sans break mais avec une ligne copiée-collée ^^

    Bref, histoire d'illustrer la possibilité d'alternatives.

    Pour les sorties de boucles, java propose une instruction "break nom_label" qui permet de sauter en dehors de la boucle préfixée par "nom_label:".

    C'est n'est que mon avis, mais même ce break-goto devrait être remplacé par une méthode qui contient un return dans la boucle, car il est souvent la manifestation d'une méthode trop complexe qui mériterait être découpée.

  7. #7
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Washmid Voir le message
    EDIT : arf, valkirys, plus rapide que moi et sans break mais avec une ligne copiée-collée ^^
    Je trouve que ça colle bien à l'algorithme, un cas d'initialisation avant une boucle, non?

    Citation Envoyé par Washmid
    C'est n'est que mon avis, mais même ce break-goto devrait être remplacé par une méthode qui contient un return dans la boucle, car il est souvent la manifestation d'une méthode trop complexe qui mériterait être découpée.
    ça donne pourtant un code clair et je vois pas l'intérêt d'introduire une fonction juste pour ça!

    Par exemple, tester le contenue d'une "matrice" à N dimension implique N boucles avec un break si on a trouvé ce que l'on cherche, rien de compliqué a priori :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    search: {
        for (Type type : types) {
            for (Type t : types2) {
                if (some condition) {
                    // Do something and break...
                    break search;
                }
            }
        }
    }
    (en java copier-coller de stackoverflow, c'est mal je sais )
    Dernière modification par Invité ; 14/03/2014 à 12h54.

  8. #8
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 616
    Points
    23 616
    Par défaut
    Citation Envoyé par valkirys Voir le message
    Même un if then else sera compilé avec des goto, le but premier des langages ( structurés ) est de simplifier le code source en supprimant les goto qui pique les yeux...
    La vraie question est : pourquoi ça te pique les yeux (à part le fait que c'est ce que l'on t'a toujours dit) ? Les réponses existent et elles sont à la base de ce débat, mais elles sont discutables en fonction de la situation et surtout, plus personne ne se pose cette question, même au départ.

    Et c'est bien le problème : l'objectif des codeurs n'est plus d'écrire le code le propre possible en fonction du contexte mais bien d'éviter les goto par principe.

    Ok pour le deuxième mais le premier se réécrit :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    printf ("%d",1);
    x=2;
    while (x<5)
    {
        putchar ('-');
        printf ("%d",x);
        x++;
    }
    je ne vois pas l’intérêt du goto.
    Justement pour éviter d'avoir à écrire deux fois la même chose, uniquement pour prendre en compte le cas initial !

    Dans cet exemple, tu saisis deux fois « printf() » mais tu n'établis aucune relation logique entre les deux : le compilateur n'a aucun moyen de savoir que ton premier printf() est en fait censé faire partie de la même boucle, ce qui casse complètement le principe-même de la programmation structurée. Ensuite, même si ce n'était pas nécessaire, tu as changé la condition initiale (x=2 et plus x=1) et quitte à écrire printf("%d",1);, tu aurais pu directement écrire printf("1");. Donc, des erreurs en cascade induites par la volonté de se priver du goto et qui, au final, rendent le code moins bon qu'au départ.

    Ensuite, dans le cas présent, il n'y a qu'une seule instruction. Que se passerait-il si tu devais sauter les cinquante premières instructions d'une boucle qui en compte cent ? Pour adopter le modèle que tu nous présentes, tu serais obligé de déclarer une fonction pour les appeler facilement avant puis dans la boucle. Et si tu retrouves le même cas de figure trente fois dans ton programme, tu dois déclarer trente fonctions locales. C'est idiot.

    C'est également plus pénible pour le développeur : même s'il reconnaît ce que tu es en train de faire, il ne peut pas savoir s'il y a bien une liaison implicite entre tes deux printf. Ça devient critique lorsque tu fais la maintenance d'un grand programme : lorsque tu en vient à modifier ce printf pour le mettre à jour ou le remplacer par autre chose, tu introduis automatiquement un bug si tu ne penses pas à traiter l'autre.

    Il est intéressant, lorsque l'on développe du logiciel, d'essayer de transposer cela au reste de l'industrie et, en particulier, de penser à la manière dont on réaliserait la fonction de façon mécanique plutôt que logicielle : dans le cas présent, si je veux imprimer sur une feuille une suite de motifs séparés par des tirets, il me suffit de construire un simple rouleau d'imprimerie et de le « déphaser » de manière à ce qu'il commence par le motif plutôt que par le tiret. La solution que tu nous proposes consisterait, elle, à mettre en place une machine spéciale dédiée pour imprimer le premier motif uniquement avant de faire passer normalement la feuille dans le rouleau.

    Tout cela pour éviter un goto qui aurait eu tout-à-fait sa place ici.


    C'est intéressant parce qu'en général, on en arrive à dire « de toutes façons le compilateur va optimiser tout cela ». Personne ne nous le garantit, d'une part, et cela revient à dire que le vrai travail est en fait mené par les personnes qui ont conçu le compilateur. Et même alors, le compilateur sera à même de faire cette optimisation que s'il est capable de reconnaître le modèle. Il faut donc que celui-ci soit défini au départ et fasse partie des motifs qui lui ont été enseignés. En toute rigueur, c'est surtout ce travail que le programmeur devrait faire, et utiliser les goto si le langage ne propose pas de lui-même ce modèle.

    Citation Envoyé par Washmid Voir le message
    Mes souvenirs en C sont un peu rouillés mais un truc du genre revient un peu au même que l'exemple en 1 :
    EDIT : arf, valkirys, plus rapide que moi et sans break mais avec une ligne copiée-collée ^^
    C'était justement le problème de départ : éviter de se trimballer un « if » évalué à chaque itération alors qu'il n'est là que pour tester le premier cas.

  9. #9
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Obsidian Voir le message
    La vraie question est : pourquoi ça te pique les yeux (à part le fait que c'est ce que l'on t'a toujours dit) ? Les réponses existent et elles sont à la base de ce débat, mais elles sont discutables en fonction de la situation et surtout, plus personne ne se pose cette question, même au départ.
    On ne m'a rien dit!
    J'ai appris l'assembleur seul et n'ai pas fait d'études en informatique.
    Je vois la différence entre de la programmation objet/structuré et des jump en asm ( je suis allergique au fonctionnel).

    Citation Envoyé par Obsidian
    Justement pour éviter d'avoir à écrire deux fois la même chose, uniquement pour prendre en compte le cas initial !

    Dans cet exemple, tu saisis deux fois « printf() » mais tu n'établis aucune relation logique entre les deux : le compilateur n'a aucun moyen de savoir que ton premier printf() est en fait censé faire partie de la même boucle, ce qui casse complètement le principe-même de la programmation structurée. Ensuite, même si ce n'était pas nécessaire, tu as changé la condition initiale (x=2 et plus x=1) et quitte à écrire printf("%d",1);, tu aurais pu directement écrire printf("1");. Donc, des erreurs en cascade induites par la volonté de se priver du goto et qui, au final, rendent le code moins bon qu'au départ.

    Ensuite, dans le cas présent, il n'y a qu'une seule instruction. Que se passerait-il si tu devais sauter les cinquante premières instructions d'une boucle qui en compte cent ? Pour adopter le modèle que tu nous présentes, tu serais obligé de déclarer une fonction pour les appeler facilement avant puis dans la boucle. Et si tu retrouves le même cas de figure trente fois dans ton programme, tu dois déclarer trente fonctions locales. C'est idiot.
    Idot? Je comprends bien à la lecture des derniers paragraphes votre façon de faire très mécanique, mais je trouve normal de découper un algorithme en une phase d'initialisation+ traitement des cas puis une partie automatique (boucle) c'est plus clair.
    Et si il faut introduire des fonctions alors c'est d'accord pour moi.
    ( pour le printf("%d",1);, on est d'accord c'est un exemple écrit vite fait )

    Citation Envoyé par Obsidian
    Ça devient critique lorsque tu fais la maintenance d'un grand programme : lorsque tu en vient à modifier ce printf pour le mettre à jour ou le remplacer par autre chose, tu introduis automatiquement un bug si tu ne penses pas à traiter l'autre.
    Il manque des commentaires expliquant que algorithmes à deux partis inutilisation et boucle. Et bien sûr il ne faudrait pas des 5 codé en dur...

    Citation Envoyé par Obsidian
    Il est intéressant, lorsque l'on développe du logiciel, d'essayer de transposer cela au reste de l'industrie et, en particulier, de penser à la manière dont on réaliserait la fonction de façon mécanique plutôt que logicielle : dans le cas présent, si je veux imprimer sur une feuille une suite de motifs séparés par des tirets, il me suffit de construire un simple rouleau d'imprimerie et de le « déphaser » de manière à ce qu'il commence par le motif plutôt que par le tiret. La solution que tu nous proposes consisterait, elle, à mettre en place une machine spéciale dédiée pour imprimer le premier motif uniquement avant de faire passer normalement la feuille dans le rouleau.
    Intéressant mais je ne pense pas de cette manière, avec un langage type C ( pas fait d'assembleur depuis des années ) et je préfère la mienne ( initialisation, cas généraux ).

    Citation Envoyé par Obsidian
    Et c'est bien le problème : l'objectif des codeurs n'est plus d'écrire le code le propre possible en fonction du contexte mais bien d'éviter les goto par principe.
    J'évite les goto ( sauf boucles imbriqués ) par principe mais pas pour ces raisons là.

  10. #10
    Membre éclairé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 222
    Points : 766
    Points
    766
    Par défaut
    Heureusement il y a toujours une actu sur developpez.com pour nous rappeler qu'on est vendredi.

    Je crois bien que la dernière fois que j'ai utilisé une instruction goto c'était dans un programme basic, il doit y avoir une vingtaine d'années... je n'aurai pas mis ma main à couper sur le fait que les goto soient encore utilisés. Mais heureusement on n'a pas besoin des goto pour mettre plein de bugs dans les logiciels.

    Vu comment sont actuellement développés les logiciels, je pense que les développeurs feraient mieux de chercher à optimiser l'utilisation mémoire plutôt que de perdre du temps à faire des goto.

    Mais de là dire que les compilateurs actuels sont capables de faire de l’optimisation poussée automatiquement... je considère le C comme un langage relativement bas niveau dans le sens où le développeur s'attend à ce que le résultat de la compilation reste sassez proche du code source. Même si le C permet de faire des des choses plus complexe, je pense que quand on veut réellement faire de la programmation structurée et/ou abstraite on se dirige vers d'autres langages en utilisant les paradigmes de programmation qui leurs sont liés.

    Par exemple un goto dans du C ne me choque pas car je m'attend à y lire de la programmation bas niveau, alors que dans du C++ ça m'interpellerait plus car je m'attend à y lire de la programmation objet de relativement haut niveau. Ce qui devient un compliqué et qui sera source d'erreurs c'est quand on veut mélanger le bas et le haut niveau.

  11. #11
    Modérateur
    Avatar de Obsidian
    Homme Profil pro
    Développeur en systèmes embarqués
    Inscrit en
    Septembre 2007
    Messages
    7 368
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur en systèmes embarqués
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2007
    Messages : 7 368
    Points : 23 616
    Points
    23 616
    Par défaut
    Avant tout : je m'aperçois en me relisant que mon ton était peut-être un peu sec. Mes excuses à ce que j'aurais pu blesser, ce n'était pas intentionnel. Nous sommes bien en train de disserter sur le fond et rien d'autre.

    Citation Envoyé par valkirys Voir le message
    OnIdot? Je comprends bien à la lecture des derniers paragraphes votre façon de faire très mécanique, mais je trouve normal de découper un algorithme en une phase d'initialisation+ traitement des cas puis une partie automatique (boucle) c'est plus clair.
    Oui mais justement : le premier tour de boucle ne constitue pas une phase d'initialisation. C'est la même que celle des autres tours et l'une et l'autre doivent être modifiées en même temps si c'est nécessaire.

    Et si il faut introduire des fonctions alors c'est d'accord pour moi.
    En quoi — dans le cas présent — est-ce plus propre qu'un goto ?

    ( pour le printf("%d",1);, on est d'accord c'est un exemple écrit vite fait )
    On est bien d'accord et c'est bien comme cela que je l'ai vu aussi : cela dit, c'est révélateur d'un problème assez fréquent : introduire des horreurs, volontairement ou non, pour corriger des choses qui n'ont pas besoin de l'être. C'est très fréquent en développement logiciel.

    Il manque des commentaires expliquant que algorithmes à deux partis inutilisation et boucle. Et bien sûr il ne faudrait pas des 5 codé en dur...
    Les commentaires sont un autre débat mais là encore, le problème de fond est différent : il s'agit bien d'un modèle de boucle à part entière et pas d'une initialisation préalable. Dans le cas du rouleau d'imprimerie, l'initialisation consisterait justement à placer le rouleau dans la bonne position avant de lancer la machine. Pas à imprimer le motif.

    J'évite les goto ( sauf boucles imbriqués ) par principe mais pas pour ces raisons là.
    Justement : la sortie d'une boucle imbriquée avec goto, ça se pratique parce qu'il n'existe pas de « break n ». On en revient à ce que l'on disait : on définit un modèle clair au départ et on l'implémente avec des gotos quand le langage ne le propose pas lui-même.

    Maintenant, comme on l'a dit également, la sortie de boucle est un modèle qui marche très bien en C mais qui n'est pas du tout universel et qui pose problème justement avec les langages interprétés, à commencer par le BASIC où le goto, s'il n'en est pas carrément issu, est censé être roi.

  12. #12
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Pour ma part je suis en train de faire des tests en C++, et le goto s'en sort vraiment très bien au milieu des exceptions et des destructeurs.
    J'en écrirai plus long sur le sujet quand j'aurai suffisamment fait de tests, mais pour l'instant il me semble que l'on pourrait (en C++, pas en C attention) le dédiaboliser, car il apporte la solution à un certains nombre de problèmes qui sont actuellement résolus par des workaround bien moches à coups de boucles.

  13. #13
    Membre averti

    Homme Profil pro
    Développeur Web
    Inscrit en
    Février 2013
    Messages
    88
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2013
    Messages : 88
    Points : 447
    Points
    447
    Billets dans le blog
    1
    Par défaut
    L'instruction GOTO ou JUMP suivant comment chacun l'a appris est à la base de nos structures IF, FOR, WHILE et UNTIL.
    Il est tout aussi possible de réaliser des bugs avec une instruction GOTO en l'utilisant mal qu'avec une structure WHILE.
    Il reste à chacun d'utiliser ce avoir quoi il est le plus à l'aise et confiant. Blâmer l'un ou l'autre n'a aucun sens.

    On pourrait aussi parler de l'utilité des instructions CONTINUE et BREAK disponibles dans la majorité des langage largement utilisés, qui ne sont que des GOTO avec comme restriction de n'agir que dans le cadre d'une instruction FOR, WHILE ou UNTIL.

  14. #14
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 518
    Points
    41 518
    Par défaut
    Pourquoi tant de gens ici parlent de "goto pour optimisation"?

    Les deux bugs récents proviennent de codes où l'usage de goto n'avait rien à voir avec l'optimisation, et tout à voir avec une gestion d'erreur+nettoyage plus lisible (sans code boomerang et sans duplication du nettoyage à chaque sortie).

    Ce qui est à ma connaissance le cas le plus reconnu pour l'utilisation de goto en C.

    Et franchement, la source du bug était plutôt une étiquette dont le nom ne correspondait pas au contenu (le "fail" du bug Apple faisait en fait un "cleanup") que le goto lui-même.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  15. #15
    Membre émérite
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Janvier 2010
    Messages
    553
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2010
    Messages : 553
    Points : 2 740
    Points
    2 740
    Par défaut
    Citation Envoyé par Grimly Voir le message
    On pourrait aussi parler de l'utilité des instructions CONTINUE et BREAK disponibles dans la majorité des langage largement utilisés, qui ne sont que des GOTO avec comme restriction de n'agir que dans le cadre d'une instruction FOR, WHILE ou UNTIL.
    c'est justement là qu'est le problème du goto: il ne souffre d'aucune restriction.
    un continue ou un break ne risque pas de dérouter le flot d'exécution n'importe ou après une étourderie quelconque. même chose pour n'importe quelle boucle.

    alors oui les branchements et les boucles sont traduits par des sauts en langage machine et on pourrait penser qu'il est donc tout à fait inutile d'utiliser des branchements ou des boucles plutôt que des goto... ça serait un peu comme penser qu'il est tout à fait inutile d'utiliser des bibliothèques puisque qu'on peut faire ce qu'elles font avec des instructions de base et sans se restreindre...

    je crois qu'en matière de programmation les restrictions ne sont pas là juste pour nous prendre la tête, elles sont la plupart du temps des garde fous pour nous éviter de faire des âneries.

  16. #16
    Expert confirmé Avatar de ManusDei
    Homme Profil pro
    vilain troll de l'UE
    Inscrit en
    Février 2010
    Messages
    1 619
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : vilain troll de l'UE

    Informations forums :
    Inscription : Février 2010
    Messages : 1 619
    Points : 4 350
    Points
    4 350
    Par défaut
    La non-utilisation du GOTO n'est pas une restriction, mais une tradition, nuance.
    Et il faudrait faire attention à ne pas en faire un dogme, car il existe quelques rares cas où il est indispensables, et d'autres où il est quand même bien plus clair.

    PS : Sinon on devrait interdire les pointeurs manuels et leur manipulation, car niveau casse-gueule, les pointeurs c'est pas mal non plus (ça et la gestion manuelle de la mémoire).
    http://www.traducteur-sms.com/ On ne sait jamais quand il va servir, donc il faut toujours le garder sous la main

  17. #17
    En attente de confirmation mail

    Profil pro
    Inscrit en
    Septembre 2013
    Messages
    639
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2013
    Messages : 639
    Points : 2 347
    Points
    2 347
    Par défaut
    Les pointeurs c'est la liberté. Dans un langage avec pointeur, le programmeur décide si un type de données qu'il crée est un pointeur explicite, un pointeur implicite ou pas un pointeur du tout. Dans un langage sans pointeur, la règle est la sémantique par référence uniforme, et il faut s'y plier que cela nous arrange ou non.

    Quand j'étais étudiant, un de nos profs avait écrit un module en pur langage C qui offrait une implémentation tout à fait bonne des exceptions dans ce langage. Quand on regardait le code de ce module, il y avait quelques goto dedans, et il aurait été difficile de s'en passer.

    Cela dit évidemment qu'un programmeur n'a généralement pas besoin d'utiliser des gotos.

    EDIT : l'intervention de 11h32 de Obsidian est hyper intéressante. J'ai appris des trucs.

  18. #18
    Membre chevronné
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2007
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Gironde (Aquitaine)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2007
    Messages : 677
    Points : 2 137
    Points
    2 137
    Par défaut
    Ah les goto, ça me rappelle mes débuts sur Amstrad (ça et les gosub/return, l’ancêtre des fonctions). Ceux qui saignent des yeux à la vue d’un goto feraient des cauchemars à la vue d’un programme écrit en Basic de l’époque.

    Par contre, pour ce qui est de C#, Java et C++ (les principaux langages que je côtoie au quotidien) je dois admettre ne jamais avoir aperçu une seule de ces bestioles, je mettrais naïvement ça sur le compte "haut niveau" et "orienté objet" desdits langages.
    Le WIP de The last bastion, mon projet de jeu-vidéo (un TD en 3D)

    Mon portfolio / Ma page fb

  19. #19
    Membre expert

    Avatar de germinolegrand
    Homme Profil pro
    Développeur de jeux vidéo
    Inscrit en
    Octobre 2010
    Messages
    738
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : Développeur de jeux vidéo
    Secteur : Tourisme - Loisirs

    Informations forums :
    Inscription : Octobre 2010
    Messages : 738
    Points : 3 892
    Points
    3 892
    Par défaut
    Citation Envoyé par I_Pnose Voir le message
    Par contre, pour ce qui est de C#, Java et C++ (les principaux langages que je côtoie au quotidien) je dois admettre ne jamais avoir aperçu une seule de ces bestioles, je mettrais naïvement ça sur le compte "haut niveau" et "orienté objet" desdits langages.
    Je mettrais plutôt ça sur le compte du dogmatisme faramineux qui sous-tend les communautés de ces langages, plus promptes à sortir leurs fameux Design Patterns que des solutions sur mesure. Alors que (et c'est très amusant de mon point de vue) un simple goto solutionnerait un des plus gros problèmes du Java (ils se plaignent de pas pouvoir revenir au début de leur try s'il a échoué... ).

  20. #20
    Membre extrêmement actif
    Homme Profil pro
    Graphic Programmer
    Inscrit en
    Mars 2006
    Messages
    1 545
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Graphic Programmer
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Mars 2006
    Messages : 1 545
    Points : 3 941
    Points
    3 941
    Par défaut
    moi j'aime pas les goto parce que je trouve pas ca elegant. un beau code n'a pas de goto et est donc arrangé autrement pour moi ^^
    tres tot mon pere m'avait dit d'essayer de concevoir sans goto. et maintenant des que je vois un goto j'essai pas tout les moyens de le virer. j'ai pas d'autres arguments, dans ma tete goto = defaut de conception ^^ et dans du code VBA les croisement de goto ca fou un merdier au debug...

    le goto c'est vraiment la rustine super sale qu'on met dans du code quand on est desespéré ^^

    mais bon si on descend au langage de plus bas niveau, en assembleur, on pourrait rien faire sans les saut d'adresse...

Discussions similaires

  1. Envoie formulaire depuis flash(pas comme les autres)
    Par TobyKaos dans le forum Flash
    Réponses: 1
    Dernier message: 22/11/2007, 15h38
  2. Une macro pas comme les autres:)
    Par Lucie75 dans le forum Macros et VBA Excel
    Réponses: 2
    Dernier message: 07/08/2007, 12h11
  3. Tâche planifiée pas comme les autres
    Par casavba dans le forum VBA Outlook
    Réponses: 2
    Dernier message: 07/08/2007, 12h08
  4. requete selection mais pas comme les autres
    Par adil_math2006 dans le forum MS SQL Server
    Réponses: 2
    Dernier message: 28/06/2007, 13h44
  5. Une horloge pas comme les autres
    Par laurent2101 dans le forum Flash
    Réponses: 3
    Dernier message: 12/06/2007, 16h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo