¿Está bien si omito las llaves en Java? [cerrado]

83

He buscado esto, pero no pude encontrar una respuesta y por alguna razón estaba demasiado avergonzado para preguntarle al profesor, debido a ese sentimiento cuando cientos de personas te miran ...

De todos modos, mi pregunta es ¿cuál es la importancia de tener corchetes? ¿Está bien si los omito? Ejemplo:

for (int i = 0; i < size; i++)  {
   a += b;
}

vs

for (int i = 0; i < size; i++)
   a += b;

Sé que ambos funcionarán, pero si omito los corchetes (que suelo hacer mucho debido a la visibilidad), ¿cambiará algo, algo en absoluto? Como dije, sé que funciona, lo probé una docena de veces, pero ahora algunas de mis asignaciones universitarias se están haciendo más grandes y, por alguna razón, tengo un miedo irracional de que, a la larga, esto me cause algunos problemas. ¿Hay alguna razón para temer eso?

vedran
fuente
Siempre uso un formateador de código para facilitar la lectura, ya que esto resuelve muchas causas potenciales de confusión. Esto puede hacer que el uso de corchetes sea redundante
Peter Lawrey

Respuestas:

146

No cambiará nada en absoluto, aparte de la capacidad de mantenimiento de su código. He visto un código como este:

for (int i = 0; i < size; i++)
   a += b;
   System.out.println("foo");

lo que significa esto:

for (int i = 0; i < size; i++)
   a += b;
System.out.println("foo");

... pero que debería haber sido este:

for (int i = 0; i < size; i++) {
   a += b;
   System.out.println("foo");
}

Personalmente siempre incluyo los corchetes para reducir la posibilidad de confusión al leer o modificar el código.

Las convenciones de codificación de todas las empresas para las que he trabajado han requerido esto, lo que no quiere decir que otras empresas no tengan convenciones diferentes ...

Y en caso de que piense que nunca haría una diferencia: tuve que corregir un error una vez que era prácticamente equivalente al código anterior. Fue muy difícil de detectar ... (es cierto que esto fue hace años, antes de que comenzara las pruebas unitarias, lo que sin duda habría facilitado el diagnóstico).

Jon Skeet
fuente
12
@vedran: ¿Entonces estás al tanto del problema pero estás asumiendo que nunca te morderá? ¿Y que todos los que lean su código sepan qué esperar? Solo digo: hay una razón por la que son obligatorios en las convenciones de codificación con las que he trabajado :)
Jon Skeet
12
Me sentí como una persona privada a la que un sargento se burlaba. Sí, aunque es más conveniente para mí, otros de mi grupo lo encuentran molesto y problemático. Me aseguraré de usar corchetes en todas partes a partir de ahora.
Vedran
13
@vedran bonita metáfora, excepto que Jon Skeet no es sargento, es el comandante en jefe :-)
stivlo
5
@stivlo Oh, estoy seguro de que su gracia perdonará la desobediencia menor;) Personalmente, pongo corchetes después de las declaraciones, porque es parte de todas las guías de codificación que he visto, pero creo que hoy es un argumento bastante débil. Con el formato de código automático en todas partes, nunca debería ver el código en su primera forma de todos modos y si la sangría es correcta, los corchetes no brindan ninguna información adicional.
Voo
4
Más argumento para usar SIEMPRE las llaves: imperialviolet.org/2014/02/22/applebug.html
MrTJ
32

El uso de llaves hace que el código sea más fácil de mantener y comprensible. Así que debería considerarlos por defecto .

A veces omito el uso de llaves en las cláusulas de guardia para hacer el código más compacto. Mi requisito para esto es que sean ifdeclaraciones seguidas de una declaración de salto , como returno throw. Además, los mantengo en la misma línea para llamar la atención sobre el idioma, por ejemplo :.

if (!isActive()) return;

También se aplican al código dentro de los bucles:

for (...) {
  if (shouldSkip()) continue;
  ...
}

Y a otras condiciones de salto de métodos que no están necesariamente en la parte superior del cuerpo del método.

Algunos lenguajes (como Perl o Ruby) tienen una especie de declaración condicional , donde no se aplican llaves:

return if (!isActive());
// or, more interestingly
return unless (isActive());

Lo considero equivalente a lo que acabo de describir, pero explícitamente respaldado por el lenguaje.

Jordão
fuente
7
Las cláusulas de guardia +1 dentro de los bucles suelen ser más claras sin las llaves.
Viccari
2
Acordó las cláusulas de guardia. Hace que el código sea más legible en mi opinión y, de hecho, aumenta la capacidad de mantenimiento. Sin embargo, los puntos que hace la respuesta aceptada son muy válidos, por lo que limitaría la omisión de llaves para proteger las cláusulas.
ChrisK
11

No hay diferencia. El principal problema con la segunda versión es que podrías terminar escribiendo esto:

for (...) 
  do_something();
  do_something_else();

cuando actualiza ese método, pensando que do_something_else()se llama dentro del ciclo. (Y eso lleva a sesiones de depuración de rascarse la cabeza).

Hay un segundo problema que la versión de corsé no tiene, y posiblemente sea aún más difícil de detectar:

for (int i=0; i<3; i++);
  System.out.println("Why on earth does this print just once?");

Así que mantén las llaves a menos que tengas una buena razón, son solo unas pocas teclas más.

Estera
fuente
3
El primer punto es bueno, pero el segundo es incorrecto. La versión de corsé todavía puede tener ese problema. para (int i = 0; i <3; i ++); {System.out.println ("¿Por qué se imprime esto solo una vez?"); }. Lo sé porque siempre uso llaves, pero a veces agrego por error puntos y comas adicionales.
emory
3
La versión de corsé puede tenerlo, pero es más visible si el corsé está en la misma línea. Con el aparato ortopédico en la siguiente línea, de hecho, es bastante desagradable.
Mat
La segunda versión para mí es tan importante como la primera, porque mirando la segunda versión es casi imposible detectar lo que está mal hasta que la ejecutes para ver qué está pasando en el mundo. Los desarrolladores dedican mucho tiempo a depurar código como este, que fácilmente se detectaría si se introdujeran esos corchetes ondulados. Para mí, omitir esos corchetes serpenteantes no es solo una cuestión de estilo, sino un buen indicador de un probable código defectuoso.
theyCallMeJun
5

Creo que perder las llaves es bueno, si también está utilizando el formato automático, porque su sangría siempre es correcta, por lo que será fácil detectar cualquier error de esa manera.

Decir que dejar las llaves es malo, extraño o ilegible es simplemente incorrecto, ya que todo el lenguaje se basa en esa idea y es bastante popular (Python).

Pero debo decir que sin usar un formateador puede ser peligroso.

Máté Magyar
fuente
La sangría importa en Python. En Java, C, C ++ u otros lenguajes de estilo C, no es así.
Christopher Schneider
1
@ChristopherSchneider Ese es el pont.
Máté Magyar
5

En la mayoría de los casos, las respuestas mencionadas hasta ahora son correctas. Pero tiene algunas desventajas desde la perspectiva de la seguridad. Habiendo trabajado en un equipo de pagos, la seguridad es un factor mucho más importante que motiva tales decisiones. Digamos que tiene el siguiente código:

if( "Prod".equals(stage) )
  callBankFunction ( creditCardInput )
else
  callMockBankFunction ( creditCardInput )

Ahora digamos que este código no funciona debido a algún problema interno. Quieres comprobar la entrada. Entonces haces el siguiente cambio:

if( "Prod".equals(stage) )
  callBankFunction ( creditCardInput )
else
  callMockBankFunction ( creditCardInput )
  Logger.log( creditCardInput )

Digamos que soluciona el problema e implementa este código (y tal vez el revisor y usted cree que esto no causará un problema ya que no está dentro de la condición 'Prod') Mágicamente, sus registros de producción ahora imprimen la información de la tarjeta de crédito del cliente que es visible para todo el personal que puede ver los registros. Dios no lo quiera si alguno de ellos (con intenciones maliciosas) se apodera de estos datos.

Por lo tanto, no dar una llave y un poco de codificación descuidada a menudo puede conducir a la violación de información segura. También está clasificada como una vulnerabilidad en JAVA por CERT - Software Engineering Institure, CMU .

kung_fu_coder
fuente
Yo diría que es un diseño bastante terrible en primer lugar, pero el punto es válido.
Christopher Schneider
4

Si tiene una sola declaración, puede omitir los corchetes, para más de una declaración, se necesitan corchetes para declarar un bloque de código.

Cuando usa corchetes, está declarando un bloque de código:

{

//Block of code
}

Los corchetes también deben usarse con una sola declaración cuando se encuentra en una situación de declaración anidada para mejorar la legibilidad, por ejemplo:

for( ; ; )
  if(a == b) 
    doSomething()

es más legible escrito con corchetes también si no es necesario:

for( ; ; ) {
  if(a == b) {
    doSomething()
   }
}
aleroot
fuente
4

Si usa corchetes, su código es más legible. Y si necesitas agregar algún operador en un mismo bloque puedes evitar posibles errores

Sergey Gazaryan
fuente
3

El uso de corchetes prueba el código en el futuro contra modificaciones posteriores. He visto casos en los que se omitieron los corchetes y alguien más tarde agregó un código y no puso los corchetes en ese momento. El resultado fue que el código que agregaron no entró en la sección que pensaban que sí. Así que creo que la respuesta es que es una buena práctica a la luz de futuros cambios en el código. He visto grupos de software adoptar eso como estándar, es decir, siempre requieren corchetes incluso con bloques de una sola línea por esa razón.

Nerdtron
fuente
Estoy de acuerdo con ésto. Los corchetes no son para ti. Son para la persona que viene detrás de ti. Varias veces, he tenido un código que mantenía que no conocía que no usaba corchetes y tenía una sangría incorrecta. En esta etapa, probablemente esté arreglando un error, así que es bueno saber qué se supone que debe suceder. Omitir llaves lo hace menos obvio, y tengo que repasar el código, perdiendo el tiempo.
Christopher Schneider
2

Más apoyo de mi parte para el grupo "always braces". Si omite llaves para bucles / ramas de declaración única, coloque la declaración en la misma línea que la declaración de control,

if (condition) doSomething();
for(int i = 0; i < arr.length; ++i) arr[i] += b;

de esa manera, es más difícil olvidarse de insertar aparatos ortopédicos cuando el cuerpo está expandido. Aún así, usa rizos de todos modos.

Daniel Fischer
fuente
2

el uso de llaves redundantes para afirmar que el código es más fácil de mantener plantea la siguiente pregunta: si los chicos que escriben, se preguntan y mantienen el código tienen problemas como los descritos anteriormente (relacionados con la sangría o la legibilidad), quizás no deberían programar en absoluto ... .


fuente
1

En cuanto al resultado, es lo mismo.

Solo dos cosas a considerar.

- Capacidad de mantenimiento del código
: código acoplado libremente. (puede ejecutar otra cosa porque no ha especificado el alcance del bucle).

Nota: En mi observación, si es un bucle dentro de un bucle. Inner Loop sin tirantes también es seguro. El resultado no variará.

Sireesh Yarlagadda
fuente
1

Si solo tiene una declaración dentro del ciclo, es lo mismo.

Por ejemplo, vea el siguiente código:

for(int i=0;i<4;i++)
            System.out.println("shiva");

solo tenemos una declaración en el código anterior. así que no hay problema

for(int i=0;i<4;i++)
            System.out.println("shiva");
            System.out.println("End");

Aquí tenemos dos declaraciones, pero solo la primera declaración entra dentro del ciclo, pero no la segunda declaración.

Si tiene varias declaraciones en un solo bucle, debe usar llaves.

NShiva
fuente
1

Si quita las llaves, solo leerá la primera línea de instrucción. No se leerán líneas adicionales. Si tiene más de 1 línea de instrucciones para ejecutar, por favor use llaves, o de lo contrario se lanzará una excepción.

Ashish Patel
fuente
1

Hoy en día, es muy fácil volver a sangrar códigos para saber qué bloque de códigos está en qué ifo for/ while. Si insiste en que es difícil volver a sangrar, los corchetes colocados en una sangría incorrecta pueden confundirlo igualmente.

for(int i = 0; i < 100; i++) { if(i < 10) {
    doSomething();
} else { for(int j = 0; j < 5; j++) {
        doSomethingElse();
    }
}}

Si haces esto en todas partes, tu cerebro se estropeará en poco tiempo. Incluso con corchetes, depende de la sangría para encontrar visualmente el inicio y el final de los bloques de código.

Si la sangría es importante, entonces ya debería escribir su código en la sangría correcta, para que otras personas no necesiten volver a sangrar sus códigos para leer correctamente.

Si desea argumentar que el ejemplo anterior es demasiado falso / deliberado, y que los corchetes están ahí para capturar un problema de sangría por descuido (especialmente cuando copia / pega códigos), considere esto:

for(int i = 0; i < 100; i++) {
    if(i < 10) {
    doSomething();
}
else {
    for(int j = 0; j < 5; j++) {
        doSomethingElse();
    }
}

Sí, parece menos serio que el ejemplo anterior, pero aún puede confundirse con tal sangría.

En mi humilde opinión, es responsabilidad de la persona que escribe el código verificar el código y asegurarse de que las cosas estén sangradas correctamente antes de proceder a hacer otras cosas.

Jai
fuente
0

también debería ser un reflejo reformatear el código ... eso es, por supuesto, para programadores profesionales en equipos profesionales


fuente
0

Probablemente sea mejor usar las llaves en todas partes por el simple hecho de que depurar esto sería una molestia extrema. Pero de lo contrario, una línea de código no necesita necesariamente el corchete. ¡Espero que esto ayude!

Ash_s94
fuente