En cuanto al mantenimiento, ¿se considera seguro `else while` sin llaves intermedias?

26

¿ else whileSin llaves intermedias se considera un mantenimiento "seguro"?

Escribiendo if-elsecódigo sin llaves como a continuación ...

if (blah)
    foo();
else
    bar();

... conlleva un riesgo porque la falta de llaves hace que sea muy fácil cambiar el significado del código sin darse cuenta.

Sin embargo, ¿a continuación también es arriesgado?

if (blah)
{
    ...
}
else while (!bloop())
{
    bar();
}

¿O se else whileconsidera "seguro" sin llaves intermedias?

Mehrdad
fuente
20
A mí me else whileparece asqueroso. Que haría uso else { while (condition) { ... } }.
Joachim Sauer
77
Creo que es demasiado subjetivo para una respuesta adecuada ... Yo mismo no lo haría, ya que no esperaré un ciclo allí, y creo que no espero que dificulte la legibilidad.
johannes
77
Me gustaría extraer método ya que mientras las cosas-
mosquito
12
Honestamente, me da escalofríos. ifsólo se evalúa una vez, pero whiledenota un bucle, por lo que la conexión de los dos me da una sensación infundada de que el ifes parte del bucle ... de alguna manera ...
user281377
44
¿Y si en la elsecláusula quieres hacer while y hacer algo más? Solo usa llaves, por favor.
Carlos Campderrós

Respuestas:

57

Eso me recuerda este código:

if ( ... ) try {
..
} catch (Exception e) {
..
} else {
...
}

Cada vez que combina dos tipos de bloques, olvidando las llaves y sin aumentar la sangría, está creando un código muy difícil de entender y mantener.

Sulthan
fuente
18
Buen ejemplo. Qué horrible manera de escribirlo.
Leo
44
¡Guau, esta respuesta es ridículamente convincente!
Mehrdad
Puede configurar fácilmente IDEs modernos para formatear automáticamente el código al guardar, incluida la inserción de llaves y la corrección de la sangría. Entonces esto es solo medio argumento. Correctamente sangrado esto no supondría ningún problema para la legibilidad, ya sea que haya llaves o no.
Hans-Peter Störr
55

Tal vez sea porque aprendí mi oficio (en el pasado) usando el método del Diagrama de Estructura de Entidad Jackson , pero me suscribo a la opinión de que el único término correcto sin corchetes después de un ifo un elsees un posterior if(es decir, permitir una else ifescalera)

Cualquier otra cosa (sin juego de palabras) deja posibles malentendidos y / o problemas de mantenimiento. Ese es el aspecto central de la idea de que los OP son "inseguros".

También sería muy cauteloso al incluir el while()en la misma línea que el else, ya sea que esté preparado o no. No me parece correcto ... la falta de máscaras de sangría adicionales que es la elsecláusula. Y la falta de claridad genera malentendidos (ver arriba).

Entonces, en el ejemplo, recomendaría / recomendaría (e insistiría, en mi equipo) sobre:

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Por supuesto, también esperaría ver comentarios adecuados también.

- Editar -

Recientemente, Apple sufrió una vulnerabilidad SSL, causada por una corrección de mantenimiento deficiente, que agregó una segunda línea a una sola línea sin arriostramiento. Entonces, ¿vamos a la cama con la idea de que las líneas simples sin refuerzo están bien?

Andrés
fuente
2
Estoy de acuerdo en si es el único término correcto para seguir a otra persona. Si hubiera un else while, probablemente ni siquiera notaría que había un bucle en un rápido descremado del código, especialmente si la condición que estaba buscando era satisfecha por el if.
Drake Clarris
3
Es gracioso. Todos dicen que es más fácil de leer si todo está entre llaves. Encuentro lo contrario para ser verdad. Si es solo una declaración, mantenerla fuera de los corchetes hace que sea más fácil de leer. Menos desorden. Puede ser solo porque siempre lo he hecho de esa manera.
Jeff Davis
2
@JeffDavis es una buena captura. "Más fácil de leer" es una invitación típica a la guerra santa inútil. Por mi parte, prefiero los aparatos ortopédicos, pero no debido a la basura irrelevante "easiertoread" (para mí, por ejemplo, es exactamente lo contrario) sino porque es más difícil romper el mantenimiento del código. Por cierto, OP lo deletreó mejor en su pregunta: ¿ se considera "seguro"else while sin llaves intermedias ?
mosquito
@JeffDavis - Sé que este hilo tiene dos años, pero Apple descubrió recientemente por qué no usar brackets no es una buena idea andrewbanks.com/…
Andrew
@ Andrew Por cierto, el lenguaje Swift de Apple ahora prohíbe explícitamente el control de flujo de una línea. Ese error podría ser una de las razones para hacerlo.
Sulthan
6

Siempre me han enseñado a mantener todo entre llaves, sangrado y comentarios. Creo que es mucho más fácil leer y detectar errores. Personalmente, creo que la modularidad es clave, por lo que siempre escribiría el código de esta manera:

    if(blah)
    {
     ....
    }
    else
    {
       while(!bloop()
       {
        bar;
       }
    }
CodeCompileHack
fuente
6

Me gustaría extraer método y hacerlo

if ( blah )
{
    ...
}
else
{
   newMethod();
}

Consulte el enfoque del "método de extracción" explicado en el sitio del Catálogo de refactorización :

Tiene un fragmento de código que se puede agrupar.

Convierta el fragmento en un método cuyo nombre explique el propósito del método.

void printOwing() {
    printBanner();

    //print details
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + getOutstanding());
}

                                                                                                         http://www.refactoring.com/catalog/arrow.gif

void printOwing() {
    printBanner();
    printDetails(getOutstanding());
}

void printDetails (double outstanding) {
    System.out.println ("name:    " + _name);
    System.out.println ("amount    " + outstanding);
}
user470365
fuente
Depende ... si, por ejemplo, el ciclo while usa datos de nivel de función, ahora tiene que agregar más datos al nivel de módulo (o clase, si usa C ++). Y si solo es un pequeño fragmento de código, estás en métodos triviales. Pero a veces, dependiendo de las circunstancias, estoy de acuerdo.
Andrew
1
Los compiladores +1 Smart C ++ pueden integrar una función En el entorno .Net, las funciones pequeñas son mejores debido a JIT.
Trabajo
4

Lo consideraría como un mal hábito de codificación. A veces funciona perfectamente bien y no tendrá problemas para compilar y ejecutar el código. En otras ocasiones, puede causar errores graves y terminarás pasando horas reparando ese error.

Siempre se recomienda modularizar su código. Si tiene que poner un bucle while en otra parte, póngalo en un bloque para que otros, cuando trabajen en su código, puedan comprender fácilmente la lógica.

if ( blah )
{
    ...
}
else
{
    while ( !bloop() )
    {
        bar();
    }
}

Es una buena práctica poner código en bloques. Hace que sea más simple y fácil de entender y depurar también.

Sandeep Gupta
fuente
4

Podría estar bien si sigue siendo así de simple, aunque personalmente no me gusta y mi preferencia es usar llaves incluso para los bloques de código if / else más simples. Es más ordenado para mí.

Sin embargo, cuando esto se vuelve desordenado es cuando ha anidado if / else bucles algunos con llaves y otros sin ellos. ¡Un bucle while en medio de todos esos espaguetis! He trabajado con un código tan malo y es una pesadilla depurar y entender. Esto sigue desde el primer punto, está bien cuando sigue siendo simple y estás contento con él, pero luego aparecen otros programadores y le agregan cosas, probablemente si no dentro del ciclo while. Si está escrito en primer lugar, entonces hay menos posibilidades de que esto suceda.

El punto es dejar las cosas claras para que otros programadores puedan ver de un vistazo lo que está bien y lo que está mal. Escriba el código para que el patrón se vea bien y no se mueva.

La otra cara de esto es que tal vez podría ver a algunas personas alegando que en ciertos casos esto se lee bien. Si tengo el recurso, necesito hacer este procesamiento mientras espero que algo haga esto. Incluso para mí, todavía no hay diferencia en anidar el bucle while dentro del bloque else.

Daniel Hollinrake
fuente
3

Bueno, a pesar de que todos discuten sobre el uso de aparatos ortopédicos y parecen amarlos, en realidad prefiero lo contrario. Solo uso llaves cuando tengo que hacerlo porque me parece más legible y conciso sin ellas.

if (...)
   foo();
else while(...)
   bar();

... De hecho, ¡encuentro este " else while(...)" notablemente legible! ¡Incluso se lee como un simple inglés! Pero supongo que todas las personas lo encontrarán extraño porque es inusual por decir lo menos.

Al final, todos tendemos a hacerlo a prueba de idiotas con llaves ... porque, bueno, ya sabes.

dagnelies
fuente
3
que va a ser especialmente legible después de algún mantenedor inocente cambia else while(...) bar();a algo así como else while(...) foobar(); bar();:)
mosquito
3
bueno, yo diría que es un mantenedor inocente bastante estúpido y peligroso . Conozco el principio de simplificarlo para evitar errores estúpidos ... pero ir tan lejos es bastante triste. Pero sabía que recibiría tales comentarios y votos negativos. No hay problema.
Dagnelies
2
"Siempre codifique como si la persona que mantendrá su código sea un psicópata violento que sepa dónde vive". ( Alan Braggins )
mosquito
1
Bueno, todo se reduce a lo que supones que sería el nivel más estúpido de alguien que trabaja en tu código. Sostengo que si su "mantenedor" se confunde con estas cuatro líneas de código ... entonces tiene un gran problema en sus manos. Y si es un psicópata violento, tienes dos. ;)
dagnelies
1
si , bueno, el enlace al que me refiero anteriormente, ha ampliado la versión de esta cita: Programador 1: 'Aquí hay una buena cita: "Codifique siempre como si la persona que mantendría su código sea un psicópata violento que sabe dónde vive". . Programador 2: (mira al mantenedor) '¿Qué quieres decir con "como si"?
mosquito
2

Siempre pongo llaves, solo porque podrías agregar otra línea cuando tengas prisa, sangrar, olvidar las llaves y rascarte la cabeza lo que está sucediendo. Mantengo el soporte de apertura en la misma línea, pero no importa. En ambos casos es mejor tenerlos.

if(blah) {
    foo();
}
else {
    bar();
}
Tsvetomir Dimitrov
fuente
¡Posicionar las llaves probablemente desencadena más argumentos que cualquier cosa más allá (o posiblemente incluida) de la religión!
Andrew
Convenido. Editaré mi respuesta para enfatizar en su existencia, no en su posición.
Tsvetomir Dimitrov
2

¿Qué hay de malo en los aparatos ortopédicos que tanta gente está tratando de evitar escribirlos?

¿Qué problema else whileresuelve exactamente ?

Los frenos son baratos y buenos, y hacen que la intención del código sea evidente y clara en lugar de inteligente e ingeniosa.

Citando la filosofía de Unix:

Regla de claridad: la claridad es mejor que la inteligencia.

Debido a que el mantenimiento es tan importante y costoso, escriba los programas como si la comunicación más importante que hicieran no fuera con la computadora que los ejecuta, sino con los seres humanos que leerán y mantendrán el código fuente en el futuro (incluido usted).

Tulains Córdova
fuente
1

No hay nada malo con

if (blah)
    foo();
else
    bar();

al igual que no hay nada malo con

if (blah) foo(); else bar();

en las circunstancias correctas (sus circunstancias pueden variar, pero ese estilo particular se usa mejor cuando tiene mucho código repetitivo; entonces la vista de cada línea es más importante que la sangría estilística)

Pero si elige una forma, manténgala: la consistencia es la reina. Entonces, su segundo ejemplo es muy malo, ya que la expresión if tenía corchetes para su declaración, la declaración while debe estar dentro de los corchetes para la cláusula else, no fuera de ella.


Además, he visto este código antes:

if (x) foo()
{
  bar();
}

y fue escrito por el propio nazi estándar de codificación (que insistió en paréntesis para todo).

gbjbaanb
fuente
1

Los IDE modernos se pueden configurar fácilmente para volver a formatear (incluida la eliminación o adición de llaves innecesarias) y / o reindentificar el código al guardar un archivo. Por lo tanto, su ejemplo se vería automáticamente, por ejemplo

if (blah) {
  blub();
} else
  while (!bloop()) {
    bar();
  }

La sangría siempre hace que el anidamiento sea fácilmente visible, incluso sin llaves innecesarias. Por lo tanto, si logra hacer cumplir tales configuraciones de IDE, no veo ningún riesgo.

Personalmente, encuentro que el código que omite los corchetes y los saltos de línea es mucho más legible ya que evita el desorden:

if (blah) blub();
else while (!bloop()) bar();

Pero, por supuesto, muchos desarrolladores están muy contentos de discutir sobre esas cosas para siempre y un día.

Hans-Peter Störr
fuente