Pourquoi de nombreux développeurs PHP détestent-ils utiliser isset () et / ou l'une des fonctions défensives similaires de PHP comme empty ()?

27

Sur stackoverflow, je vois ce problème surgir tout le temps:

Même Pekka (qui offre beaucoup de conseils PHP solides) a heurté le E_NOTICEmonstre redouté et espérait une meilleure solution que d'utiliser isset(): isset () et empty () rendent le code laid

Personnellement, j'utilise isset()et empty()à de nombreux endroits pour gérer le flux de mes applications. Par exemple:

public function do_something($optional_parameter = NULL) {
    if (!empty($optional_parameter)) {
        // do optional stuff with the contents of $optional_parameter
    }
    // do mandatory stuff
}  

Même un simple extrait comme celui-ci:

if (!isset($_REQUEST['form_var'])) {
    // something's missing, do something about it.
}

me semble très logique. Cela ne ressemble pas à du ballonnement, il ressemble à du code stable. Mais de nombreux développeurs lancent leurs applications avec E_NOTICEles options activées, découvrent de nombreux avis frustrants sur les «index de tableau non initialisés», puis grimacent à la perspective de vérifier les variables définies et de «salir» leur code isset().

Je suppose que d'autres langues gèrent les choses différemment. Par expérience, JavaScript n'est pas aussi poli que PHP. Une variable non définie interrompra généralement l'exécution du script. De plus, (parlant d' inexpérience ), je suis sûr que des langages comme C / C ++ refuseraient simplement de compiler.

Alors, les développeurs PHP sont-ils juste paresseux? (sans parler de vous, Pekka, je sais que vous refactoriez une ancienne application.) Ou d'autres langages gèrent-ils les variables non définies plus gracieusement que de demander au programmeur de vérifier d'abord si elles sont définies?

(Je sais qu'il existe d'autres E_NOTICEmessages en plus des variables non définies, mais ceux-ci semblent être ceux qui provoquent le plus de chagrin)

Addendum
D'après les réponses fournies jusqu'à présent, je ne suis pas le seul à penser que le isset()code n'est pas trop lourd. Donc, je me demande maintenant, y a-t-il des problèmes avec les programmeurs dans d'autres langues qui font écho à celui-ci? Ou s'agit-il uniquement d'un problème de culture PHP?

Stephen
la source
4
Malheureusement, j'ai vu des développeurs php fonctionner avec des "avertissements" également désactivés.
Viper_Sb
Aie. C'est triste.
Stephen
1
N'étant pas un utilisateur PHP, je me demande: pourquoi auriez-vous besoin de vérifier les variables non définies?
Winston Ewert
2
@Winston: Le problème avec PHP (contrairement à de nombreux autres langages) est que PHP permet de nombreuses combinaisons de configuration. Par exemple, le programmeur peut décider d'ignorer les avertissements, les avis et les notifications de dépréciation. Les développeurs plus expérimentés travailleront avec error_reporting pour tout signaler. PHP possède également de nombreuses fonctions qui génèrent des erreurs et renvoient des codes d'état plutôt que de lever des exceptions. Il faut être très intime avec le langage pour pouvoir coder défensivement et avec succès. De nombreuses autres langues ne permettent pas le choix. Strict est généralement la seule option par défaut.
Wil Moore III
1
Je n'aime pas isset () à cause de la verbosité qu'il ajoute. Une meilleure forme de @ serait une bonne alternative.
Kzqai

Réponses:

34

Je code E_STRICTet rien d'autre.

L'utilisation de vérifications vides et Isset ne rend pas votre code laid, il rend votre code plus verbeux. Dans mon esprit, quelle est la pire chose qui puisse arriver en les utilisant? Je tape encore quelques caractères.

Conteste les conséquences de ne pas les utiliser, à tout le moins des avertissements.

Josh K
la source
7
Mon environnement de développement l'est aussi E_STRICT. Je supprime toutes les erreurs de production, mais c'est juste pour m'assurer que rien ne m'a échappé pendant le développement.
Stephen
2
+1 Josh, je suis de la même façon. Lorsque vous programmez dans E_STRICT, vous savez que vous n'aurez jamais de surprises dans votre code. Seul moyen de voler, imo.
EricBoersma
3
@Stephen: désactivez toujours les erreurs de production. Mais ce n'est qu'un filet de sécurité. Le développement devrait (OMI) être toujours E_STRICT. Écrivez le code et résolvez tous les avertissements et erreurs.
Josh K
tu me perroquets? :)
Stephen
@Stephen: Je suis d'accord. :)
Josh K
17

Je pense que les avis sur les éléments inconnus sont une erreur de conception en PHP. Je ne suis pas sûr qu'il soit possible de corriger l'erreur maintenant, mais cela produit beaucoup de code passe-partout comme if(isset($foo['abc']) && $foo['abc'] == '123')- ce code ne devrait pas avoir isset, car l'intention est de vérifier s'il y a '123' à un certain endroit $fooet s'il n'y a rien là c'est certainement pas «123». La seule raison pour laquelle vous devez écrire deux fois plus de code est à cause de cette malheureuse erreur de conception en PHP. Et les notifications sont très chères en PHP, malheureusement, donc juste les désactiver n'est pas une option pour le code où les performances sont un problème.

Alors oui, cela rend le code laid à mon humble avis et cela m'ennuie. Et ce n'est pas par manque d'expérience - j'utilise PHP depuis 1998 et je me souviens quand il y avait une .php3extension et cela signifiait "ce n'est pas PHP 2". Peut-être que je suis paresseux :) Mais la paresse - au moins certains types de celui-ci - est une vertu pour un programmeur.

D'un autre côté, une utilisation valide de issetet empty- tout comme celles de l'article d'origine - est très bien. Je pense juste que PHP est trop zélé à propos des avertissements dans des endroits où isset/emptyils ne sont pas vraiment nécessaires.

StasM
la source
3
Droite. C'est une question de verbosité. $eg = isset($_GET['eg'])? $_GET['eg'] : null;est ridiculement verbeux. Je souhaite vraiment qu'il y ait un autre opérateur qui n'était pas "suppression d'erreur" en soi pour remplacer le sens court de $eg = @$_GET['eg'];"accepter-la-non-existence-de-cette-clé-de-tableau-comme-un-null". J'ai tendance à utiliser une fonction courte, ces jours-ci.
Kzqai
7
D'accord. 4 ans plus tard, entrez dans l'opérateur Null Coalesce: wiki.php.net/rfc/isset_ternary nous donnant$eg = $_GET['eg'] ?? null;
Steve
Ou faites-le maintenant avec l'opérateur de suppression d'erreur, par exemple $eg = @$_GET['eg'] ?: null;. Je ne l'utilise généralement pas, mais dans ce cas, nous attendons explicitement cette erreur et décidons de l'ignorer. C'est un caractère plus long que la fusion nulle et ce n'est pas aussi bon (il supprime toutes les erreurs, et il peut y avoir un ArrayAccess qui fait des trucs géniaux là-bas, pas seulement un tableau), mais en général, il fait le travail.
El Yobo
12

Je crois que PHP, en tant que langage libre, qui est interprété et utilisé sur le Web, a une très forte proportion de codeurs non professionnels et non formés qui ne savent pas vraiment pourquoi ils devraient coder de manière défensive et voient simplement les avertissements comme une autre erreur inutile. .

J'entends tout le temps ces points de la part de développeurs débutants et de codeurs de scripts autodidactes:

  • Pourquoi initialiser une variable si elle existe quand même?
  • Pourquoi vérifier si quelque chose existe avant de l'utiliser, undefined équivaut à faux de toute façon?
  • Si je préfixe avec @ il corrige mon code, pourquoi compliquer les choses?

S'ils n'ont jamais connu un langage fortement typé, ou ont connu les pièges des variables non déclarées / non corroborées, alors ils prennent un peu convaincant. Je trouve qu'ils cèdent généralement une fois qu'ils ont éprouvé le plaisir de déboguer du code pendant environ une heure pour trouver que c'était une faute de frappe dans un nom de variable causant le problème.

L'autre facteur important est l'utilisation de PHP dans l'industrie du Web, qui a tendance à être beaucoup plus préoccupée par le débit que par la sécurité et la qualité du code.

Orbling
la source
10
"Je crois que PHP [...] a une très forte proportion de codeurs non professionnels et non formés" En tant que développeur PHP dédié, je ne peux pas être plus d'accord avec vous. +1
Stephen
@Stephen Eh bien, je code principalement en PHP et jQuery récemment, même si j'ai une formation formelle, mais le code que vous voyez comme un professionnel dont vous devenez responsable avant ... il défie parfois la croyance. ;-)
Orbling
1
Je pense que c'est un vrai problème avec PHP. Mis à part quelques bizarreries dans la langue (qu'ils résolvent lentement dans chaque nouvelle version), il y a un air d'amateurisme autour de lui. Je peux imaginer qu'être un développeur PHP professionnel peut parfois être frustrant, car vous êtes comparé au «neveu du patron du coin».
Erik van Brakel
1
@Erik PHP était un parent assez pauvre de Perl il y a dix ans, c'est maintenant un langage interprété assez raisonnable, en particulier pour une utilisation Web. Il y a une raison pour laquelle des entreprises comme Facebook l'utilisent. Mais comme il est disponible partout, le set amateur l'utilise largement et cela ternit la réputation.
Orbling
5

Oui, ils sont paresseux. Beaucoup d'entre eux de toute façon ...

Malheureusement, la mentalité de nombreux codeurs PHP est "Il n'y a aucun point de codage défensif si vous pouvez obtenir le même résultat final plus rapidement en s'appuyant sur le langage pour gérer les erreurs causées par des variables manquantes, etc.". Je sais, j'ai travaillé avec plusieurs d'entre eux.

Ils ont tendance à être aussi ceux qui se dirigent mystérieusement vers un déjeuner tôt lorsque leur manque de gestion des erreurs et de rapports corrects supprime les serveurs en direct pendant plusieurs heures ...

Gruffputs
la source
5
-1 pour l'opinion subjective sur les codeurs PHP.
Josh K
4
@Josh, ayant été codeur PHP senior pendant 4 ans et demi et codé et désactivé PHP depuis 1999, je crains d'être quelque peu subjectif. J'aurais dû me qualifier avec "D'un autre côté, les codeurs PHP les plus expérimentés ne sont pas paresseux et font les choses correctement" ...
Gruffputs
1
Que tu devrais avoir.
Josh K
5

J'essaie d'éviter l'utilisation de isset () et empty () en évitant l'utilisation de tableaux comme objets de transfert de données. Créez une classe qui peut être configurée pour accepter un ensemble limité de propriétés avec des valeurs par défaut saines et valider l'entrée de ces propriétés. Il peut même implémenter l'interface ArrayAccess afin que vous puissiez l'utiliser comme un tableau. Cela vous permet également d'utiliser l'indicateur de type dans vos signatures de méthode pour détecter les erreurs lorsque quelqu'un tente de transmettre le mauvais type d'entité à votre méthode.

Anévrisme9
la source
Une approche très intéressante.
Toby
2

L'une des questions posées est la mienne, alors permettez-moi de répéter.

De nombreux développeurs confondent la présence de beaucoup isset()comme signe de qualité. Il donne une apparence de fiabilité et certaines personnes y voient même une fonction de sécurité.

Mais vous devez tenir compte du fait que PHP n'est pas un langage compilé. C'est un langage de script avec un système de type dynamique. Les erreurs E_NOTICE ne sont que des erreurs de nom. Et si beaucoup issetsont utilisés dans le seul but de supprimer les avis, alors vous ne faites que coder en fonction de la langue .

Alors, les développeurs PHP sont-ils juste paresseux?

C'est en effet le cas si vous voyez une abondance d'avis et d'avertissements lancés. Beaucoup de débutants ne se soucient pas des avis, et c'est généralement le résultat d'un handicap complet error_reporting(0).

Vous vous trompez cependant sur le fait que d'autres développeurs n'ont pas reconnu les E_NOTICE simplement parce qu'ils n'ont pas été supprimés @ ou isset. C'était du moins mon intention derrière la question des avis de conservation . Ils ne sont pas quelque chose à se débarrasser, mais des informations de débogage parfois importantes.

Comme toutes les généralisations, l'utilisation inconsidérée de isset ne conduit pas à un code optimal. Il est important de différencier où issetet emptysont nécessaires et où ils sont du sel syntaxique .

Ou s'agit-il uniquement d'un problème de culture PHP?

Non, les "erreurs" variables non définies ne sont pas un problème PHP seul. Bash, TCL et Perl ou JavaScript permettent l'utilisation de variables non définies. Cette fonctionnalité de langage immanent n'est cependant pas considérée comme un défaut. Il existe des constructions de langage similaires pour vérifier les valeurs non définies. Cependant, ils ne sont pas aussi constamment utilisés qu'en PHP, car les valeurs undef ne sont pas qualifiées d'erreurs.

mario
la source
1

Intéressant. Je n'utilise presque jamais isset (). Mon code PHP est rarement dans un état où je ne sais pas si une variable a été définie en premier lieu. Chaque variable GET ou POST utilisée est accessible via une fonction qui lui fournira une valeur par défaut si elle n'existe pas. Les valeurs par défaut dans les appels de fonction sont généralement définies explicitement sur 0 ou des chaînes vides.

GrandmasterB
la source
+1. Passer à une méthode de fonction ou de classe est une bonne solution. En fait , je DOIS le faire, mais dans un pincement mes exemples ci - dessus semblent toujours propre et non gonflé pour moi.
Stephen
0

J'utilise isset et vide beaucoup. Mais la plupart du temps, ce sont des endroits que vous mentionnez, comme le traitement $ _REQUEST, au cas où quelqu'un aurait dérangé avec les paramètres. Dans les cas où j'ai le contrôle sur toutes les variables qui volent, je trouve que je n'en ai généralement pas besoin.

Tesserex
la source
0

Je n'aime pas utiliser isset, mais s'il y a des masses de code faites par un autre, cela peut être une grâce salvatrice. J'ai écrit le code wee ci-dessous pour résoudre ce problème, au lieu d'utiliser isset () isseter ($ a, $ b) retournera $ b si $ a n'est pas défini ou vide, ou la fonction retourne une valeur nulle. Toutes améliorations, bienvenue:

//returns var or NULL (if undefined)
//$reserve optional second value is returned as $default if undefined
function isseter(&$default,&$reserve=NULL)
{
$default = isset($default) ? $default : NULL;
$reserve = isset($reserve) ? $reserve : NULL;
if ((!$default) && ($reserve)) $default=$reserve;
return $default;
}
bigal
la source