Quand l'évaluation des courts-circuits est-elle mauvaise?


12

Pour être un peu plus clair, je dirai que j'ai passé beaucoup de temps avec différentes langues. Mais jusqu'à présent, cela a été soit il l'utilisera tout le temps, soit il ne le supportera pas du tout.

Maintenant, le travail me fait commencer sur des projets qui nécessitent VB.net et je vois qu'il fournit les deux sens en termes de AND et ANDALSO . Le premier ne court-circuite pas et le second le fait.

Cela me conduit donc à me demander pourquoi? Comme le configurer comme celui-ci semble impliquer qu'il arriverait assez souvent que l'on veuille changer de mode. Mais je ne peux penser à aucune situation où ce serait une mauvaise chose d'utiliser le court-circuit .

Je sais que cela pourrait très bien devenir plus une option, donc si j'ai besoin de mettre cela à un autre endroit, dites-moi simplement où.

Bien que j'espère qu'il y ait au moins une réponse officielle, à savoir pourquoi avoir les deux options serait mieux que de toujours faire un court-circuit , quand il est disponible.



Réponses:


5

Certains termes d'une expression logique peuvent avoir des effets secondaires. Il est parfois nécessaire de s'assurer que tous les effets secondaires se produisent dans l'ordre indiqué, et aucun n'est ignoré et c'est le résultat de l'évaluation qui guide la logique:

if not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Dans d'autres cas, vous ne souhaitez évaluer aucun des termes restants si une évaluation antérieure renvoie faux.

if IsAirborne() and not (PushAirPlane(thrust) and TurnAirplane(vector)), SimulateCrash(severity)

Certains soutiendront / auront fait valoir que le fait de se fier au comportement de court-circuit dans le deuxième exemple est une mauvaise forme, mais cela revient au style de codage et aux systèmes de croyance. Il existe de nombreux très bons morceaux de code dans le monde qui dépendent de presque toutes les fonctionnalités d'un langage, et c'est exactement ainsi.

ANDALSO de VB est net et semble être une tentative de rendre la pratique plus acceptable.

Comme JimmyJames le souligne dans sa réponse, il peut y avoir des implications mesurables en termes de performances autour de l'évaluation des courts-circuits. Les langages qui ne fournissent pas le mécanisme évaluent toujours chaque terme de l'expression, tandis que ceux qui le fournissent peuvent générer des instructions de branche supplémentaires. Quoi qu'il en soit, cela dépend beaucoup du nombre d'étapes de traitement nécessaires pour évaluer chacun des termes et également des architectures du compilateur et du processeur. Normalement, vous ne vous souciez pas de ces choses jusqu'à ce que vous ayez un goulot d'étranglement mesuré dans le code et que vous deviez trouver un moyen de l'atténuer. Toute règle de faire ou de ne pas autoriser l'évaluation de court-circuit dans votre code aurait à peu près la même chance de ralentir le code et d'optimiser tôt peut être une perte de temps totale, alors mesurez toujours, puis optimisez.


4
Bien que factuellement correct, ce n'est pas un excellent design.
Robert Harvey

2
@RobertHarvey, je ne peux pas écrire un système de contrôle qui n'a pas d'effets secondaires et je ne peux pas contrôler le système correctement si je ne réagis pas aux résultats. En d'autres termes, surmontez-le;).
jwdonahue

7
Non, mais vous pouvez affecter les résultats de ces fonctions d'effet secondaire à des variables booléennes, vérifier ces variables dans votre ifcondition et toujours court-circuiter. Je suis d'accord que c'est, à certains égards, une distinction stylistique, mais elle a le mérite de rendre les choses claires comme du cristal.
Robert Harvey

3
@jwdonahue Il est normal d'utiliser des "gros mots" si le risque de confusion est faible. Le risque de confusion et de manquer des nuances particulières d'un bloc de code comme celui-ci est extrêmement élevé et peut être catastrophique pour la logique. Il n'est jamais bon de faire réfléchir très fort le développeur en lecture.
jpmc26

5
"Certains termes dans une expression logique peuvent avoir des effets secondaires" - Bien que cette déclaration liminaire soit correcte, je pense que cette réponse échoue en ne soulignant pas que compter sur les effets secondaires est mauvais . Bien pire, en fait, que de s'appuyer sur une évaluation de court-circuit pour éviter des évaluations parasites. Ce que cette réponse suggère peut être une mauvaise forme.
2018 à 9h01

20

Apparemment, votre question n'est pas de savoir si les courts-circuits sont bons ou mauvais en général, mais pourquoi VB.NET fournit des opérateurs avec et sans. Dans cet esprit, la réponse à

quand l'évaluation des courts-circuits est-elle mauvaise?

est tout simplement: quand il viole la compatibilité descendante .

Ok, vous pouvez maintenant dire que VB.NET n'est pas très rétrocompatible avec les anciens VB6 ou VBA, mais au moins certaines parties du langage le sont. La décision de Microsoft de conserver les anciennes sémantiques ET et OU (sans court-circuit) a rendu une énorme catégorie d'erreurs moins susceptible de se produire lors du portage d'anciens programmes VB sur VB.NET.

D'un autre côté, les concepteurs du langage VB.NET ont probablement partagé votre opinion sur le fait que le court-circuit était une bonne chose. Si je me souviens bien, les premières versions préliminaires de VB.NET fournissaient aux opérateurs AND ou OR un court-circuit, mais les commentaires des développeurs devaient être si mauvais que MS retire cette décision avant l'apparition de VB.NET 1.0. Les concepteurs ont donc décidé de l'implémenter en termes de nouveaux mots clés ANDALSOet en ORELSEtant que compromis entre la compatibilité descendante et l'utilité.

À mon humble avis, c'était une bonne décision. J'ai dû porter plusieurs programmes plus anciens au cours de la dernière décennie, et le fait de ne pas avoir à effectuer une analyse d'impact lourde pour chaque expression logique, y compris AND et / ou OR (jeu de mots), a rendu cette tâche beaucoup plus facile et plus économique. D'un autre côté, chaque fois que je dois écrire une nouvelle expression logique dans VB.NET, mon choix par défaut pour les opérateurs sont les formes de court-circuit, c'est à cela que je suis habitué en C, C ++, C # etc, et cela permet moi d'écrire plusieurs idiomes sous une forme plus concise (même si ANDALSO a besoin de 4 caractères de plus pour taper).

Si vous n'êtes pas convaincu, je vous recommande de lire le grand article de Joel Spolsky sur les casques martiens , qui explique pourquoi les premières décisions de conception dans le développement de logiciels ne peuvent pas être facilement révoquées après que le composant ou le langage ou l'API en jeu a atteint une base d'utilisateurs d'une certaine taille .


Ok, cela se qualifie comme une diatribe et le lien vers les casques martiens ne semble pas du tout lié.
jwdonahue

6
@jwdonahue: Je n'ai aucune idée pourquoi vous pensez que c'est une diatribe, bien au contraire. Et l'article sur les casques martiens explique pourquoi certaines décisions de conception dans le développement de logiciels prises il y a plusieurs décennies ne peuvent pas être facilement révoquées après que le composant ou le langage ou l'API en jeu a atteint une base d'utilisateurs d'une certaine taille. L'analogie n'est-elle pas si difficile à saisir? VB6 était très populaire dans le passé, et je suis sûr que des centaines de milliers d'entreprises dans le monde ont toujours des applications critiques en cours d'exécution en VB6 ou VBA.
Doc Brown

Je ne vois pas vraiment comment l'article "Martian headests" s'intègre vraiment. Ce qui est nécessaire pour assurer l'interopérabilité entre les X et les Y (par exemple, les écrous et les boulons) est d'avoir des normes distinctes pour X et Y, de sorte qu'un écrou dans le pire des cas puisse accueillir un boulon légèrement pire que celui spécifié, et vice versa. On devrait essayer d'écrire les spécifications afin d'éviter de rendre les écrous ou les boulons inutilement chers, ou d'avoir une quantité inutile de pente entre les écrous et les boulons, mais la spécification des deux moitiés séparément permet d'assurer l'interopérabilité de manière beaucoup plus fiable que d'essayer d'en avoir une servir des deux côtés.
supercat

3
@supercat: il s'agit d'avoir déjà des milliards d'écrous (ou des lignes de code VB6) existants et en cours d'utilisation, et maintenant les boulons (ou dans ce cas le compilateur VB) seront remplacés par une nouvelle génération. Si les écrous existants ne s'adaptent qu'aux boulons non métriques, il n'est pas économique de fabriquer le système métrique de boulons plus récent uniquement.
Doc Brown

tl; dr: VB est un dialecte de BASIC, une langue datant de 1964, et en BASIC l' Andopération ne court-circuite pas, ni dans SQL (1974), ni FORTRAN (1956), ni Pascal (1970).
Ben

3

quand l'évaluation à court terme est-elle mauvaise?

Ils deviennent mauvais , dès que vous commencez à compter sur les effets secondaires des expressions que vous prévoyez d'exécuter dans l'évaluation d'un résultat global booléen.


1

Mise en garde : C'est un peu ésotérique dans la mesure où dans presque tous les cas, les développeurs ne devraient pas s'en inquiéter. Mais ... il peut y avoir un impact sur les performances en raison de l'évaluation conditionnelle car elle crée une ramification lors de l'exécution. Un fonctionnement sans court-circuit ne dérive pas et est plus prévisible.

La raison pour laquelle cela importe rarement est que le coût est généralement faible et également généralement compensé par le coût de l'évaluation de la deuxième (ou troisième, etc.) condition. Cela n'aura jamais d'importance que dans les routines de calcul coûteux lorsque des performances élevées sont requises et cela pourrait ne pas être important non plus.


Je pense que vous ne pouvez optimiser une déclaration logique que jusqu'à présent, vous devez finalement prendre des branches.
jwdonahue

@jwdonahue Je ne comprends pas votre point. Pardon.
JimmyJames

Nous parlons ici de logique combinatoire. Évaluation de court-circuit ou non, vous avez un ou plusieurs termes qui doivent être évalués en fonction du résultat d'un terme antérieur. Par conséquent, la ramification est impliquée.
jwdonahue

1
@jwdonahue Bien sûr, mais chaque court-circuit est une branche supplémentaire. Dans certains scénarios, l'exécution de deux expressions (par exemple) est plus rapide que la vérification du résultat de la première avant d'exécuter la seconde, même si c'est souvent le cas que la seconde n'est pas pertinente. Encore une fois, cela est rarement important. Le cas que quelqu'un m'a fait pour cela était pour des choses comme la multiplication matricielle où vous avez beaucoup d'évaluations simples.
JimmyJames

1
J'ai mis à jour ma réponse avec crédit.
jwdonahue

0

Pascal n'a pas défini si ET et OU utilisent ou non l'évaluation des courts-circuits, vous donnant le pire des deux mondes.

C et C ++ ont des opérations au niveau du bit & et | ce qui en pratique vous donne des opérations sans court-circuit. Et les compilateurs sont libres d'évaluer comme bon leur semble si cela ne fait pas de différence observable.


@Deduplicator: Comme indiqué, Pascal n'a pas défini si ET / OU utiliser l'évaluation de court-circuit. Cela signifie "ne pas savoir".
supercat
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.