Estilos de codificación PHP return; in switch / case


Estamos tratando de implementar nuevas pautas de estilo de codificación para nuestro equipo, el codesniffer de php está imprimiendo una advertencia en las instrucciones de mayúsculas y minúsculas cuando no se encuentra "break" como:

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

Hay alguna buena razón para usar :

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

?? ¿la ruptura nunca se alcanza ?

Author: Jon Seigel, 2009-09-17

6 answers

Es perfectamente válido omitir el break cuando return de un switch.

Pero es una práctica bastante común agregar breaks explícitos a cada case como una práctica de programación defensiva.

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

    case 2:
        return 2;
        break;
}

La idea es que si más tarde cambias tu código en case 1 y eliminas la instrucción return, podrías olvidarte de agregar un break.

Que causaría accidentalmente que el flujo del programa cayera a través de case 2.

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

    case 2:
        return 2;
        break;
}

Caer a través de las declaraciones de caso es un poco inusual y debe agregar un comentario a su código cuando lo haga para mostrar que es intencional.

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

    case 2:
        return 2;
        break;
}

Al igual que con muchas prácticas de programación defensiva, debe equilibrar si el código inflado, que potencialmente desordena su código y lo hace menos legible, vale la pena o no.

 71
Author: John Carter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-04 17:51:33

Tengo una solución mucho mejor.Por favor, siga el código a continuación para el estado del interruptor anterior:

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

No resultará en ningún error y el código también está bien con los conceptos.

 3
Author: Lavkush,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-01 14:30:17

Para responder a tu pregunta, no, no hay una buena razón para tener algo que no hace nada. Piénsalo de esta manera, un comentario después de return en lugar de un break diciendo "no olvides" tendrá el mismo efecto - ninguno. Y dicho de esa manera suena tonto, ¿verdad?

A menos que necesite establecer un var para usar más tarde, sugeriría que el enfoque que tiene está perfectamente bien. Sabía la intención del código en 2 segundos desde que lo vi. Tener un break solo crea confusión.

Hay no hay una talla única para todos. El enfoque correcto depende de lo que se ajuste al escenario. Establecer una variable en cada case y tener un break puede ser la forma correcta, o tal vez solo retorno tiene sentido.

 
 


Algunas observaciones sobre otras sugerencias hechas en las respuestas:

1) No tener un break después de return significa que podrían surgir problemas si el código se cambia más tarde

Siempre que sea posible, el código debe ser explícito, así como legible y claro. También podemos codificar de una manera que facilite los cambios futuros. Pero en algo tan simple como un switch no debería ser ningún problema y no necesita ninguna red de seguridad para refactorizar un case más tarde para agregar o eliminar un return o break.

De hecho, si eliminó un return y " no se dio cuenta de que no había break" entonces eso es un error pobre y podría cometerse en cualquier parte de la codificación. Ningún cheque te salvará de eso. Y uno debe ser muy cuidadoso codificando los potenciales futuros, ya que ese potencial puede nunca suceder, o puede suceder algo más, y acabas manteniendo código obsoleto durante años.

En el mismo sentido, se argumentó que esto era una red de seguridad para cambios futuros: ¿Qué pasa si se quita el return y se deja accidentalmente en esa red de seguridad break cuando debería haberlo eliminado?

Incluso si esta instrucción switch fuera un escenario de vida o muerte, un código realmente serio, estaría en contra de agregar la interrupción "sin sentido" después del regreso. Sólo asegúrate de quienquiera que estuviera trabajando en el código sabía lo que estaba haciendo, y el código fue revisado por suficientes ojos y probado completamente.
Si fuera tan grave, entonces tendría cheques adicionales en su lugar mejor que una red de seguridad propuesta para atrapar desarrolladores descuidados.

Argumentar que la ruptura después de la devolución agrega una red de seguridad, significa que no está codificando o probando correctamente. Si esta es una red de seguridad que se considera útil, es probable que haya toneladas de errores en el código en lugares potencialmente más serios.

El artículo wiki de "Programación Defensiva" fue enlazado, pero no es relevante aquí:

La programación defensiva es una forma de diseño defensivo destinada a garantizar la función continua de una pieza de software bajo imprevisto circunstancia.

Dejar una red de seguridad break no es un escenario de circunstancias imprevistas, ni de programación defensiva. Es solo una mala codificación, y no puedes ensuciar tu código con un código de respaldo por si acaso no codifique correctamente cuando cambie algo. Ese es un mal enfoque para la codificación. El argumento de que "si alguien eliminó devolver no funcionará", bien, también podría tener un error tipográfico en el caso var, u olvidar escribir el caso, o...

El return regresa, y no codifica "defensivamente" para evitar que una devolución falle. Eso significaría que PHP está roto, y no vas a llenar tu código con redes de seguridad para atender eso. Eso es algo que tienes en un nivel mucho más alto.

2) break después de return mantiene explícita

Pero está explícitamente mal. El return regresa, por lo que la ruptura no sucederá. Para mí eso es scratch head time preguntándome si he perdido la intención, no por mucho tiempo, ya que está claro lo que sucederá, pero habrá un momento en el que lo pondere para asegurarme de que no me he perdido algo.

Si bien no es inválido o error tener un return y luego break en el mismo case, es completamente inútil como el break no hace nada. Es un código sin sentido que necesita ser visto, mantenido y descubierto, ya que no es lógico.

Si explicit es el objetivo principal y tener un break después de un return te urks porque no tiene sentido, entonces yo diría que sería mejor establecer una variable y break, luego devolver la variable después de romper el interruptor.
Me gusta @RageZ respuesta https://stackoverflow.com/a/1437476/2632129

 

3) Establezca una variable y regrese después de que se complete la instrucción switch

No hay nada malo con este enfoque en absoluto, pero si no hay razón para almacenar el valor en una variable (uso posterior, etc.), entonces es bueno regresar inmediatamente cuando no hay necesidad de esperar para hacer nada más.

Que muestra una intent clara: devuelve un valor tan pronto como el caso coincide.

 3
Author: James,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-02 01:42:48

Si su "php codesniffer está imprimiendo una advertencia" intente obtener otro mejor codesniffer y no olvide intentar usar la última versión estable de PHP. Puedes, por supuesto, escribir un breakdespués de uno return, pero no tiene sentido, porque nunca se leerá. Tu código está bien.

, Mira esto:

$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"

En mi opinión, esto es más simple y mejor: menos líneas = > menos código para mantener : -)

 3
Author: Chemaclass,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-20 08:11:45

No soy un experto en codificación perfecta, pero creo que el validador preferiría algo así

switch ($foo) {   
    case 1:
      $ret =  1;   
      break;
    case 2:
      $ret = 2;
      break;   
   default:
       $ret = 3

}
return $ret

Creo que usar la instrucción return in case para romper el flujo del código no es realmente una buena práctica. Por eso el validador dice que no hay interrupción ...

Para su pregunta sobre la categoría at, no lo sé ... lo siento

 -1
Author: RageZ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-17 08:30:19

Del manual de PHP ( http://us3.php.net/manual/en/control-structures.switch.php) :

PHP continúa ejecutando las sentencias hasta el final del bloque switch, o la primera vez que ve una sentencia break. Si no escribe una sentencia break al final de la lista de sentencias de un caso, PHP continuará ejecutando las sentencias del siguiente caso. Por ejemplo:

<?php
switch ($i) {
    case 0:
        echo "i equals 0";
    case 1:
        echo "i equals 1";
    case 2:
        echo "i equals 2";
}
?>

Aquí, si $i es igual a 0, PHP ejecutaría todas las sentencias echo! Si PHP i es igual a 1, PHP ejecutaría las dos últimas declaraciones echo. Obtendrías el comportamiento esperado ('i es igual a 2' se mostraría) solo si $i es igual a 2. Por lo tanto, es importante no olvidar las declaraciones break (aunque es posible que desee evitar proporcionarlas a propósito bajo ciertas circunstancias).

 -11
Author: Sander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-09-17 08:29:01