web-dev-qa-db-fra.com

PHP Retour des styles de codage; dans switch / case

nous essayons d'implémenter de nouvelles directives de style de codage pour notre équipe, le php codesniffer affiche un avertissement sur les instructions de cas de commutation lorsqu'aucune "rupture" n'est trouvée comme:

switch ($foo) {   
    case 1:
      return 1;   
    case 2:
      return 2;   
   default:
       return 3; 
}

y a-t-il une bonne raison d'utiliser:

   switch ($foo) {
       case 1:
         return 1;
         break;
   }

?? la rupture n'est jamais atteinte?

48
opHASnoNAME

Il est parfaitement valable de laisser de côté le break lorsque vous return d'un switch.

Mais il est assez courant d'ajouter breaks explicites à chaque case comme une programmation défensive .

switch ($foo) {
    case 1:
        return 1;
        break;

    case 2:
        return 2;
        break;
}

L'idée est que si vous modifiez ultérieurement votre code dans case 1 et supprimer l'instruction return, vous pourriez oublier d'ajouter un break.

Cela entraînerait accidentellement le déroulement du programme à case 2.

switch ($foo) {
    case 1:
        somethingDifferent();

    case 2:
        return 2;
        break;
}

La chute des déclarations de cas est légèrement inhabituelle et vous devez ajouter un commentaire à votre code lorsque vous le faites pour montrer qu'il est intentionnel.

switch ($foo) {
    case 1:
        somethingDifferentAndWeWantToDoCase2AsWell();
        // fallthrough

    case 2:
        return 2;
        break;
}

Comme pour de nombreuses pratiques de programmation défensive, vous devez déterminer si le gonflement du code - qui encombre potentiellement votre code et le rend moins lisible - en vaut la peine ou non.

79
John Carter

Si votre "php codesniffer affiche un avertissement" essayez d'obtenir un autre meilleur codesniffer et n'oubliez pas d'essayer d'utiliser la dernière version stable PHP. Vous pouvez, bien sûr, écrire un breakaprès un return, mais cela n'a pas de sens, car il ne sera jamais lu du tout. Votre code est OK.

Regarde ça:

$fun = function(int $argument): string {
    switch ($argument) {
        case 1:
            return "one";
        case 2:
            return "two";
        default:
            return "more than two";
    }
};
$str = $fun(4); // return "more than two"

À mon avis, c'est plus simple et meilleur: moins de lignes => moins de code à maintenir :-)

4
Chemaclass

Pour répondre à votre question, non, il n'y a pas de bonne raison d'avoir quelque chose qui ne fait rien. Pensez-y de cette façon, un commentaire après le return au lieu d'un break disant "n'oubliez pas" aura le même effet - aucun. Et de cette façon, cela semble idiot, non?

À moins que vous ne deviez définir une var à utiliser plus tard, je suggère que l'approche que vous avez est parfaitement adaptée. J'ai connu l'intention du code dans les 2 secondes après l'avoir vu. Avoir un break crée juste de la confusion.

Il n'y a pas vraiment de taille unique. L'approche correcte dépend de celui qui correspond au scénario. Définissez une variable dans chaque case et avoir un break peut être la bonne façon, ou peut-être simplement retourner a du sens.



Quelques observations sur d'autres suggestions faites dans les réponses:

1) Ne pas avoir un break après return signifie que des problèmes pourraient survenir si le code est changé plus tard

Dans la mesure du possible, le code doit être explicite, ainsi que lisible et clair. Nous pouvons également coder de manière à faciliter les modifications futures. Mais dans quelque chose d'aussi simple qu'un switch, cela ne devrait poser aucun problème et n'a pas besoin de filet de sécurité pour refactoriser un case plus tard pour ajouter ou supprimer un return ou break.

En fait, si vous avez supprimé un return et que " n'a pas remarqué qu'il n'y avait pas de break", c'est une mauvaise erreur qui pourrait être commise dans n'importe quelle partie du codage. Aucune vérification du gotcha ne vous sauvera de cela. Et il faut être très prudent en codant pour les potentiels futurs, car ce potentiel peut ne jamais se produire, ou quelque chose d'autre peut se produire, et vous finissez par maintenir le code obsolète pendant des années.

Dans la même veine, cela a été considéré comme un filet de sécurité pour les changements futurs - Et si vous supprimiez le return et que vous laissiez accidentellement dans ce filet de sécurité break alors que vous auriez dû le retirer?

Même si cette déclaration de changement était un scénario de vie ou de mort, un code vraiment sérieux, je serais contre l'ajout de la pause "inutile" après le retour. Assurez-vous simplement que celui qui travaille sur le code sait ce qu'il fait, et le code a été examiné par suffisamment d'yeux et entièrement testé.
Si c'était si grave, alors vous auriez des contrôles supplémentaires en place mieux qu'un filet de sécurité proposé pour attraper les développeurs bâclés.

Faire valoir que la pause après le retour ajoute un filet de sécurité signifie que vous ne codez pas ou ne testez pas correctement. S'il s'agit d'un filet de sécurité jugé utile, il est probable qu'il y ait des tonnes de bogues dans le code dans des endroits potentiellement plus graves.

L'article wiki de "Programmation défensive" était lié à, mais il n'est pas pertinent ici:

La programmation défensive est une forme de conception défensive destinée à assurer la fonction continue d'un logiciel dans des circonstances imprévues.

Laisser un filet de sécurité break dedans n'est pas un scénario de circonstances imprévues, ni de programmation défensive. C'est juste un mauvais codage, et vous ne pouvez pas salir votre code avec du code de sauvegarde au cas où vous ne coderiez pas correctement lorsque vous changez quelque chose . C'est une si mauvaise approche du codage. L'argument selon lequel "si quelqu'un supprimé retourne ne fonctionnera pas", vous pouvez également avoir une faute de frappe dans le cas var, ou oublier d'écrire le cas, ou ...

return revient et vous ne codez pas "défensivement" pour éviter un échec de retour. Cela signifierait PHP est cassé, et vous n'allez pas remplir votre code de filets de sécurité pour répondre à cela. C'est quelque chose que vous avez à un niveau beaucoup plus élevé.

2) break après return le maintient explicite

Mais c'est explicitement faux. return revient, donc la rupture ne se produira pas. Pour moi, c'est du temps de tête de se demander si j'ai manqué l'intention - pas tant qu'il est clair ce qui se produira , mais il y aura un moment où je réfléchirai à ce qu'il fera bien sûr, je n'ai rien manqué.

Bien qu'il ne soit pas invalide ou erroné d'avoir un return puis break dans le même case, c'est tout à fait inutile car le break ne fait rien. C'est du code inutile qui doit être vu, maintenu et compris car il n'est pas logique.

Si explicite est l'objectif principal et avoir un break après un return vous invite parce que c'est inutile, alors je dirais qu'il serait préférable de définir une variable et break, puis de retourner la variable après une rupture du commutateur.
Comme la réponse @RageZ https://stackoverflow.com/a/1437476/2632129

3) Définissez une variable et retournez une fois l'instruction switch terminée

Il n'y a rien de mal à cette approche, mais s'il n'y a aucune raison de stocker la valeur dans une variable (utilisation ultérieure, etc.), il est bon de revenir immédiatement lorsqu'il n'y a pas besoin de traîner pour faire autre chose.

Cela montre une intention claire - renvoyer une valeur dès que le cas correspond.

3
James

J'ai une bien meilleure solution.Veuillez suivre le code ci-dessous pour la déclaration de commutateur ci-dessus:

$result = 3; // for default case
switch ($foo) {   
    case 1:
      $result = 1;
      break;  
    case 2:
      $result = 2;
      break;    
   default:
      // do nothing
}
return $result;

Cela n'entraînera aucune erreur et le code convient également aux concepts.

3
Lavkush