web-dev-qa-db-fra.com

Vérifier la véritable explicité est-il mauvais par conception?

Est-il considéré comme mauvais de vérifier explicitement le booléen vrai? Serait-il préférable de faire une simple if(success)?

J'ai déjà vu diverses blagues sur la façon dont if (someBoolean === true) est un code horrible dans un langage fortement typé, mais est-il également considéré comme mauvais dans les langages faiblement typés?

Ceci s’appliquerait à n’importe quel langage faiblement typé faisant coercition sur une instruction if.

Un exemple spécifique serait:

var onSuccess = function (JSONfromServer) {
    // explicitly check for the boolean value `true`
    if (JSONfromServer === true) {
         // do some things
    }
}

// pass it to an ajax as a callback
doSomeAjax(onSuccess);

[Modifier]

Dans ce cas particulier, la variable de réussite est tout code JSON valide renvoyé par un serveur. Donc ça pourrait être n'importe quoi. si c'est le vrai booléen alors un succès est arrivé. S'il s'agit d'un objet de traitement d'erreur, il sera traité. S'il s'agit de quelque chose d'autre, cela sera probablement traité tranquillement.

La question était d'obtenir que le serveur renvoie true en tant que JSON et de rechercher un moyen efficace de gérer le cas où l'action a réussi.

Je voulais éviter d'être spécifique à JavaScript et AJAX bien que.

17
Raynos

Je suis dans deux esprits à ce sujet moi-même.

En un sens, l’exemple de code que vous avez posté est bon, en raison de la façon dont Javascript gère la contrainte de type. Un simple if (success) entrerait dans le bloc if aussi longtemps que success serait vérité - p. Ex. une chaîne non vide ferait l'affaire. Le triple égal garantit que success est bien la valeur booléenne true, qui est une garantie plus solide que celle obtenue avec la version plus courte (et probablement celle que vous voulez).

Cependant, si vous avez besoin ceci - c’est-à-dire que vous ne savez pas si success sera un booléen, une chaîne ou un entier, je dirais que c’est une odeur de code en soi. Quelle que soit la manière dont vous effectuez la comparaison, je comparerais toujours avec une variable qui sera inévitablement un booléen; à ce stade, peu importe la forme de comparaison utilisée, elle serait équivalente. En fait, je voudrais même introduire une variable "redondante" comme ceci:

var successCount = items.size(); // or some other way to get an integer
var success = successCount > 0;
if (success) {
   ...
}

Alors, euh, oui. Je ne pense pas que quiconque puisse vraiment se plaindre de l'utilisation (explicite) de === dans la comparaison en raison de sa différence fonctionnelle. Mais dans le même ordre d'idées, si vous utilisez clairement des drapeaux booléens success, je ne pense pas que quelqu'un devrait se plaindre du style court non plus.

(En ce qui concerne votre première phrase, je ne pense pas qu'il soit mauvais de vérifier explicitement la valeur booléenne true dans un langage à typage dynamique, si cette valeur correspond bien à ce que vous voulez. C'est superflu lorsque le typage statique contraint déjà la variable à être un booléen.)

10
Andrzej Doyle

Avec Javascript, il vaut la peine de savoir qu’au-delà du vrai et du faux booléens, les valeurs peuvent être vérité et falsy.

Considérer:

if (false)     // evaluates to false.
if (0)         // evaluates to false, 0 is falsy.
if ("")        // evaluates to false, empty strings are falsy.
if (null)      // evaluates to false, null values are falsy.
if (undefined) // evaluates to false, undefined values are falsy.
if (NaN)       // evaluates to false, NaN is falsy.

Toutes les autres valeurs pour les objets sont la vérité.

Si les valeurs vérité et fausseté génèrent des erreurs dans votre logique, vous devez envisager explicitement d'utiliser les opérateurs === et !== pour vous assurer que les objets sont comparés par type et par valeur.

16
Matthew Abbott

Généralement, vous attendez des noms de variables booléennes tels que:

success, enabled, pass

avoir une vraie valeur. Alors 

if(success) //or

if(enabled) //or

if(pass) //or

if(enabled) //or

est compréhensible et logiquement lisible. Mais si vous avez des variables comme:

result, status, port1.bit7

il vaut mieux écrire:

if(result == true) //or

if(status == false) //or

if(port1.bit7 == true)

parce qu'il est facilement compris de cette façon que l'exemple ci-dessous:

if(result)
{
  ....
}

La lisibilité est la maintenabilité.

7
LEMUEL ADANE

Qu'est-ce qui peut aller mal? Exactement rien. Dans le meilleur des cas, votre fonction ne fait rien. C’est encore mieux qu’un argument aléatoire soit accepté en tant que true.

Si vous utilisez true toute l’autre fois, vous devriez également le vérifier explicitement. 

Bien que je sois certain en faveur de if foo: en Python, il existe une grande différence et c’est le fait qu’en fin de compte, un programmeur jQuery aléatoire risque d’être long et pense "Oh! Il fonctionne également avec une chaîne et new Boolean()" et utilise ça.

Concernant la suggestion de Sean d'utiliser !!, cela dépend vraiment de savoir si vous voulez seulement qu'un booléen soit accepté ou quoi que ce soit qui soit vrai. Pour une API propre, je n'accepterais que des booléens.

2
Ivo Wetzel

Pour ajouter à cette conversation, les variables sessionStorage et localStorage ne peuvent être stockées aujourd'hui que sous forme de chaînes. Par conséquent, si vous utilisez:

sessionStorage.setItem('completed',true);

En fait, il sera converti en chaîne et stocké comme «vrai». J'ai vu beaucoup de personnes écrire des méthodes et des conversions pour manipuler cette valeur afin qu'elles puissent utiliser une instruction if en utilisant une valeur booléenne, où 

if sessionStorage.getItem('completed') === 'true';

suffirait et est parfaitement lisible et maintenable à mon avis.

1
user3094826

J'ai beaucoup lu sur JavaScript et je n'ai jamais vu personne dire que if(success) était une mauvaise pratique. Je le ferais. Etes-vous sûr que le paramètre success sera toujours booléen? Pour le moment, si cela devait changer, vous devriez éditer la fonction. Mais si vous utilisez simplement if(success), cela fonctionnera pour les autres valeurs "véracité" et "falsey", comme une chaîne par rapport à une chaîne vide ou 1 vs 0.

Si vous voulez convertir ce paramètre en valeur booléenne, vous pouvez simplement le nier deux fois: !!success; mais ce n'est pas nécessaire dans un conditionnel comme ça.

1
Andrew Burgess

S'agit-il d'une odeur de code ou d'une langue, d'un détail d'implémentation ou d'une question de convention?

Vraiment, cela dépend de la situation.

Le fait de placer toutes les valeurs fausses et toutes les valeurs vraies dans un compartiment simplifie les choses, jusqu'à ce que les différences comptent, qu'il s'agisse d'une mauvaise conception de code ou parce que cela compte vraiment pour une raison quelconque.

Dans le même ordre d'idées, Hoare s'est excusé pour avoir inventé la référence null, qui est aussi proche que je le vois de la racine de ce problème de vérité. La conception de JavaScript ne fait que confondre le problème en ajoutant encore plus de valeurs de vérité, ce qui pousse beaucoup à préconiser la vérification explicite pour éviter les erreurs difficiles à localiser (Douglas Crockford). La communauté JavaScript a accepté le langage lui-même, est un peu coincé. L'équipe principale de Python préconise le contraire, car la conception de la langue semble être axée sur la simplification, et non la confusion, et l'équipe de base est toujours en train de planifier des modifications de la langue. De petits changements itératifs sont l’essence de grandes améliorations dans le temps, qu’il s’agisse de la convention ou de la conception du langage.

Les deux sont de bonnes stratégies pour leur situation particulière. Je ne dis pas que c'est la source exclusive d'amélioration, mais c'est une source majeure d'amélioration en ce moment.

Par exemple, True et False sont en réalité des sous-classes d'une int en Python, 0 et 1 en particulier. Cela présente plusieurs avantages en termes de conception. Puis le PEP8 préconise de préférer faire

if a_reference:
    pass

La seule fois où None doit vraiment être utilisé en Python est lors de la spécification d'un paramètre facultatif.

def foo(bar=optional): # NOTE I made up this idealistic construct
    """Looks good at the surface"""
    pass

def foo(bar=None):
    """But this is clear to the programmer"""
    pass

JavaScript a implicitement toutes les variables en option:

function foo(x, y, z) {
    // Certainly not clear to the programmer.
}

Et Crockford préconise de vérifier explicitement les choses pour essayer d'ajouter un peu de clarté au langage.

if (foo === undefined) {
    // pass
}

Fondamentalement, JavaScript a ajouté la référence de référence n ° 2, connue sous le nom de undefined. Je trouve également drôle que le langage JavaScript soit si mal considéré par la communauté de la programmation qu’ils pensent qu’il est juste d’ajouter à la complexité d’utiliser quelque chose comme CoffeeScript, GWT, Pyjamas, simplement pour avoir un meilleur langage côté client. Bien sûr, je ne suis pas d'accord sur la complexité supplémentaire, mais il est malheureusement vrai que certaines personnes peuvent en bénéficier, du moins temporairement, et faire le travail plus rapidement, au lieu de gérer JavaScript.

Je pense cependant que c'est une décision stupide à long terme.

0
Derek Litz