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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    gl
    gl est déconnecté
    Rédacteur

    Homme Profil pro
    Inscrit en
    Juin 2002
    Messages
    2 165
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Isère (Rhône Alpes)

    Informations forums :
    Inscription : Juin 2002
    Messages : 2 165
    Par défaut
    Citation Envoyé par valkirys Voir le message
    Les fonctions sont bien, par principe car on peut faire des tests fonctionnels.
    Lorsqu'elles n'ont pas de responsabilité clairement définies et pas de sens par elles-mêmes (i.e. quand une fonction est créée juste pour respecter une règle quelconque : nombre de lignes, pas de goto), elles ne sont pas bien et ne permettent pas de faire des tests fonctionnels dessus (tout simplement car elles ne sont pas une fonctionnalité).

    Commençons par réfléchir aux responsabilités, aux rôles des différentes fonctions, à l'objectif à atteindre plutôt que de se focaliser sur telle ou telle règle arbitraire. On aboutit à de bien meilleurs résultats (et ces règles sont naturellement respectées dans l'immense majorité des cas, sauf quand elles nuisent plus qu'autre chose).

  2. #2
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par gl Voir le message
    Lorsqu'elles n'ont pas de responsabilité clairement définies et pas de sens par elles-mêmes (i.e. quand une fonction est créée juste pour respecter une règle quelconque : nombre de lignes, pas de goto), elles ne sont pas bien et ne permettent pas de faire des tests fonctionnels dessus (tout simplement car elles ne sont pas une fonctionnalité).

    Commençons par réfléchir aux responsabilités, aux rôles des différentes fonctions, à l'objectif à atteindre plutôt que de se focaliser sur telle ou telle règle arbitraire. On aboutit à de bien meilleurs résultats (et ces règles sont naturellement respectées dans l'immense majorité des cas, sauf quand elles nuisent plus qu'autre chose).
    Je n'ai pas dis le contraire, et c'est bien de rappeler tout cela. Le fait est que si l'on pense le code avec des fonctions pour des tests on évitera la majorité des goto.

  3. #3
    Membre extrêmement actif
    Homme Profil pro
    Graphic Programmer
    Inscrit en
    Mars 2006
    Messages
    1 631
    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 631
    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...

  4. #4
    Modérateur

    Homme Profil pro
    Développeur java, access, sql server
    Inscrit en
    Octobre 2005
    Messages
    2 713
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Développeur java, access, sql server
    Secteur : Industrie

    Informations forums :
    Inscription : Octobre 2005
    Messages : 2 713
    Par défaut GOTO utile s'il reste lisible
    Il m'arrive d'utiliser un GOTO en Transaq-SQL quand je fais une procédure stockée et que je ne souhaite pas faire de sous-procédures

    On est là dans un cas particulier :
    - le programme court (pas plus d'une centaine de lignes)
    - le langage a un domaine assez limité (orienté uniquement sur la manipulation de tables)

    du coup le GOTO reste lisible et facilement débugable.

    s'il n'y avait pas de GOTO, alors il me faudrait utiliser un enchaînement de IF BEGIN END ELSE IF BEGIN .... ce qui est dur à lire.
    le goto qui pointe sur des étiquettes bien claires, ça peut être pas mal !

    à l'inverse, en Java, même si le goto était possible, je ne l'utiliserai pas pour des raisons de lisibilité.
    Labor improbus omnia vincit un travail acharné vient à bout de tout - Ambroise Paré (1510-1590)

    Consulter sans modération la FAQ ainsi que les bons ouvrages : http://jmdoudoux.developpez.com/cours/developpons/java/

  5. #5
    Inactif  
    Profil pro
    undef
    Inscrit en
    Février 2013
    Messages
    1 001
    Détails du profil
    Informations personnelles :
    Localisation : France, Lot (Midi Pyrénées)

    Informations professionnelles :
    Activité : undef

    Informations forums :
    Inscription : Février 2013
    Messages : 1 001
    Par défaut
    ça peut aider dans une volonté d’obfuscation.

  6. #6
    Membre actif
    Profil pro
    Inscrit en
    Juin 2010
    Messages
    79
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2010
    Messages : 79
    Par défaut GOTO retour vers... le passé
    Bonjour à tous,

    Je suis un amateur, j'ai commencé à écrire de petits programmes personnel avec un ORIC en 1983... aujourd’hui j'utilise Windev.
    Le souvenir que je garde des instructions GOTO sous Basic, c'est qu'elles se trouvaient dans le programme principal qui s'exécutait linéairement et qu'elles permettaient un branchement à une ligne précise.
    Aujourd’hui avec le procédural, c'est les appels aux fonctions et autres procédures qui font le boulot et GOTO n'a plus d'intérêt... me semble-t'il.
    Du reste, il aura fallut que je tombe sur la question posée dans ce forum, pour que je me demande si l'instruction GOTO intègre Windev... oui c'est le cas, mais je ne l'ai jamais utilisée.
    Maintenant, c'est vous qui voyez...

    Bon dev.

  7. #7
    Membre Expert
    Homme Profil pro
    sans emploi
    Inscrit en
    Janvier 2014
    Messages
    539
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : sans emploi
    Secteur : Conseil

    Informations forums :
    Inscription : Janvier 2014
    Messages : 539
    Par défaut
    Bonjour,

    cela faisait longtemps aussi que je n'avait répondu à un fil sur le goto !
    Après m'être frotté avec des machines allant du TI99/4A à l'atari 512stf, J'ai enfin reçu une «vraie» formation informatique en fac au courant des années 1990. C'est à ce moment qu'on m'a révélé les commandements que je ne devrais jamais violer au risque de m'exposer à la colère divine. Je peux citer des choses comme «la bande passante du réseau illimitée tu ne croiras point» ou «de courtes fonctions tu écriras» sans oublier le «ton code tu commenteras». Mais il est vrai que LA loi première était «JAMAIS de goto tu n'utiliseras», LA loi qui évite de rentrer dans un état de péché originel ... le goto est comme une pomme qu'il ne faut pas croquer sous peine d'expulsion du jardin de l'Eden de la programmation structurée.
    J'obéissais militairement à ces lois dans le but d'être adoubé mais essayais néanmoins d'en comprendre l'origine. Jusqu'au jour où j'ai reçu l'illumination de la part d'un de mes professeur, M. Cansell (true story).

    Le goto peut introduire de la confusion dans la phase de compilation, il interrompt le flux sans qu'on puisse a priori savoir ce qui va se passer réellement ou quelle était l'intention du programmeur (du moins à l'époque). Écrire une boucle for en utilisant des gotos masquait le fait de vouloir utiliser une boucle for et empêchait le compilo de faire du bon boulot. C'est pourquoi il était préférable de toujours utiliser une boucle for ou while, ou toute autre structure de plus haut niveau pour se passer de goto. Enfin en général, car les gurus du goto pouvaient optimiser certains codes grâce à eux, mais comme nous ne sommes que des mortels faillibles et non des gurus ....
    Et effectivement, au fur et à mesure, les cas d'utilisation de goto se sont retrouvées de moins en moins nombreux car remplacés par de nouvelles structure de niveau supérieur : switch (goto calculé), gestion des erreurs, etc ...
    La règle est alors amendée : si le langage utilisé ne propose pas la structure de contrôle adaptée alors le goto avec des pincettes tu pourras utiliser. Par exemple le C ne propose pas de gestion d'erreur par try/catch ... ok on peut utiliser les goto si c'est indispensable, C ne propose pas un «ne fait pas ça pour au premier tour de boucle» du coup un goto est «autorisé» et même élégant dans ce cas je trouve car ça évite une duplication de code (encore une loi ... jamais inutilement du code tu ne dupliqueras).

    Le second point est, comme le soulève Obsidian, celui des automates finis, et plus généralement des parsers. Les machines à états avec transitions s'implémentent agréablement avec des gotos ... mais souvent la taille des programmes est telle que le code devient complexe sans pour autant être compliqué. La solution la plus simple est donc de créer un programme (et de prouver qu'il est correct) qui va s"en charger pour nous. Lex,flex,bison et yacc tirent leur origine de ça et créent du code bourré de goto (enfin dans les années 90...) tout à fait correct (la plupart du temps dans les années 90 ).

    Bref, un goto c'est comme une paire de ciseaux pointus : on se blesse plus souvent qu'avec une paire de ciseaux arrondis.

  8. #8
    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
    Par défaut
    Citation Envoyé par picodev Voir le message
    Bref, un goto c'est comme une paire de ciseaux pointus : on se blesse plus souvent qu'avec une paire de ciseaux arrondis.
    Mais les meilleurs artisans n'oublient jamais qu'ils ont dans leur boîte à outils une paire de ciseaux pointus pour s'adapter précisément à leurs besoins .
    Le plus grand danger c'est de ne pas connaître les outils à sa disposition, et pire, d'en avoir peur .

  9. #9
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 026
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 026
    Par défaut
    Bonjour,

    Le goto est très utilisé en programmation kernel :
    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
    16
    17
    void foo(void)
    {
          char * ptr = kalloc(sizeof(char) );
          if( ! ptr )
               goto END;
          // blabla
         char * ptr2 = kalloc(sizeof(char) );
          if( ! ptr2)
               goto FREE_PTR1;
     
     
          free(ptr2);
    FREE_PTR1 :
          free(ptr);
    END : 
          // blabla
    }
    Ils permettent d'être sûr que toutes les ressources sont bien libérées à la fin de la fonction.
    Bon là je n'ai qu'un exemple "bateau".

  10. #10
    Membre éclairé
    Profil pro
    Retraité
    Inscrit en
    Novembre 2009
    Messages
    331
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2009
    Messages : 331
    Par défaut
    L'exemple donné par Obsdian http://www.developpez.net/forums/d14...tion-autres/#4
    ne me semble pas très heureux: j'écrirai plutôt ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (x = 1; x < 5; x++) {
        printf ("%d-",x);
     }
    printf ("%d" ,x++);
    Entrer au milieu d'une boucle est interdit en Fortran pour une raison simple: il est très facile de ne pas initialiser correctement cette boucle, et si la boucle comporte de nombreuses lignes, il n'est pas naturel de remonter loin en avant pour le vérifier.

    Bien sûr, le goto est bien utile dans certains cas (je n'hésite pas à l'utiliser, c'est faire preuve de sectarisme que de s'y refuser)
    [TROLL]
    mais pour obscurcir un code, rien ne vaut le COMEFROM http://en.wikipedia.org/wiki/Comefrom
    [/TROLL]

  11. #11
    Inactif  

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Décembre 2012
    Messages
    63
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Cher (Centre)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : Arts - Culture

    Informations forums :
    Inscription : Décembre 2012
    Messages : 63
    Billets dans le blog
    1
    Par défaut Pour mémoire vous devriez citer l'exemple du concepteur du langage pascal...
    Pour mémoire vous devriez citer l'exemple du concepteur du langage pascal Niklaus Wirth, qui avait prédit que l'on puisse se passer de la fonction GoTo a travers des structures élaborées de programmation.

    D'autre part, les programmeurs devraient aussi connaître le langage de l'assembleur et de constater la présence des instructions Jump et ses déclinaisons.

  12. #12
    Membre éprouvé
    Avatar de Matthieu Vergne
    Homme Profil pro
    Consultant IT, chercheur IA indépendant
    Inscrit en
    Novembre 2011
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant IT, chercheur IA indépendant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 2 307
    Billets dans le blog
    3
    Par défaut
    Pour ma part, un langage de programmation est, au même titre qu'un langage naturel, voué à communiquer une idée en vue de faire exécuter une action par un interpréteur. Dans une simple conversation, ce serait tout simplement de faire comprendre à l'autre ce à quoi on pense, dans le cas d'un programme, c'est d'exécuter une fonctionnalité particulière. À ce titre, l'utilisation du goto est à bannir pour une raison purement linguistique : c'est un opérateur ayant une sémantique trop large, et donc trop peu informative sur les réelles intentions. C'est comme si on utilisait le terme "chose" ou "truc" pour parler. Avec un ou deux dans la phrase, si on suit bien on peut arriver à recoller les morceaux et savoir de quoi on parle. Avec ce genre de termes utilisés à tout bout de champs, on ne comprends plus rien et on n'a plus qu'à prier pour que ce qu'on dise soit bien compris comme on le souhaite par l'interpréteur. Dit autrement, dès lors où on a des structures sémantiquement plus précises qui correspondent à nos besoins, choisir d'utiliser néanmoins un goto est équivalent à choisir de manquer de clarté, même avec parcimonie. C'est de la mauvais fainéantise.

    Dans l'exemple d'Obsidian :
    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++;
    }
    Plusieurs l'ont fait remarquer : ton goto peut être remplacé par un code tout aussi complexe où tu fait ton printf avant la boucle, sur le modèle d'une initialisation suivie d'une répétition.
    Citation Envoyé par Obsidian Voir le message
    Dans cet exemple, tu saisis deux fois « printf() » mais tu n'établis aucune relation logique entre les deux[...]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.
    La maintenance te gène du fait de la duplication de code ? Met ton printf dans une fonction et appelle cette fonction, ce qui a du sens car on veut bel et bien faire exactement la même chose avant et dans la boucle (clin d'oeil à gl : "Commençons par réfléchir aux responsabilités, aux rôles des différentes fonctions, à l'objectif à atteindre plutôt que de se focaliser sur telle ou telle règle arbitraire."). Tu n'aimes pas le fait d'avoir un appel de fonction pour quelque chose d'aussi simple ? C'est une optimisation basique qu'un compilateur est tout à fait à même de faire : cette fonction n'est utilisée qu'ici, elle est courte (1 ligne contre 1 ligne) et donc il est tout à fait pertinent de remplacer l'appel de fonction par la ligne correspondante à la compilation. En revanche, avec ton goto, tu dis au compilateur que tu veux commencer au milieu de la boucle sans dire pourquoi, empêchant le compilateur de faire son boulot d'optimisation. Et du point de vue du développeur, quand il voit que tu appelles une fonction, il se fiche pas mal du contenu de cette fonction : elle est là pour faire un boulot particulier. Tant qu'elle le fait correctement, tout va bien. Décider de remplacer l'appel d'une fonction par son code juste pour économiser des lignes, c'est faire une optimisation syntaxique qui n'a pas lieu d'être car n'apporte rien au dév si ce n'est de satisfaire son égo en pensant à tord qu'il a aidé le compilo : pourquoi un dév serait meilleur, pour faire des optimisations aussi simples, qu'un compilo fait par toute une communauté ? Mais je reviens sur ce point plus loin.

    Et encore, ici on pinaille sur le bien fondé de faire une fonction pour un printf, mais cette logique est généralisable : quand tu as plusieurs lignes qui se suivent au sein de la boucle que tu veux répéter lors d'une initialisation, c'est que cet ensemble de lignes à un rôle précis, qui peut être avantageusement traduit en une fonction bien nommée (sinon c'est que tu ne maitrise pas ton propre code, donc revoit ta conception) qui est appelée avant et dans la boucle. Au même titre que refuser d'utiliser le goto par principe est critiquable, refuser d'avoir deux fois la même ligne de code par principe est tout aussi critiquable : si la sémantique de ton programme est de répéter une même opération, tu la répète. Si tu veux la répéter de manière homogène, tu utilises des structures qui te le permette (for, while, ...), si tu veux la répéter de manière hétérogène alors tu conçoit chaque répétition différente, et si tu a des répétitions différentes au sein desquelles tu as des répétitions homogènes, alors tu combine. Je pense ce coup-ci à cela :
    Citation Envoyé par Obsidian Voir le message
    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.
    Oui c'est idiot : quand tu en viens à devoir répéter, tu factorise : si ça devient le genre d'opération que tu utilises à tout bout de champs, alors crée ta propre fonction avec callback/classe qui te permet d'exécuter une initialisation et une boucle qui répète. Si c'est une structure centrale, pourquoi ne pas y mettre un peu d'effort pour avoir quelque chose de solide qui te simplifie la tâche partout plutôt que de faire des copier-coller de codes, de surcroit avec des goto qui auront tôt fait de te faire aller sur le label d'une autre boucle sans faire sourciller le compilateur, parce que tu auras oublié de renommer correctement tes labels ?

    Si tu persistes à vouloir garder tes lignes exclusivement dans la boucle en utilisant un goto, c'est que tu continues à croire que deux codes sémantiquement différents (afficher un début de séquence VS afficher une suite de séquence) mais au code similaire (printf VS "-" + printf) sont sémantiquement identiques. Ce qui est sémantiquement identique, c'est la notion d'affichage d'un élément d'une séquence (le printf) qui a donc ses raisons de se retrouver dans une fonction qui lui est dédiée. Ta solution avec goto c'est typiquement le genre de code sémantiquement sale qui est considéré comme propre par un abus d'une autre règle : ne pas répéter le code. Ce n'est pas parce que j'utilise exactement le même code que ça correspond exactement à la même sémantique : si le contexte est suffisamment différent pour justifier que changer le code dans un cas (bug fixing, changement du cahier des charges ou que sais-je) n'implique pas de changer le code dans l'autre, alors on n'a aucune raison de factoriser le code, aussi similaires soient-ils syntaxiquement. Si on le fait, on prend le risque qu'un changement normal dans un cas implique un bug dans l'autre, parce qu'on aura mis en commun ce qui n'avait pas de raison de l'être (c'est pareil par coïncidence, et non par besoin). L'optimisation de la syntaxe, c'est le boulot du compilo, le boulot du programmeur c'est l'optimisation de la sémantique, que le compilo n'est pas capable de faire à notre place. Et c'est ça qui permet d'avoir un code lisible pour un autre dév sans avoir besoin de foutre des commentaires au sein du code (je parle pas d'entêtes, mais bien de commentaires qui redisent en français ce que le code dit en C/Java/...).

    Je note aussi une erreur rapide, probablement d'inattention :
    Citation Envoyé par Obsidian Voir le message
    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.
    Qu'il est censé appliquer la même fonction de la même manière, OK, mais qu'il est censé faire partie de la boucle, pas du tout ! C'est ta propre conception qui te dit que "c'est dans la boucle", mais ce n'est pas la seule valable. C'est qu'une unique phrase, donc je passe vite, mais ça me semble représentatif de pourquoi tu as du mal à concevoir que ton goto n'a rien de nécessaire : tu fais passer ta conception devant celle des autres en abusant d'un principe différent (réduire la répétition de code).

    Dans le cas de l'AFD :
    Citation Envoyé par Obsidian Voir le message
    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;
     
    …
    Là ça semble faire sens d'utiliser un goto, parce qu'on se fiche complètement du contexte autre que l'état courant et la condition : pour tel état+condition, tu vas là, point final. Mais ce n'est vrai que si dans ton programme, tout ce que tu as c'est cet automate et rien d'autre. Si ton programme vise à utiliser cet automate pour faire autre chose (il est rare qu'on lance un automate juste pour dire de le faire tourner) alors tes gotos te font prendre le risque de voyager hors du scope de ton automate. Pourquoi prendre ce risque ? Pourquoi ne pas prendre/faire une bibliothèque qui gère exclusivement les automates (e.g. en objet : des classes Etat, Transition, Automate et ce qu'il faut de fonctions haut niveau -et goto-free- pour les utiliser simplement) pour ensuite les utiliser dans ton programme en affichant clairement la sémantique (que sont tes états, tes transitions, etc.) plutôt que de les cacher dans des suites de if-goto ou même if-then ou switch à décrypter ? Tu y réponds presque :
    Citation Envoyé par Obsidian Voir le message
    … 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.
    Alors là soit. C'est statique, donc on le code en dur : on utilise un langage tout con fait pour encoder des AFD, inutile d'utiliser un langage aussi large que C ou Java pour quelque chose d'aussi spécifique. Si tu mélanges le code en dur de ton automate au code du reste de ton programme, alors tu ne poses aucune différence sémantique entre ton programme et ton AFD, et donc n'importe qui cherchant à déboguer ton code aura donc toutes les raisons du monde de transformer ton automate en autre chose qu'un automate, parce que de son point de vue il aura besoin d'introduire par exemple la notion de mémoire et donc, plutôt que d'utiliser un autre automate pour encoder cette mémoire, il préfèrera sauvegarder les X états précédemment visités ou intégrer des variables globales. Alors dis-moi, qu'est ce qui est important ? D'avoir un AFD ou d'avoir une simple structure de conditions que tu peux remanipuler (et donc représentable en AFD ou non selon les choix de conception) ? Dans le premier cas, ton code en dur est à jeter car non maintenable (c'est un bloc monolithique qui devrait être factorisé). Dans le second on se fiche pas mal d'avoir un AFD, et tous tes états/transitions peuvent être représentés différemment selon qu'on n'ait qu'une seule condition (attente jusqu'à condition satisfaite), plusieurs indépendantes (suite de if-elsif), plusieurs avec points communs (imbrications de if), etc. Bref, les cas d'écoles hyper particuliers c'est joli, mais ça fait pas des arguments.

    Citation Envoyé par Obsidian Voir le message
    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.
    Je dirais plutôt le contraire : à n'utiliser que pour se sortir d'une impasse, dans le sens où tant qu'on peut résoudre un problème sans sortir l'outil dangereux, il faut se prémunir de le sortir. Mais j'imagine que c'était l'idée de base, et dans ce sens je suis à moitié d'accord. L'analogie est pertinente, mais le contexte a une différence majeure : quand je fais la maintenance moi-même et quand je fais un script censé s'en charger. Quand je le fais à la main, une fois, je peux me permettre d'utiliser un outil dangereux, en en étant conscient et donc en apportant une attention particulière au moment où je l'utilise. Si je le fait plusieurs fois, je vais finir par augmenter le risque de faire des bêtises, et donc, sachant que je serai surement amener à recommencer, je vais chercher/faire un outil adapté à ce besoin ayant moins de risque. Quand je fais un programme, l'idée est la même, sauf qu'on saute directement à l'étape répétition. Se permettre d'utiliser des outils dangereux à ce niveau est donc se tirer une balle dans le pied dès le départ, car on s'ouvre toutes les portes pour qu'un problème surgisse un jour ou un autre, si une situation qu'on n'a pas prévu arrive (ce qui est toujours plausible, nous ne sommes que des humains après tout).

    Tout au mieux, ton outil dangereux mais bien pratique fournit une rustine efficace, mais pas une solution. Si tu ne reviens pas dessus pour faire une correction en bonne et due forme, tu ne fais que remplacer ton problème par un autre problème potentiel qui, si ça se trouve, sera encore plus dur à résoudre quand tu auras oublié d'où ça vient.

    Les break et continue, c'est sémantiquement plus précis, mais tout aussi dangereux. Un break est avantageusement remplacé par un return, clair et sans ambiguité : la boucle a un but précis, donc on la factorise dans une fonction au nom représentatif, et plutôt que d'avoir un break qui te dit que tu vas sauter certaines lignes et reprendre quelque part plus loin, tu as un return qui te dit que ta fonction est terminée, point barre. Tu ne commences pas à chercher midi à 14h, tu sors de la fonction. Et du point de vue de l'appelant, pas d'ambiguité non plus : tu appelles une fonction et quand elle a fini tu as ton résultat, peu importe comment elle le génère (c'est son boulot, pas celui de l'appelant), et tu poursuis à la ligne qui suit, pas quelque part plus loin. Et avec un peu de chance, ça te donnera une fonction prête à l'emploi si tu veux recommencer ailleurs, mais ça c'est l'argument marketing. Là je pense surtout à ce genre de fonctionnalité, avantageusement remplacée par un appel de fonction et le break par un return :
    Citation Envoyé par valkirys Voir le message
    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;
                }
            }
        }
    }
    Pour le principe :
    Citation Envoyé par Obsidian Voir le message
    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.
    Il y a aussi ce qu'on appelle le "sens commun", la "tradition", ou que sais-je : quand on apprend que quelque chose est plus risqué qu'avantageux, quelqu'un de bien attentionné s'arrangera pour que ça rentre dans le crane des générations suivantes. C'est de là qu'on pose des principes, méthodes, chartes, etc. Libre à chacun de les remettre en cause, mais s'ils sont là c'est qu'ils ont des raisons d'être. On peut reprocher à quelqu'un qu'il critique sur la seule base d'un principe plutôt que d'un argumentaire, mais pas qu'il choisit de s'appuyer sur un principe sans savoir ce qu'il y a derrière, surtout si celui-ci a fait ses preuves. Sinon l'éducation n'aurait aucun sens, on devrait toujours tout remettre en cause et on n'avancerai pas.

    Citation Envoyé par Obsidian Voir le message
    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.
    Il faut comparer ce qui est comparable. Là, tu parles d'une chaine en dur (rouleau d'imprimerie), qui n'aurait donc pas besoin d'un déphasage, juste d'avoir directement le bon contenu. Dans nos deux cas, on gère une variable (x) associée à une chaine en dur ("-"). Cela implique d'avoir 2 parties (mécaniques), la partie constante ("-") et la partie variable (x) qui seront chacune imprimée à la suite de l'autre. Dans le cas du goto, c'est équivalent à mettre une feuille de papier buvard lors de l'impression du premier tiret, de façon à ce que le premier élément vraiment imprimé soit x. Dans le cas de l'initialisation, ça revient à forcer l'impression du x d'abord, puis à lancer la machine. Perso, je préfère garder le contrôle plutôt que de devoir calculer précisément quand je dois mettre et retirer le buvard. Mes doigts s'en porteront mieux.

    Citation Envoyé par Obsidian Voir le message
    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.
    Ce que connait le compilo (i.e. ceux qui le font) c'est le modèle du langage. C'est à dire toute la partie syntaxique. Et eux ont vocation à la maitriser. Faire par soi-même de l'optimisation syntaxique revient à faire passer son orgueil devant la compétence de ceux qui ont fait le compilo. Là où le programmeur a tout le mérite, c'est quand il s'assure que ce qu'il écrit représente la sémantique qu'il a en tête : ici je suis censé faire la même chose que là, donc je vais utiliser la même fonction plutôt que de copier coller le code. Ici je veux afficher, tout comme là, mais bien que je peux faire exactement la même chose rien ne me dit que c'est censé être tout à fait pareil, donc je copie colle le code plutôt que de factoriser en une fonction commune. Comme ça si quelqu'un décide de changer l'un, on évite d'avoir un changement non voulu sur l'autre.
    Site perso
    Recommandations pour débattre sainement

    Références récurrentes :
    The Cambridge Handbook of Expertise and Expert Performance
    L’Art d’avoir toujours raison (ou ce qu'il faut éviter pour pas que je vous saute à la gorge {^_^})

  13. #13
    Membre à l'essai
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mai 2008
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Val de Marne (Île de France)

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

    Informations forums :
    Inscription : Mai 2008
    Messages : 4
    Par défaut
    C'est toujours très agréable de lire quelqu'un qui à eu le courage de décrire précisément son opinion juste avant d'avoir à le faire soi-même.

  14. #14
    Invité
    Invité(e)
    Par défaut
    Citation Envoyé par Matthieu Vergne Voir le message
    Les break et continue, c'est sémantiquement plus précis, mais tout aussi dangereux. Un break est avantageusement remplacé par un return, clair et sans ambiguité : la boucle a un but précis, donc on la factorise dans une fonction au nom représentatif, et plutôt que d'avoir un break qui te dit que tu vas sauter certaines lignes et reprendre quelque part plus loin, tu as un return qui te dit que ta fonction est terminée, point barre. Tu ne commences pas à chercher midi à 14h, tu sors de la fonction. Et du point de vue de l'appelant, pas d'ambiguité non plus : tu appelles une fonction et quand elle a fini tu as ton résultat, peu importe comment elle le génère (c'est son boulot, pas celui de l'appelant), et tu poursuis à la ligne qui suit, pas quelque part plus loin. Et avec un peu de chance, ça te donnera une fonction prête à l'emploi si tu veux recommencer ailleurs, mais ça c'est l'argument marketing. Là je pense surtout à ce genre de fonctionnalité, avantageusement remplacée par un appel de fonction et le break par un return.
    Pour le break c'est vrai mais le continue ne peut pas vraiment être remplacé par une fonction.

    Citation Envoyé par pvincent Voir le message
    L'exemple donné par Obsdian http://www.developpez.net/forums/d14...tion-autres/#4
    ne me semble pas très heureux: j'écrirai plutôt ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for (x = 1; x < 5; x++) {
        printf ("%d-",x);
     }
    printf ("%d" ,x++);
    mea culpa j'ai écrit une horreur un peu plus haut

  15. #15
    Membre éprouvé
    Avatar de Matthieu Vergne
    Homme Profil pro
    Consultant IT, chercheur IA indépendant
    Inscrit en
    Novembre 2011
    Messages
    2 307
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Consultant IT, chercheur IA indépendant
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2011
    Messages : 2 307
    Billets dans le blog
    3
    Par défaut
    Pour le continue, je pense que c'est plus une question d'organisation du code et d'abus de la règle "ne pas répéter le code". Je vais encore créer des fonctions, mais pour ceux qui voient l'usinagaz à 365 fonctions arriver, lisez quand même, j'y réponds en fin de post.

    Typiquement, tu as des choses du genre :
    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
    for(...) {
    // code commun
    if (cas1) {
     // code specifique 1
    } else if (cas2) {
     // code specifique 2
     continue;
    } else if (cas3) {
     // code specifique 3
    } else {
     // code specifique 4
     continue;
    }
    // code specifique 1&3
    }
    Les continue servent surtout à factoriser un code qui ne s'applique que dans certains cas, ici 1 et 3 et pas 2 et 4. Le problème, c'est que quand tu lis le code spécifique 1&3 tu ne sais pas que ça concerne uniquement les cas 1 et 3 sans bien lire tes if avant pour voir les continue (à moins que tu mettes des commentaires, ce qui est encore un effort supplémentaire). Du coup, niveau débogage/maintenabilité, c'est pas le top. Ensuite, parlons sémantique : si ce code 1&3 doit être exécuté dans le cas 1 et le cas 3, alors tu peux le mettre directement dans les cas correspondant :
    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
    16
    for(...) {
    // code commun
    if (cas1) {
     // code specifique 1
     // code specifique 1&3
    } else if (cas2) {
     // code specifique 2
     continue;
    } else if (cas3) {
     // code specifique 3
     // code specifique 1&3
    } else {
     // code specifique 4
     continue;
    }
    }
    Dès lors, c'est évident, les continue deviennent inutiles :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    for(...) {
    // code commun
    if (cas1) {
     // code specifique 1
     // code specifique 1&3
    } else if (cas2) {
     // code specifique 2
    } else if (cas3) {
     // code specifique 3
     // code specifique 1&3
    } else {
     // code specifique 4
    }
    }
    Maintenant, pourquoi préfère-t-on avoir les continue et le code factorisé ? Pour ne pas répéter le code. Très bien, alors pourquoi ne pas faire une fonction ?
    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
    16
    17
    18
    for(...) {
    // code commun
    if (cas1) {
     // code specifique 1
     fun();
    } else if (cas2) {
     // code specifique 2
    } else if (cas3) {
     // code specifique 3
     fun();
    } else {
     // code specifique 4
    }
    }
    ...
    fun() {
    // code specifique 1&3
    }
    Dans certain cas, ça peut être trop compliqué parce qu'on a des arguments à faire passer et parfois plusieurs résultats à récupérer. Sauf que de par mon expérience, ce genre de problèmes est rarement (pour ne pas dire jamais) difficile à résoudre : une classe faisant office de structure de données et hop, le tour est joué. Plutôt que d'utiliser 50 variables, on utilise 50 champs dans 1 structure, on passe la structure en argument de notre fonction et une fois exécutée la structure est modifiée en conséquence (ou on récupère une nouvelle version en retour de fonction) avec toutes les données nécessaires dedans. Selon le traitement qu'on fait, on préfèrera avoir plusieurs structures de données pour mieux séparer différentes sémantiques, voire avec des méthodes déjà intégrées à ces classes pour des traitement très spécifiques. Dès lors, on disposera d'un ensemble d'objets bien pratiques qui, si bien nommés, seront bien plus parlant qu'un ensemble de variables distribuées au milieu du code.

    Du coup, qu'on ait cette difficulté ou non, une fonction fait généralement très bien l'affaire et, contrairement au cas des continue qui nous font couper notre code en morceau, la fonction s'exécute bien à l'intérieur des cas qui en ont besoin, et non en dehors avec la nécessité de bien relire ce qui est au dessus pour bien comprendre quels cas sont concernés. Et surtout, du fait qu'on ne répète qu'une ligne, ça diminue grandement l'envie de factoriser ce code en utilisant des continue, ce qui nous permet de garder des cas atomiques qu'on pourra corriger à volonté.

    Une autre raison qui fait que c'est mauvais de factoriser avec des continue : ce n'est pas généralisable. Si j'ai un code commun à 1 et 3 et un autre commun à 2 et 4, je ne peux en factoriser que 1 en utilisant les continue, alors que les autres je suis obligé de répéter le code dans les deux cas concernés. Et si j'en ai d'autres encore, des cas avec des parties communes, pareil : je ne peux le faire que pour 1 factorisation, le reste je dois le répéter. Si je veux éviter ça, il me faut par exemple imbriquer mes if :
    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
    16
    17
    18
    for(...) {
    // code commun
    if (cas1 || cas3) {
     if (cas1) {
      // code specifique 1
     } else if (cas3) {
      // code specifique 3
     }
     // code specifique 1&3
    } else {
     if (cas2) {
      // code specifique 2
     } else {
      // code specifique 4
     }
     // code specifique 2&4
    }
    }
    Et là on voit bien que, bien que plus complexe que notre cas de base, on n'a pas besoin de continue. Mais la structure est plus complexe et on doit tester plusieurs fois nos cas. Des fois on peut optimiser mais ça peut être au détriment de la lisibilité. Et si on a vraiment une structure complexe, les imbrications à la chaine... Mais au moins c'est généralisable : on peut imbriquer autant que c'est nécessaire et, si on s'organise bien (conditions claires, des fonctions pour éviter d'avoir trop d'imbrications, etc.) on peut avoir quelque chose d'assez propre. Mais faut être bon pour y arriver (et motivé pour le relire derrière).

    Une autre façon, généralisable et qui évite une telle complexité, est d'utiliser les fonctions comme décrite au début :
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    for(...) {
    // code commun
    if (cas1) {
     // code specifique 1
     fun13();
    } else if (cas2) {
     // code specifique 2
     fun24();
    } else if (cas3) {
     // code specifique 3
     fun13();
    } else {
     // code specifique 4
     fun24();
    }
    }
    ...
    fun13() {
    // code specifique 1&3
    }
     
    fun24() {
    // code specifique 2&4
    }
    Encore une fois, on ne répète qu'une ligne, donc ça donne pas envie de tout factoriser (salement). Ensuite, même si on a des parties communes 1&2 et 3&4 par exemple, on peut les factoriser tout aussi facilement et lisiblement (avec les if imbriqués par contre, là ça devient vraiment galère). Et au final, en appliquant cette méthode, qu'est-ce qu'on a dans notre code ? Ni plus ni moins qu'une suite de cas précis ayant chacun leur processus, avec des parties communes bien en vues dans des fonctions spécialisées. Ca donne un code clair et modulaire.

    Et pour ceux qui lancent l'argument "ouais mais tu finis par avoir 300 fonctions dans une seule classe", je leur dirait que c'est encore qu'une question d'organisation de code : j'ai parlé de structures de données en début de post, et typiquement ces structures de données son liées à des processus spécifiques, processus qu'on retrouve généralement dans ces fonctions. Pour quelqu'un d'habitué à faire de l'objet, ça doit le faire tilter : tes fonctions fun13() et fun24(), c'est pas ici que tu vas les avoir, c'est dans les classes de tes structures de données. Si on as 50 fonctions dans une classe, c'est probablement parce qu'on y fait beaucoup de choses différentes. Je ne serai pas étonné qu'il y ait un paquet de concepts qui soit avantageusement représentés par des classes spécifiques, avec leurs fonctions, pour alléger significativement le code.

    Alors pourquoi on le fait pas et on utilise des continue ? Parce qu'on se limite très souvent à faire de l'optimisation syntaxique à l'arrache : je vois un code identique dans plusieurs cas, je factorise ce code là, sans même chercher à savoir si c'est censé être pareil (sémantiquement) ou si c'est juste une coïncidence (un copier-coller rapide et pratique qui devra probablement évolué différemment un jour ou l'autre). Après, peut-être que je verrai qu'il y en d'autres qui ont du code en commun, mais comme j'arriverai plus à le factoriser parce que les continue c'est pas généralisable, je me consolerai en me disant que j'en ai au moins factorisé 1 donc je n'ai rien à me reprocher. Et voilà comment on dort tranquille avec du code sale {^_^}.
    Site perso
    Recommandations pour débattre sainement

    Références récurrentes :
    The Cambridge Handbook of Expertise and Expert Performance
    L’Art d’avoir toujours raison (ou ce qu'il faut éviter pour pas que je vous saute à la gorge {^_^})

  16. #16
    Membre Expert
    Avatar de Pyramidev
    Homme Profil pro
    Tech Lead
    Inscrit en
    Avril 2016
    Messages
    1 513
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Tech Lead

    Informations forums :
    Inscription : Avril 2016
    Messages : 1 513
    Par défaut
    Je up car on parle de goto en C dans un autre fil.

    Comme certains l'ont déjà dit, le principal intérêt de goto en C, c'est de gérer les erreurs.

    Voici un exemple de code illustratif avec des goto :
    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
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
        if(code = allouer_A(/* paramètres */))
            return code;
     
        if(code = allouer_B(/* paramètres */))
            goto cleanup_A;
     
        if(code = allouer_C(/* paramètres */))
            goto cleanup_B;
     
        if(code = allouer_D(/* paramètres */))
            goto cleanup_C;
     
        code = faireDesTrucs(/* paramètres */);
     
        liberer_D();
     
    cleanup_C:
        liberer_C();
     
    cleanup_B:
        liberer_B();
     
    cleanup_A:
        liberer_A();
     
        return code;
    Bien sûr, on peut faire sans goto, mais ce serait moins élégant.
    Le code équivalent sans goto serait une pyramide de if :
    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
    16
    17
    18
        code = allouer_A(/* paramètres */);
        if(!code) {
            code = allouer_B(/* paramètres */);
            if(!code) {
                code = allouer_C(/* paramètres */);
                if(!code) {
                    code = allouer_D(/* paramètres */);
                    if(!code) {
                        code = faireDesTrucs(/* paramètres */);
                        liberer_D();
                    }
                    liberer_C();
                }
                liberer_B();
            }
            liberer_A();
        }
        return code;
    Ici, la pyramide a 5 niveaux d'indentation. Quand on passe à 10, c'est encore pire.

    Remarque : une autre possibilité est de déclarer plein de booléens pour savoir quelles ressources libérer, mais ce n'est pas mieux que les goto :
    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
    16
    17
    18
    19
        code = allouer_A(/* paramètres */)
        const bool faudra_liberer_A = !code;
     
        if(!code) code = allouer_B(/* paramètres */);
        const bool faudra_liberer_B = !code;
     
        if(!code) code = allouer_C(/* paramètres */);
        const bool faudra_liberer_C = !code;
     
        if(!code) code = allouer_D(/* paramètres */);
        const bool faudra_liberer_D = !code;
     
        if(!code) code = faireDesTrucs(/* paramètres */);
     
        if(faudra_liberer_D) liberer_D();
        if(faudra_liberer_C) liberer_C();
        if(faudra_liberer_B) liberer_B();
        if(faudra_liberer_A) liberer_A();
        return code;

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