10
votes

Différence entre goto et lancer?

Beaucoup de gens m'ont récemment accusé de mentionner un seul mot - "goto".
Cela me fait me demander, pourquoi il est considéré comme un mot aussi méchant.
Je suis au courant de plusieurs discussions précédentes sur le sujet, mais cela ne convainc pas - S ome de Les réponses expliquent simplement "c'est mauvais" ne même pas essayer d'expliquer et d'apporter raisons, non pertinentes pour Des langages de script comme php, imo .

Quoi qu'il en soit, je vais poser une question très particulière:
Comparons goto code> et lancer code>.
À mes deux, à mon avis, faites la même chose: éviter l'exécution d'une partie de la partie du code en fonction de certaines conditions.
Si oui - do jette code> ont les mêmes inconvénients que goto? (le cas échéant)?
Si non - whit est la différence alors. P>

Toute personne expérimentée suffisante, qui peut dire à la différence conceptuelle forte> fondamentale forte> entre les structures de code des deux extraits de code suivants?
En ce qui concerne ces extraits de code, pas "en théorie" ou "en général" ou "Voici une belle comique XKCD!".
Pourquoi le premier considéré comme brillant et ce dernier considéré comme le plus meurtrier des péchés? P>

#$a=1;
#$b=2;

/* SNIPPET #1 */

try {
    if (!isset($a)) {
      throw new Exception('$a is not set');
    }
    if (!isset($b)) {
      throw new Exception('$b is not set');
    }
    echo '$a + $b = '.($a + $b)."<br>\n";
} catch (Exception $e) {
    echo 'Caught exception: ', $e->getMessage(), "<br>\n";
}

/* SNIPPET #2 */

if (!isset($a)) { 
  $message = '$a is not set';
  goto end;
}
if (!isset($b)) {
  $message = '$b is not set';
  goto end;
}
echo '$a + $b = '.($a + $b)."<br>\n";

end:
if (!empty($message)) {
  echo 'Caught exception: ', $message, "<br>\n";
}


7 commentaires

goto n'a absolument rien à voir avec des exceptions ... "Mais les exceptions peuvent être mises en œuvre par goto!", alors peut si des déclarations, alors que, alors que des boucles, alors que les coroutines puissent alors appelle


En C #, l'iL émis est très différent. Par conséquent, fondamentalement, pour répondre à votre question, je pense que vous devriez comprendre ce que l'interprète PHP effectue lorsqu'il rencontre votre script pour commencer à répondre à cette question. Toutes les autres réponses codent du djihad. Ceci est pédant, mais dans votre exemple Goto, votre relevé d'écho est trompeuse à un autre dev alors qu'il n'y a pas d'exception à cette portée (donc pas de StackTrace, etc.).


Lecture associée: Joelonsoftware.com/items/2003/10/13.HTMLLe


Lecture partiellement liée (quelques paraptgraphes sur les exceptions) Joelonsoftware.com/articles/wrong.htmlled/a >


@Hejazzman Je ne vois pas ce que vous répondez, mais cela ressemble à il y a 8,5 ans :) Je peux dire que beaucoup de choses ont changé de nombreuses choses dans cette époque, et je suis sûr que d'autres choses ne l'ont pas fait.


@defines Certains post / commentaire peuvent être à partir de 8,5 ans, mais les gens le lisent aujourd'hui et, dans 5 et 10 ans, tant que le débordement de la pile est en place et sert cette réponse. Donc, la date d'affichage n'a pas d'importance, les postes sont vivaces et la discussion de commentaire est asynchrone sur l'éternité ...


@Hejazzman cool haricots!


11 Réponses :


7
votes

Je pense que vous devez poser la question dans l'inverse: pourquoi utiliseriez-vous goto lorsque des exceptions sont parfaitement adaptées à la situation? C'est quelles exceptions sont pour .

Vous pouvez aussi bien demander "pourquoi utiliser pendant , pour et fonctionne lorsque je peux tout aussi facilement utiliser goto


2 commentaires

Bon point. Du point de vue pratique, c'est une réponse parfaite. Mais je suis toujours intéressant dans la différence conceptuelle, le cas échéant. Surtout pourquoi il y a tellement des opinions polaires de toi deux.


Une grande partie de la haine pour "goto" vient des langues antérieures telles que Basic, où elle est utilisée conjointement avec un numéro de ligne (au lieu d'une étiquette). Ceci a été considéré comme une très mauvaise pratique car vos numéros de ligne modifient inévitablement lorsque vous apportez des modifications au fichier.



13
votes

Jeton / Catch est beaucoup plus flexible que GoTo: vous pouvez attraper des fonctions qui appellent le code lancant l'exception. De plus, les destructeurs requis sont appelés automatiquement.


1 commentaires

En outre, le lanceur d'exception n'a pas besoin de savoir quel code, le cas échéant, attirera l'exception.



5
votes

goto codes papier Le chemin d'exécution dans le code. Des exceptions d'autre part permettent de déterminer le chemin d'exécution à l'exécution.

Par exemple, supposons que vous disposiez d'une classe de base de données qui jette une exception sur l'erreur. Avec des exceptions, vous pouvez capturer cette erreur et faire quelque chose d'autre avant de raincre la page d'erreur (comme nettoyer les ressources allouées, ou "Rollback" de modifications préalables si vous utilisez un type de dB non transactionnel. Si vous avez utilisé un goto, vous ne voulez pas T avoir la chance de le faire, car le goto aurait rendu la page d'erreur.

N'oubliez pas que votre code est réutilisable et flexible. goto est l'antithèse des deux ...


0 commentaires

5
votes

Dans votre exemple, il n'y a effectivement aucune différence car vous vérifiez la condition d'erreur et que vous soulevez l'exception ou appelez goto code> si la condition échoue. Votre exemple peut être recodé pour supprimer le besoin de em> construire.

où les exceptions sont utiles utiles sont là où vous appelez des méthodes pouvant avoir un état d'erreur mais ne peut pas Poignez-la eux-mêmes car le pseudo code suivant illustre: P>

if (!isset($a))
{
    throw new Exception('$a is not set');
}
if (!isset($b))
{
    throw new Exception('$b is not set');
}


0 commentaires

2
votes

goto peut avoir un peu de performance boost comparant à lancer, car il ne crée aucune pile d'exception.


0 commentaires

2
votes

en termes pratiques, la différence entre vos deux segments de code est que vous devrez passer plus de temps à vous expliquer à d'autres programmeurs avec le code "goto".

Pour le meilleur ou pour le pire, la plupart des programmeurs pensent que vous devriez jamais utiliser un goto. Peut-être que vous pouvez prouver que cela n'est pas fondé et que votre code GOTO est le meilleur moyen de mettre en œuvre cette fonction. Malgré tout, vous devrez vous battre avec des collègues ou une autre personne avec qui vous collaborez pour les accepter.

Si vous travaillez par vous-même et personne ne verra votre code - utilisez ce que vous voulez. Mais si vous travaillez sur une équipe, le chemin du moindre résistance est parfois prudent.


4 commentaires

-1 Si vous renvoyez un code parfaitement valide (peu importe s'il y a un goto là-bas ou non), en raison de la résistance ignorante de vos collègues, je peux alors appeler beaucoup de noms, mais aucun de leur est prudent .


@John - alors pendant que vous vous battez avec vos collègues pour leur prouver que vous avez raison, je vais me passer et faire du travail. C'est le but. C'est prudent.


Passer à la recherche d'un meilleur endroit au travail serait prudent. On dirait que vous venez d'abandonner et de laisser les imbéciles gouverner la compagnie. Ce n'est pas prudent. L'homme plus sage donne et la stupidité règne le monde. Félicitations!


@John - sérieusement? Le réalisme n'abandonne pas. Un homme sage choisit ses batailles avec soin.



-3
votes

Ne pas utiliser non plus. Utilisez un "tandis que (1)" autour de la majeure partie de votre code et des relevés "Break" où vous souhaitez aller à la fin.

while(1)
{
    if (!isset($a)) { 
      $message = '$a is not set';
      break;
    }
    if (!isset($b)) {
      $message = '$b is not set';
      break;
    }

    echo '$a + $b = '.($a + $b)."<br>\n";
    break;
}

if (!empty($message)) {
  echo 'Caught exception: ', $message, "<br>\n";
}


4 commentaires

Est-ce que c'est censé être une réponse amusante?


De quelle manière est-ce une meilleure solution que d'utiliser goto?


@ Emilvikström: Ce n'est pas le cas. C'est " goto sans le goto ", et est encore pire car le code est maintenant sur l'intention. Quand on ressent la nécessité d'utiliser une structure de contrôle pour émuler goto - dans une langue que a elle, pas moins - ils ont raté tout le point de l'argument Contre goto en premier lieu.


Une meilleure alternative à "tandis que" est un do {/ * votre code cassable ici * /} tandis que (0). Il est exécuté une seule fois et a exactement le même avantage d'une "pause" facile à partir du flux de code



0
votes

Je ne déteste pas le goto autant que beaucoup, mais je pense que son principal problème est qu'il n'est pas limité à une "portée" spécifique. Avec toutes les autres structures de contrôle, vous savez où il commence et où il se termine. Une étiquette goto, d'autre part, peut être placée dans de nombreux endroits plus imprévisibles. Vous pouvez bien sûr chercher l'étiquette, mais il enfreint la lisibilité.

Bien sûr, tout est à la hauteur de son utilisation.


3 commentaires

Tort. Dans PHP Goto est limité à la fonction / fichier qu'il figure dans.


@Petah: Un fichier peut être très long.


Un fichier extrêmement long avec la rupture des fonctions est une mauvaise pratique de toute façon.



3
votes

goto code> est utile pour faire des choses comme ceci: xxx pré>

par opposition à ceci: p>

$matching_item = null;
foreach ($items as $item) {
    if ($item->is_match()) {
        $matching_item = $item;
        break;
    }
}
if ($matching_item === null) {
    $item = new Item();
}

render('find_item.php', $item);


2 commentaires

Avez-vous lu Knuth sur ce sujet? Parce que c'est l'un de ses exemples.


@Cwallenpoole, je n'ai jamais entendu parler de cela. Obtenu un lien?



2
votes

La chose qui est "erronée" est que goto Il peut implémenter de nombreux types de mécanismes de contrôle, pas seulement lancer , et a donc peu de structure inhérente. Pour cette raison, il existe plusieurs raisons pour lesquelles un programmeur de script serait intéressé à utiliser Alternatives Alternatives:

Tout d'abord, nous commençons à voir des scripts passer d'une option purement interprétée au code d'octet compilé. De bons exemples peuvent être trouvés n'importe où, tels que Python, Perl 6, Scala (Ascenseur), Clojure (Compojure). Même PHP a des compilateurs de code d'octet. Étant donné que goto a peu de structure, la compilation des mécanismes de contrôle ne peut pas se produire, ce qui constitue une perte de performance considérable, car les compilateurs modernes sont généralement très bons à cela. Pour lancer , les compilateurs peuvent commencer à supposer qu'une exception étant lancée n'est pas courante, elle optimisera donc le chemin de contrôle "normal" au coût d'un chemin de contrôle "anormal" moins optimal.

Même si vous n'avez pas de compilateur soufflé complet, les interprètes peuvent aider un programmeur considérablement plus que le programmateur utilise des mécanismes de contrôle qui ont plus de structure. Par exemple, pour Les blocs de boucle sont lexiquement scopés par le compilateur / interprète. Un programmeur peut donc utiliser ce cadre pour modulariser des morceaux de code. Sinon, avec goto vous êtes obligé de polluer l'espace de noms de variable.

En outre, si votre langue vous permet de déclarer des méthodes que lancer exceptions, le compilateur / interprète peut vous informer que vous n'avez pas géré toutes les exceptions possibles que les méthodes que vous êtes. L'appel peut expérimenter (similaire à lancers Java, si vous avez de l'expérience). Avec goto , le compilateur n'a aucune idée de ce que vous essayez de faire, de sorte que cela ne vous aidera pas pendant la compilation et les tests.

goto nécessite également le programmateur de récupérer de l'erreur. Imaginez si vous avez eu du code comme celui-ci (arraché et édité de vos extraits): xxx

Le problème ici est que le programmeur est nécessaire pour faire la bonne chose. S'il oublie Goto AfterError , il fonctionnera à travers la prochaine voie d'exception. Avec lancer les mécanismes sont un peu moins sujets d'erreur.

Enfin, mon expérience personnelle me fait n'aime pas la déclaration simplement parce qu'il n'est pas facile de lire. Lorsque j'essaie de comprendre un morceau de code avec quatre ou cinq étiquettes nommées une erreur d'erreur , échoue , réessaye , et ils sont Non situé à proximité du code offensant / exceptionnel, il peut s'agir d'un cauchemar pour démêler. Et si ce n'est pas facile à lire, alors même le programmeur essayant de revoir ce qu'il a fait il y a un an peut conduire à des erreurs.

comme un script à cette réponse, je ne crois pas " mal "est la bonne façon de décrire goto . Cela pourrait être venu de sensationnaliser le célèbre papier Dijkstra. "Puissant" peut être un meilleur terme, car cela implique que cela puisse faire à peu près tout, mais même les erreurs les plus simples rendent "mal" se transformer en "horriblement faux". Nous ne devrions pas interdire des outils parce qu'ils sont vraiment dangereux; Nous devrions mieux éduquer les gens sur leur danger et les laisser décider.


1 commentaires

Mettez un autre moyen: goto est le couteau suisse de contrôle de flux. Il (avec si ) peut réimplémenter chaque structure de contrôle dans la langue (et, généralement, au niveau de la langue de la machine; les processeurs rarement (par exemple :) faire foreach nativement ). Mais ce pouvoir vient avec un coût: goto est trop générique pour exprimer son intention. Comme un couteau d'armée suisse typiquement suce comme un tournevis, peut ouvrir ou souvent même un couteau, goto est inférieur à des structures plus spécifiques et plus expressives - et ne doit être utilisée que si un événement existant ne 't répondre à vos besoins sans quelques superbes.



3
votes

Puisque personne n'a encore fourni une réponse à cette question que l'OP est jugé acceptable, je vais jeter mon chapeau dans la bague.

... la différence fondamentale et conceptuelle entre les structures de code des deux extraits de code suivants?

Il n'y a pas de différence conceptuelle entre les deux extraits de code que vous avez fournis. Dans les deux cas, une condition est testée et si elle est remplie, un message est lancé à une autre partie du programme de manipulation.

Pourquoi le premier considéré comme brillant et ce dernier envisagé être le plus mortel des péchés?

Merci Col. Shrapnel pour ouvrir la porte au rant suivant.

Chaque construction de programmation contient le potentiel d'abus. La persécution dogmatique de goto me rappelle le ressemblant à Bashing de PHP. PHP conduit à de mauvaises pratiques de programmation. comparé à: goto conduit au code spaghetti.

Mettez simplement: goto est "mal" car Edsger Dijkstra a dit et Niklaus Wirth lui donna son sceau d'approbation. ;-p

Pour votre jouissance de lecture: http://fr.wikipedia.org/wiki/goto

Probablement la critique la plus célèbre de Goto est une lettre de 1968 par Edsger Dijkstra a appelé aller à la déclaration jugée nocive . Dans cette lettre Dijkstra a fait valoir que des déclarations goto illimitées devraient être abolies des langages de niveau supérieur parce qu'ils ont compliqué la tâche de analyser et vérifier l'exactitude des programmes (en particulier ceux impliquant des boucles). Un point de vue alternatif est présenté dans La programmation structurée de Donald Knuth avec Aller à des déclarations qui analyse de nombreuses tâches de programmation courantes et découvre que dans certains d'entre eux Goto est la construction de langues optimale à utiliser.

Ça continue à dire,

Certains programmeurs, tels que Linux Kernel Designer et Coder Linus Torvalds ou ingénieur logiciel et auteure de livre Steve McConnell objet au point de vue de Dijkstra, indiquant que les gotos peuvent être utiles caractéristique linguistique, amélioration de la vitesse du programme, de la taille et de la clarté du code, mais seulement lorsqu'il est utilisé de manière raisonnable par une manière relativement sensible programmeur.

Cela dit, je n'ai personnellement pas trouvé d'usage pratique pour aller depuis le commodore Basic, mais ce n'est ni ici ni là. : -)


1 commentaires

Comme je me souviens de l'histoire, Dijkstra a simplement été exprimée (forte et assez valable à l'époque) concernant le potentiel d'abus (son document était intitulé à l'origine «un cas contre le aller à instruction»). WIRTH a pris l'idée et courut avec elle, en le prenant aux niveaux dogmatiques.