¿Es una mala práctica usar una declaración if sin llaves? [cerrado]

130

He visto un código como este:

if(statement)
    do this;
else
    do this;

Sin embargo, creo que esto es más legible:

if(statement){
    do this;
}else{
    do this;
}

Dado que ambos métodos funcionan, ¿es simplemente una cuestión de preferencia cuál usar o se recomendaría de una forma sobre la otra?

jerebear
fuente
En mi opinión, es malo, porque comienzas a confiar en la sangría de espacios en blanco que casi nunca es completamente consistente. Se descarrila el tren de pensamiento del lector cuando tienen que preocuparse por tales cosas.
Sridhar Sarnobat

Respuestas:

212

El problema con la primera versión es que si regresa y agrega una segunda declaración a las cláusulas if o else sin recordar agregar las llaves, su código se romperá de maneras inesperadas y divertidas.

En cuanto al mantenimiento, siempre es más inteligente usar la segunda forma.

EDITAR: Ned señala esto en los comentarios, pero vale la pena vincularlo aquí, creo. Esto no es solo una mierda hipotética de la torre de marfil: https://www.imperialviolet.org/2014/02/22/applebug.html

clee
fuente
17
Y siempre debe codificar la mantenibilidad. Después de todo, estoy bastante seguro de que al compilador no le importa qué forma usa. Sin embargo, sus compañeros de trabajo pueden ser molestos si introduce un error debido a un error tonto de llaves.
Esteban Araya
12
O podría usar un lenguaje que no use paréntesis para bloques de código ...
Tor Valamo
10
@ lins314159 - No, me refiero a Python. Porque soy machista a este respecto.
Tor Valamo
17
Otros errores de prueba pueden suceder (y lo hacen): imperialviolet.org/2014/02/22/applebug.html
Ned
8
Afirmar que el error SSL es un argumento a favor de las llaves es falso. No es como si el desarrollador tuviera la intención de escribir if (…) { goto L; goto L; }pero olvidó las llaves. Es pura coincidencia que `` if (...) {goto L; ir a L; } `no es un error de seguridad, porque sigue siendo un error (solo que no tiene consecuencias de seguridad). En otro ejemplo, las cosas podrían ir en la dirección opuesta y el código sin llaves podría ser accidentalmente seguro. En un tercer ejemplo, el código sin llaves inicialmente estaría libre de errores y el desarrollador introduciría un error tipográfico al agregar las llaves.
Pascal Cuoq
112

Un problema con omitir bloques de instrucciones es la ambigüedad de lo contrario. Es decir, los lenguajes inspirados en C ignoran la sangría y, por lo tanto, no tienen forma de separar esto:

if(one)
    if(two)
        foo();
    else
        bar();

De esto:

if(one)
    if(two)
        foo();
else
    bar();
doynax
fuente
8
Este es un problema mucho más serio que el mencionado en la respuesta superior (agregando una segunda declaración).
3
de hecho, esta respuesta realmente me llevó de leer estas respuestas cínicamente a estar un poco preocupado, es posible que haya cometido este error.
omikes
2
Si alguien más se preguntaba cómo era C de qué manera lo interpreta, una prueba que hice con GCC interpreta este código de la primera manera. tpcg.io/NIYeqx
horta
2
"ambigüedad" es el término equivocado. No hay ambigüedad alguna en cómo el analizador verá esto: se elseune con avidez al más cercano, más interno if. El problema surge cuando las personas que no saben esto, no lo piensan o no tienen suficiente café todavía están codificando C o lenguajes similares, por lo que escriben un código que creen que hará una cosa, pero el la especificación del idioma dice que el analizador tiene que hacer otra cosa, que podría ser muy diferente. Y sí, ese es otro argumento sólido a favor de incluir siempre llaves incluso si la gramática las señala como teóricamente 'innecesarias'.
underscore_d
35

Mi patrón general es que si cabe en una línea, haré:

if(true) do_something();

Si hay una cláusula else, o si el código en el que quiero ejecutar truees de longitud significativa, usa llaves todo el tiempo:

if(true) {
    do_something_and_pass_arguments_to_it(argument1, argument2, argument3);
}

if(false) {
    do_something();
} else {
    do_something_else();
}

En definitiva, se trata de una cuestión subjetiva de estilo y legibilidad. Sin embargo, el mundo de la programación general se divide en dos partes (para los idiomas que usan llaves): o úselas todo el tiempo sin excepción, o úselas todo el tiempo con excepción. Soy parte del último grupo.

Matchu
fuente
44
Aunque, tan fácil como es escribir if(true){ do_something(); }, ¿por qué arriesgarse a que otro programador introduzca un error grave en el futuro? (Busque el error de código ssl total "goto fail" de Apple).
Craig
9
Ninguna cantidad de paréntesis liberará al mantenedor del uso de su cerebro. Apoyo la idea de "sin paréntesis si cabe en una línea" porque, bueno, para mí, ese if es solo una versión del operador ternario if donde no es necesario hacer nada en la parte "after:" de ternario. Y ¿por qué alguien introducir a los soportes ternaria si ?
Michal M
No estoy de acuerdo en absoluto en que, en última instancia, sea subjetiva, ni que solo afecte el estilo y la legibilidad. Como alguien que ha perdido el tiempo tratando de depurar los problemas que resultaron, fueron causados ​​por la falta de delimitadores de bloque (y sin darse cuenta de su ausencia), porque tuve que usar un estilo de codificación que los omite cuando es 'innecesario', y quién ha leído sobre numerosos errores terribles causados ​​por tales estilos de codificación. Creo que este es un problema muy objetivo y práctico. Claro, con un estilo de delimitadores obligatorios, aún podemos olvidarlos, pero seguramente, al menos, la memoria muscular nos hace mucho menos propensos a hacerlo.
underscore_d
10

Estoy usando el formateador de código del IDE que uso. Eso puede diferir, pero se puede configurar en Preferencias / Opciones.

Me gusta este:

if (statement)
{
    // comment to denote in words the case
    do this;
    // keep this block simple, if more than 10-15 lines needed, I add a function for it
}
else
{
    do this;
}
Pentium10
fuente
55
Siendo un problema de estilo completamente subjetivo, personalmente no me gusta la redundancia de las líneas de solo corsé. Pero hey.
Matchu
14
Yo apoyo este estilo. La mayoría de las personas leen el código de izquierda a derecha y eso hace que nuestros ojos se fijen en el borde izquierdo de la pantalla. Ayuda a separar visualmente y extraer código a bloques lógicos de pasos.
mloskot
66
Siempre he preferido este estilo. Mucho más fácil de encontrar el paréntesis de cierre correspondiente. ¿Entonces ocupa mucho espacio? Usa una fuente más pequeña.
2010 a las 23:41
44
Siempre me resulta más fácil "escanear" a través del código cuando las llaves están en líneas separadas. Eso vale para todo; clases, métodos, declaraciones if y while, etc. Nunca me gustó tener ese primer aparato ortopédico en la misma línea ...
Svish
2
El espacio en blanco es barato, especialmente cuando tiene un IDE con capacidad de plegado de código.
Moo
10

La "regla" que sigo es esta:

Si la instrucción "if" se está probando para hacer algo (funciones de llamada de IE, configurar variables, etc.), use llaves.

if($test)
{
    doSomething();
}

Esto se debe a que siento que debe dejar en claro qué funciones se están llamando y hacia dónde va el flujo del programa, en qué condiciones. Hacer que el programador entienda exactamente qué funciones se llaman y qué variables se configuran en esta condición es importante para ayudarlo a comprender exactamente lo que está haciendo su programa.

Si la instrucción "if" se está probando para dejar de hacer algo (control de flujo de IE dentro de un bucle o función), use una sola línea.

if($test) continue;
if($test) break;
if($test) return;

En este caso, lo que es importante para el programador es descubrir rápidamente cuáles son los casos excepcionales en los que no desea que se ejecute el código, y todo eso está cubierto en $ test, no en el bloque de ejecución.

Marcus Harrison
fuente
8

Tener los aparatos correctos desde el primer momento debería ayudar a evitar que tenga que depurar esto:

if (statement)
     do this;
else
     do this;
     do that;
Matt Bishop
fuente
1
Esa parece ser la razón aceptada, pero (para jugar el abogado del diablo aquí) ¿una sola regla adicional de resaltado de sintaxis no resolvería esto, al mismo tiempo que guarda una línea?
Ken el
2
También tendrá un IDE que corrige la sangría cuando golpeas ;:)
Sam Harwell
6

Use llaves para todas las declaraciones if, incluso las simples. O reescriba una declaración if simple para usar el operador ternario:

if (someFlag) {
 someVar= 'someVal1';
} else {
 someVar= 'someVal2';
}

Se ve mucho mejor así:

someVar= someFlag ? 'someVal1' : 'someVal2';

¡Pero solo use el operador ternario si está absolutamente seguro de que no hay nada más que deba ir en los bloques if / else!

potencias de sotavento
fuente
2

Desde mi experiencia, la única (muy) ligera ventaja de la primera forma es la legibilidad del código, la segunda forma agrega "ruido".

Pero con los IDE modernos y la autogeneración de código (o autocompletado), le recomiendo usar la segunda forma, no pasará más tiempo escribiendo llaves y evitará algunos de los errores más frecuentes.

Hay suficientes errores que consumen energía, la gente simplemente no debe abrir puertas por grandes pérdidas de tiempo.

Una de las reglas más importantes para recordar al escribir código es la coherencia. Cada línea de código debe escribirse de la misma manera, sin importar quién la haya escrito. Ser riguroso evita que los errores "sucedan";)

Esto es lo mismo con nombrar clara y explícitamente sus variables, métodos, archivos o con sangría correcta ...

Cuando mis alumnos aceptan este hecho, dejan de luchar contra su propio código fuente y comienzan a ver la codificación como una actividad realmente interesante, estimulante y creativa. ¡Desafían sus mentes, no sus nervios!

thomas.g
fuente
2

Es una cuestión de preferencia. Personalmente uso ambos estilos, si estoy razonablemente seguro de que no necesitaré agregar más declaraciones, utilizo el primer estilo, pero si eso es posible, utilizo el segundo. Como no puede agregar más declaraciones al primer estilo, he oído que algunas personas recomiendan no usarlo. Sin embargo, el segundo método incurre en una línea de código adicional y si usted (o su proyecto) usa este tipo de estilo de codificación, el primer método es muy preferido para declaraciones if simples:

if(statement)
{
    do this;
}
else
{
    do this;
}

Sin embargo, creo que la mejor solución a este problema está en Python. Con la estructura de bloques basada en espacios en blanco, no tiene dos métodos diferentes para crear una instrucción if: solo tiene uno:

if statement:
    do this
else:
    do this

Si bien eso tiene el "problema" de que no puedes usar los frenos en absoluto, obtienes el beneficio de que no son más líneas que el primer estilo y tienen el poder de agregar más declaraciones.

Grant Paul
fuente
Por mí mismo, creo que la forma en que Python maneja las declaraciones if-else es muy feo, pero, de nuevo, todavía no soy un programador de Python
helpermethod
1

Siempre he intentado que mi código sea estándar y se vea lo más parecido posible. Esto facilita que otros lo lean cuando están a cargo de actualizarlo. Si haces tu primer ejemplo y le agregas una línea en el medio, fallará.

No funcionará

if (declaración) haz esto; y esto; si no, haz esto;

Joe
fuente
1

Personalmente utilizo el primer estilo solo lanzo una excepción o regreso de un método prematuramente. Como argumento Comprobación al comienzo de una función, porque en estos casos, rara vez tengo que hacer más de una cosa, y nunca hay otra.

Ejemplo:

if (argument == null)
    throw new ArgumentNullException("argument");

if (argument < 0)
    return false;

De lo contrario, uso el segundo estilo.

Nate Heinrich
fuente
1

Mi preferencia personal es usar una mezcla de espacios en blanco y corchetes como este:

if( statement ) {

    // let's do this

} else {

    // well that sucks

}

Creo que esto se ve limpio y hace que mi código sea muy fácil de leer y, lo más importante, depurar.

Simón
fuente
0

Estoy de acuerdo con la mayoría de las respuestas en el hecho de que es mejor ser explícito en su código y usar llaves. Personalmente, adoptaría un conjunto de estándares de codificación y me aseguraría de que todos en el equipo los conozcan y se ajusten. Donde trabajo utilizo estándares de codificación publicados por IDesign.net para proyectos .NET.

Kane
fuente
0

Prefiero poner un aparato ortopédico rizado. Pero a veces, el operador ternario ayuda.

En vez de :

int x = 0;
if (condition) {
    x = 30;
} else {
    x = 10;
}

Uno simplemente debería hacer: int x = condition ? 30 : 20;

También imagine un caso:

if (condition)
    x = 30;
else if (condition1)
    x = 10;
else if (condition2)
    x = 20;

Sería mucho mejor si te pusieras la llave.

fastcodejava
fuente