Disons que j'ai une condition booléenne a AND b OR c AND d
et j'utilise un langage où AND
a un ordre de fonctionnement plus élevé que OR
. Je pourrais écrire cette ligne de code:
If (a AND b) OR (c AND d) Then ...
Mais vraiment, cela équivaut à:
If a AND b OR c AND d Then ...
Y a-t-il des arguments pour ou contre l'inclusion des parenthèses superflues? L'expérience pratique suggère-t-elle qu'il vaut la peine de les inclure pour plus de lisibilité? Ou est-ce un signe qu'un développeur doit vraiment s'asseoir et prendre confiance dans les bases de son langage?
Les bons développeurs s'efforcent d'écrire du code qui est clair et correct . Les parenthèses dans les conditions, même si elles ne sont pas strictement requises, aident aux deux.
Quant à clarté, pensez à des parenthèses comme des commentaires dans le code: ils ne sont pas strictement nécessaires, et en théorie, un développeur compétent devrait être capable de comprendre le code sans eux. Et pourtant, ces indices sont extrêmement utiles, car:
De plus, des parenthèses supplémentaires, tout comme les indentations, les espaces blancs et d'autres normes de style, aident à organiser visuellement le code de manière logique.
Quant à exactitude, les conditions sans parenthèses sont une recette pour des erreurs stupides. Quand ils se produisent, ils peuvent être des bogues difficiles à trouver, car souvent une condition incorrecte se comportera correctement la plupart du temps et échouera occasionnellement.
Et même si vous comprenez bien, la prochaine personne à travailler sur votre code ne le fera peut-être pas, soit en ajoutant des erreurs à l'expression, soit en comprenant mal votre logique et en ajoutant ainsi des erreurs ailleurs (comme LarsH le fait remarquer à juste titre).
J'utilise toujours des parenthèses pour les expressions qui combinent and
et or
(et aussi pour les opérations arithmétiques avec des problèmes de priorité similaires).
Peu importe que vous ayez confiance en votre maîtrise de la langue. Ce qui importe le plus, c'est la compréhension du langage du n00b qui vous suit.
Écrivez votre code de la manière la plus claire et la plus claire possible. Des parenthèses supplémentaires aident souvent (mais pas toujours). Mettre une seule instruction sur une ligne aide souvent. La cohérence du style de codage est souvent utile.
Il y a une telle chose comme trop de parenthèses, mais c'est une de ces situations où vous n'aurez pas besoin de conseils - vous le saurez quand vous le verrez. À ce stade, refactorisez votre code pour réduire la complexité de l'instruction plutôt que de supprimer les parenthèses.
Vous devez toujours utiliser des parenthèses ... vous ne contrôlez pas l'ordre de priorité ... le développeur du compilateur le fait. Voici une histoire qui m'est arrivée sur la non utilisation des parenthèses. Cela a touché des centaines de personnes sur une période de deux semaines.
J'ai hérité d'une application de cadre principal. Un jour, hors du bleu clair, il a cessé de fonctionner. C'est ça ... pouf ça vient de s'arrêter.
Mon travail consistait à le faire fonctionner le plus rapidement possible. Le code source n'avait pas été modifié depuis deux ans, mais tout à coup, il venait de s'arrêter. J'ai essayé de compiler le code et il s'est cassé sur la ligne XX. J'ai regardé la ligne XX et je ne pouvais pas dire ce qui ferait casser la ligne XX. J'ai demandé les spécifications détaillées de cette application et il n'y en avait pas. La ligne XX n'était pas la coupable.
J'ai imprimé le code et j'ai commencé à le réviser de haut en bas. J'ai commencé à créer un organigramme de ce qui se passait. Le code était si compliqué que je pouvais à peine le comprendre. J'ai renoncé à essayer de l'organigramme. J'avais peur de faire des changements sans savoir comment ce changement affecterait le reste du processus, d'autant plus que je n'avais aucun détail sur ce que faisait l'application ou où elle se trouvait dans la chaîne de dépendance.
J'ai donc décidé de commencer en haut du code source et d'ajouter des freins blancs et de ligne pour rendre le code plus lisible. J'ai remarqué, dans certains cas, qu'il y avait des conditions combinant AND
et OR
et qu'il n'était pas clairement possible de distinguer quelles données étaient AND
éd et quelles données étaient OR
ed. J'ai donc commencé à mettre des parenthèses autour des conditions AND
et OR
pour les rendre plus lisibles.
Alors que je descendais lentement pour le nettoyer, je sauvegardais périodiquement mon travail. À un moment donné, j'ai essayé de compiler le code et une chose étrange s'est produite. L'erreur avait dépassé la ligne de code d'origine et était maintenant plus bas. J'ai donc continué, en séparant les conditions AND
et OR
avec des parens. Quand j'ai fini de le nettoyer, ça a marché. Allez comprendre.
J'ai alors décidé de visiter le magasin des opérations et de leur demander s'ils avaient récemment installé de nouveaux composants sur le châssis principal. Ils ont dit oui, nous avons récemment mis à jour le compilateur. Hmmmm.
Il s'avère que l'ancien compilateur évaluait l'expression de gauche à droite. La nouvelle version du compilateur a également évalué les expressions de gauche à droite mais le code ambigu, ce qui signifie que la combinaison peu claire de AND
et OR
n'a pas pu être résolue.
Leçon que j'en ai tirée ... TOUJOURS, TOUJOURS, TOUJOURS utiliser des parens pour séparer les conditions AND
et OR
lorsqu'elles sont utilisées conjointement.
IF Product = 191 OR Product = 193 AND Model = "ABC" OR Product = 201 OR Product = 202 AND Model = "DEF" ...
(Code jonché de plusieurs d'entre eux)
Ceci est une version simplifiée de ce que j'ai rencontré. Il y avait aussi d'autres conditions avec des déclarations de logique booléenne composées.
Je me souviens l'avoir poussé à:IF ((Product = 191 OR Product = 193) AND Model = "ABC") OR ((Product = 201 OR Product = 202) AND Model = "DEF") ...
Je n'ai pas pu le réécrire car il n'y avait pas de spécifications. L'auteur original était parti depuis longtemps. Je me souviens d'une pression intense. Un cargo entier a été bloqué dans le port et n'a pas pu être déchargé car ce petit programme n'a pas fonctionné. Pas d'avertissement. Aucune modification du code source. Il ne m'est apparu que de demander aux opérations réseau s'ils avaient modifié quoi que ce soit après avoir remarqué que l'ajout de parens avait modifié les erreurs.
Oui, s'il y a un mélange "et" et "ou".
Aussi une bonne idée de () ce qui est logiquement une vérification.
Bien que le mieux soit d'utiliser des fonctions de prédicat bien nommées et d'expulser la plupart des vérifications et conditions, laissant si simple et lisible.
Les parenthèses sont sémantiquement redondantes, donc le compilateur ne s'en soucie pas, mais c'est un hareng rouge - la vraie préoccupation est la lisibilité et la compréhension du programmeur.
Je vais prendre la position radicale ici et donner un "non" chaleureux aux parenthèses dans a AND b OR c AND d
. Chaque programmeur doit savoir par cœur que la priorité dans les expressions booléennes va PAS> ET> OU , tout comme se souvenir - Veuillez excuser ma chère tante Sally pour les expressions algébriques. La ponctuation redondante ajoute juste un encombrement visuel la plupart du temps dans le code sans aucun avantage sur la lisibilité du programmeur.
De plus, si vous utilisez toujours des parenthèses dans les expressions logiques et algébriques, vous abandonnez la possibilité de les utiliser comme marqueur de "quelque chose de délicat se passe ici - attention!" Autrement dit, dans les cas où vous souhaitez remplacer priorité par défaut et faire évaluer l'addition avant la multiplication, ou OR avant ET, les parenthèses sont un drapeau rouge de Nice pour le prochain programmeur. Trop en utiliser quand ils ne sont pas nécessaires, et vous devenez le Boy Who Cried Wolf.
Je ferais une exception pour tout ce qui est en dehors du domaine de l'algèbre (booléen ou non), comme les expressions de pointeur en C, où quelque chose de plus compliqué que les idiomes standard comme *p++
ou p = p->next
devrait probablement être entre parenthèses pour garder le déréférencement et l'arithmétique droits. Et, bien sûr, rien de tout cela ne s'applique aux langages comme LISP, Forth ou Smalltalk qui utilisent une certaine forme de notation polonaise pour les expressions; mais pour la majorité des langues dominantes, la priorité logique et arithmétique est totalement standardisée.
Comme je le vois:
OUI Avantages:
OUI Inconvénients:
NON Avantages:
NON Inconvénients:
En C #, la multiplication et la division ont priorité sur l'addition et la soustraction.
Pourtant, StyleCop, un outil qui applique un style commun à travers la base de code avec un objectif supplémentaire pour atténuer le risque de bogues introduits par du code qui peut ne pas être suffisamment clair, a le règle SA1407 . Cette règle produira un avertissement avec un morceau de code comme celui-ci:
var a = 1 + 2 * 3;
Il est clair que le résultat est 7
et pas 9
, mais quand même, StyleCop suggère de mettre des parenthèses:
var a = 1 + (2 * 3);
Dans votre cas particulier, il existe une priorité de AND par rapport à OR dans la langue particulière que vous utilisez.
Ce n'est pas ainsi que chaque langue se comporte. Beaucoup d'autres traitent ET et OR également.
En tant que développeur qui travaille principalement avec C #, quand j'ai vu votre question la première fois et lu le morceau de code sans lire ce que vous avez écrit auparavant, ma première tentation a été de commenter que les deux expressions ne sont pas les mêmes. J'espère que j'ai lu toute la question avant de commenter.
Cette particularité et le risque que certains développeurs croient que AND et OR ont la même priorité, il est encore plus important d'ajouter des parenthèses.
N'écrivez pas de code dans le but de montrer que vous êtes intelligent. Écrivez du code dans un but de lisibilité, y compris par des personnes qui ne connaissent peut-être pas tous les aspects de la langue.
Y a-t-il des arguments pour ou contre l'inclusion des parenthèses superflues? L'expérience pratique suggère-t-elle qu'il vaut la peine de les inclure pour plus de lisibilité? Ou est-ce un signe qu'un développeur doit vraiment s'asseoir et prendre confiance dans les bases de son langage?
Si personne d'autre ne devait jamais revoir mon code, je ne pense pas que je m'en soucierais.
Mais, d'après mon expérience:
Je fais presque toujours cela parce que j'ai confiance en ma capacité à lire rapidement et à ne pas faire beaucoup plus de petites erreurs avec des parens que rien d'autre.
Dans votre cas, je ferais presque certainement quelque chose comme:
if (a AND b) then ab = true
if (c AND d) then cd = true
If (ab OR cd) Then ...
Oui, c'est plus de code. Oui, je peux faire à la place des opérateurs booléens sophistiqués. Non, je n'aime pas la chance lors de l'écrémage de code 1+ ans dans le futur, j'ai mal lu les opérateurs booléens de fantaisie. Et si j'écrivais du code dans une langue qui avait une priorité ET/OU différente et que je devais revenir en arrière pour résoudre ce problème? Vais-je y aller, "aha! Je me souviens de cette petite chose intelligente que j'ai faite! Je n'ai pas eu à inclure de parens quand j'ai écrit cela l'année dernière, c'est une bonne chose que je me souvienne maintenant!" si cela se produit (ou pire, quelqu'un d'autre qui n'était pas au courant de cette intelligence ou qui a été jeté dans une situation de type "réparer dès que possible")?
Séparer avec () rend tellement plus simple de survoler rapidement et de comprendre plus tard ...
Comme tout le monde l'a dit, utilisez des parenthèses à chaque fois que cela rend l'expression plus lisible. Cependant, si l'expression est compliquée, je conseillerais de introduire de nouvelles fonctions pour les sous-expressions.
Ou est-ce un signe qu'un développeur doit vraiment s'asseoir et prendre confiance dans les bases de son langage?
Si vous utilisez strictement langue au singulier, peut-être. Prenez maintenant tous les langues que vous connaissez, des âges aux plus modernes, de la compilation aux scripts en passant par SQL à votre propre DSL que vous avez inventé le mois dernier.
Vous souvenez-vous des règles de priorité exactes pour chacune de ces langues, sans regarder?
"Dois-je utiliser des parenthèses dans les déclarations logiques même lorsque cela n'est pas nécessaire."
Oui, car deux personnes les trouveront utiles:
Le prochain programmeur, dont les connaissances, les compétences ou le style peuvent être différents
Le futur vous qui reviendrez sur ce code à une date ultérieure!