Je prends un cours sur les structures de données intermédiaires comme condition préalable à l'entrée au programme CS MS dans une université dont tout le monde en Amérique a entendu parler. Une ligne de code écrite en classe a attiré mon attention:
if (a > 33 | b++ < 54) {...}
Cela ne passerait pas un examen du code sur mon lieu de travail. Si vous avez écrit un code comme celui-ci dans une interview, ce serait une grève importante contre vous. (En plus d'être un conditionnel avec des effets secondaires, il est intelligent au détriment de la clarté.)
En fait, je n'ai jamais vu de conditionnel avec des effets secondaires, et Google ne se présente pas beaucoup non plus. Un autre élève est resté derrière après le cours pour poser des questions à ce sujet également, donc je ne suis pas le seul à penser que c'était bizarre. Mais le professeur était assez catégorique qu'il s'agissait d'un code acceptable et qu'il écrirait quelque chose comme ça au travail. (Son travail de FT est en tant que SWE principal dans une entreprise dont vous avez tous entendu parler.)
Je ne peux pas imaginer un monde dans lequel cette ligne de code serait jamais acceptable, encore moins souhaitable. Ai-je tort? Est-ce correct? Qu'en est-il du cas plus général: les conditions avec effets secondaires? Est-ce que ça va?
Réponses:
Il y a un effet secondaire semi-conditionnel auquel je pense que c'est correct:
while(iter.MoveNext())
Cela dit, je pense que cela tombe principalement dans la catégorie " jamais un très gros qualificatif". Je peux penser à quelques rares cas où je l'ai vu être acceptable, mais en général c'est vil et à éviter.
Je ne peux pas non plus penser à un scénario où cette ligne particulière serait acceptable, mais je ne peux pas non plus penser à un scénario où cette ligne particulière serait utile , il est donc difficile d'imaginer le contexte dans lequel elle se trouve.
la source
while(v = *p++)
analyses de style C / C ++ à travers un tableau terminé par zéro (par exemple la chaîne C) sont assez courantes et largement acceptées.while(c = input.read() != '\n')
comme raisonnablement idiomatiques.Dans mon monde, une lecture à partir de la mémoire peut être considérée comme un effet secondaire (par exemple IO mappé en mémoire).
Maintenant, considérez ce qui suit:
Et comparer à:
L'évitement de l'effet secondaire (la lecture) dans la condition a-t-il aidé à la lisibilité; ou a-t-il simplement dupliqué du code et ajouté de l'encombrement?
Ce n'est pas OK pour qu'une condition ait des effets secondaires (si cela rend le code moins lisible) et c'est aussi OK pour une condition d'avoir des effets secondaires (si cela rend le code plus lisible). Le facteur clé est la "lisibilité". Tout le reste est des règles créées par des imbéciles dans une tentative malavisée d'améliorer la lisibilité (tout en ayant souvent l'effet inverse).
la source
Comme toujours avec de telles questions, c'est une question de degré. S'il y avait une preuve sans équivoque que tout effet secondaire dans une
if
expression toujours conduit à un code pire, alors il ne serait pas légal de créer ces expressions. Les concepteurs de langage peuvent être des humains idéosyncratiques et faillibles, mais ils ne sont pas si stupides.Cela dit, quels sont les exemples d'effets secondaires justifiés dans un
if
? Par exemple, supposons que vous êtes légalement tenu d'enregistrer tous les accès à la propriétéP
d'une entitéE
à des fins d'audit. (Imaginez que vous travaillez dans une usine d'enrichissement d'uranium, et qu'il existe des contrôles juridiques très stricts sur ce que votre code est autorisé à faire et comment il est censé le faire.) Ensuite, tout ceif
qui vérifie cette propriété entraînera l'effet secondaire de la journal d'audit en cours d'extension.C'est une préoccupation transversale assez claire, cela n'affecte pas votre raisonnement sur l'état du programme (beaucoup), et vous pouvez l'implémenter de sorte qu'il soit complètement invisible et sans distraction lorsque vous passez en revue la ligne avec le
if
(caché dans l'accesseur, ou encore mieux via AOP). Je dirais que c'est un cas assez clair d'un effet secondaire qui n'est pas un problème. Des situations similaires peuvent être imaginées lorsque vous souhaitez simplement compter les exécutions de branches à des fins de profilage, etc.Plus ces circonstances atténuantes disparaissent, plus la construction deviendra étrangère. Si un type de boucle particulier (par exemple
if((c = getc()) == 'x') { quit(); }
est bien connu et accepté par la communauté linguistique, alors c'est beaucoup moins un problème que lorsque vous l'inventez spontanément, etc. Votre exemple de ligne ne correspond pas à cette norme, mais je pourrais imaginer beaucoup, beaucoup plus horribles que je ne taperai même pas, ils sont tellement horribles.la source
Bien que le code soit vraiment mauvais, il a l'avantage d'être plus simple (et peut-être plus rapide si vous n'avez pas un bon compilateur d'optimisation) que son équivalent
if (a > 33 | b < 54) {b++; ...} else b++;
mais bien sûr il est possible de l'optimiser pour les suivants (mais attention! celui-ci a un comportement différent en cas de débordement!):
b++; if (a > 33 | b < 53) {...}
la source