¿Por qué se considera una mala práctica omitir llaves? [cerrado]


177

¿Por qué todos me dicen que escribir código como este es una mala práctica?

if (foo)
    Bar();

//or

for(int i = 0 i < count; i++)
    Bar(i);

Mi mayor argumento para omitir las llaves es que a veces puede ser el doble de líneas con ellas. Por ejemplo, aquí hay un código para pintar un efecto de brillo para una etiqueta en C #.

using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
{
    for (int x = 0; x <= GlowAmount; x++)
    {
        for (int y = 0; y <= GlowAmount; y++)
        {
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));
        }
     }
 }
 //versus
using (Brush br = new SolidBrush(Color.FromArgb(15, GlowColor)))
    for (int x = 0; x <= GlowAmount; x++)
        for (int y = 0; y <= GlowAmount; y++)
            g.DrawString(Text, this.Font, br, new Point(IconOffset + x, y));

También puede obtener el beneficio adicional de encadenar usingsjuntos sin tener que sangrar un millón de veces.

using (Graphics g = Graphics.FromImage(bmp))
{
    using (Brush brush = new SolidBrush(backgroundColor))
    {
        using (Pen pen = new Pen(Color.FromArgb(penColor)))
        {
            //do lots of work
        }
    }
 }
//versus
using (Graphics g = Graphics.FromImage(bmp))
using (Brush brush = new SolidBrush(backgroundColor))
using (Pen pen = new Pen(Color.FromArgb(penColor)))
{
    //do lots of work
}

El argumento más común para las llaves se basa en la programación de mantenimiento y los problemas que se producirían al insertar código entre la declaración if original y el resultado deseado:

if (foo)
    Bar();
    Biz();

Preguntas:

  1. ¿Está mal querer usar la sintaxis más compacta que ofrece el lenguaje? Las personas que diseñan estos idiomas son inteligentes, no puedo imaginar que pondrían una función que siempre es mala de usar.
  2. ¿Deberíamos o no deberíamos escribir código para que el mínimo común denominador pueda entender y no tener problemas para trabajar con él?
  3. ¿Hay otro argumento que me estoy perdiendo?

66
Estoy de acuerdo contigo. Omitirlos Período.
Andrei Rînea

67
A QUIÉN LE IMPORTA CUÁNTAS LÍNEAS ALGO ES EN 2010. ¡Los monitores son anchos, baratos y de alta resolución! ¡Mi monitor mide 2048 X 1152 y tengo DOS de ellos! La legibilidad es mucho más importante que guardar 2 líneas verticales cuando puede introducir fácilmente errores sutiles que son difíciles de encontrar.

51
Los monitores son anchos y baratos, pero no son altos y baratos. El espacio vertical es más escaso que el espacio horizontal.
Adam Says - Reinstate Monica

32
@AdamRuth Ponlos de lado :)
Zachary Yates

16
Así que no te equivocas como Apple con el error SSL encontrado en febrero de 2014, jajaja.
learnvst

Respuestas:


183

En realidad, la única vez que realmente me mordió fue cuando estaba depurando y comenté bar ():

if(foo)
  // bar();
doSomethingElse();

Aparte de eso, tiendo a usar:

if(foo) bar();

Que se encarga del caso anterior.

EDITAR Gracias por aclarar la pregunta, estoy de acuerdo, no debemos escribir código al mínimo común denominador.


31
Eso es difícil, por supuesto, pero creo que el mayor problema para los mantenedores es que agregarán una segunda línea y no se darán cuenta de que no es parte de la declaración condicional a pesar de que REALMENTE parece que debería ser.
danieltalsky

23
No me gusta el estilo de una línea porque siempre busco el cuerpo del bucle a continuación.
Nosredna

18
Encuentro que el estilo de una sola línea es más irritante que útil porque (especialmente en anidamiento profundo - ugh) la declaración puede ser fácilmente leída y puede producirse confusión. Sin embargo, uso casi exclusivamente dichos ifs de una sola declaración para la validación de entrada (es decir, los primeros retornos) o el control de bucle (por ejemplo, ignorando nombres de archivo irrelevantes en recorridos del sistema de archivos), donde las líneas en blanco ayudan a desencadenarlos del código principal.
Alan Plum

1
El estilo de una línea también oculta la barra () de la cobertura de prueba. Se verá cubierto incluso si foo siempre es falso.
Bohumil Janda

1
Esta es otra forma de decir: "si la fuente hubiera incluido las llaves, no habría perdido el tiempo en la depuración". - agregar las llaves es trivialmente simple y evita dejar escollos para la siguiente persona. El único argumento en contra es la "legibilidad", que es bastante tenue, dado que este es un caso en el que sucede algo implícitamente si los omite.
Andrew Theken el

156

Velocidad de lectura ...

Aparte de lo que ya se ha mencionado. En este punto, ya he sido condicionado a analizar si las declaraciones con llaves y espacios en blanco. Entonces leí:

if (condition)
{
    DoSomething();
}

DoSomethingElse();

Ligeramente más rápido de lo que leí:

if (condition) DoSomething();

DoSomethingElse();

Lo leo un poco más lento si se ve así:

if (condition) DoSomething();
DoSomethingElse();

Leí esto significativamente más lento que el anterior:

if (condition) 
    DoSomething();
DoSomethingElse();

porque no puedo evitar leerlo nuevamente por si acaso y preguntarme si el autor pretendía:

if (condition)
{
    DoSomething();
    DoSomethingElse();
}

Ya cubierto en general, pero cuando se trata de leer lo siguiente, lo investigaré durante bastante tiempo para asegurarme de lo que pretendía el autor. Incluso puedo cazar al autor original para confirmar.

if (condition) 
    DoSomething();
    DoSomethingElse();

29
El problema se resuelve cuando, en su cuarta muestra, simplemente coloca una línea vacía después de la instrucción if para separarla de DoSomethingElse () Eso es lo que hago y la legibilidad es prácticamente la misma que con la primera muestra (si no mejor ;-P) Otra cosa es que poner líneas en grupos de 2 o 3 ayuda significativamente a la lectura, simplemente escanea el código mucho más rápido.
Piotr Owsiak

66
Tal vez sea porque estoy acostumbrado a Python, pero poner la primera llave en la misma línea que la instrucción if me permite leerlo + entenderlo aún más rápido.
Ponkadoodle

16
El problema con el estilo sin llaves hace que desperdicies tu preciosa concentración pensando si el bloque tiene o no llaves en lugar de cosas más importantes. Esto por sí solo es una razón suficientemente buena para usar la convención más simple posible, que son los corchetes siempre.
Nate CK

2
Las llaves son explícitas por naturaleza. Me quedaré con eso, gracias.
TheOptimusPrimus

2
En el último caso, persiga al autor original y golpéelo ...;)
Per Lundberg

55

Si es algo pequeño, escríbalo así:

if(foo()) bar();

Si es lo suficientemente largo para dividirse en dos líneas, use llaves.


Sí, eso es lo que yo hago también. Te obliga a agregar llaves si agregas otra línea, y es bastante claro ver que bar () es realmente parte del if, por lo que sucederán cosas malas si solo lo comentas.
jalf

10
Sin embargo, no es muy amigable para el depurador. ¿Cómo se configura un punto de interrupción en la parte de "barra"?
Nemanja Trifunovic

9
@Nemanja: solo coloca el cursor en la barra (); y presiona F9. Tanto VS2005 como VS2008 manejan puntos de interrupción intralínea, si son "declaraciones" separadas.
GalacticCowboy

44
GalanticCowboy: Hay más entornos que los que conoces. :-)

20
Claro, pero dado que el contexto es C #, eso debería cubrir a una mayoría significativa de los usuarios ...
GalacticCowboy

47

También solía pensar que es mejor usar solo llaves cuando realmente se necesita. Pero ya no, la razón principal, cuando tiene mucho código, lo hace más legible y puede analizar el código más rápido cuando tiene un estilo de refuerzo consistente.

Otra buena razón para usar siempre llaves, además de que alguien agregue una segunda declaración al if, es algo así:

if(a)
   if(b)
     c();
else
   d();

¿Notó que la cláusula else es en realidad la del "if (b)"? Probablemente lo hiciste, pero ¿confiarías en que alguien esté familiarizado con este problema?

Entonces, si solo es por coherencia y porque nunca se sabe qué cosas inesperadas podrían suceder cuando alguien más (siempre son los demás los que son estúpidos) cambia el código, siempre pongo llaves, porque hace que el código fuente sea más legible y más rápido de analizar. tu cerebro. Solo para las declaraciones if más simples, como un if donde se hace una delegación o es como un interruptor, donde sabes que la cláusula nunca se extenderá, dejaría las llaves.


12
Este es uno de los dos casos en los que uso llaves. De otra forma no.
Andrei Rînea

3
Esto debería escribirse como si (a && b) ... en primer lugar, me parece.
alexander.biskop

8
@ alexander.biskop: Seguramente no, ya que eso le da al bloque else un significado diferente ( !a || !b) que ya sea con ( !a) o sin ( a && !b) llaves añadidas.
Ben Voigt

1
@Ben Voigt: ¡Cierto! Cayó por eso ;-) Medio año y dos votos más tarde, alguien se da cuenta de que la declaración que hice es incorrecta ... Supongo que no presté suficiente atención a los detalles, principalmente porque la intención detrás de mi comentario fue diferente a señalar una transformación técnicamente correcta de esa cláusula if. Lo que quise decir fue que las declaraciones if en línea anidadas generalmente disminuyen la legibilidad (y especialmente la trazabilidad del flujo de control) significativamente en mi humilde opinión y, por lo tanto, deberían combinarse en una sola declaración (o evitarse por completo). Saludos
alexander.biskop

3
@ alexander.biskop: al mismo tiempo, la depuración es más fácil con ifs anidados, cada uno con condiciones más simples, ya que puede pasar a cada uno de ellos.
Ben Voigt


35

Las líneas son baratas. La potencia del procesador es barata. El tiempo del desarrollador es muy costoso.

Como regla general, a menos que esté desarrollando una aplicación absolutamente crítica de recursos / velocidad, siempre me equivocaría al escribir código que sea

(a) Fácil para cualquier otro desarrollador seguir lo que estoy haciendo

(b) Comente partes específicas del código que puedan necesitarlo

(c) Fácil de depurar si algo sale mal

(d) Fácil de modificar si necesita ser en el futuro (es decir, agregar / eliminar código)

La velocidad o la elegancia académica del código es secundaria a estos factores desde una perspectiva empresarial. Esto no quiere decir que me propuse escribir código torpe o feo, pero este es MI orden de prioridad.

Al omitir las llaves en la mayoría de los casos, para mí hace que (b), (c) y (d) sean más difíciles (sin embargo, no es imposible). Yo diría que usar o no llaves no tiene efecto en (a).


9
Su última declaración sobre (a) es la opinión de que una gran cantidad de desarrolladores, incluidos otros carteles aquí, argumentarían.
Kelly S. French, el

34

Prefiero la claridad que ofrece la llave. Sabes exactamente lo que significa y no tienes que adivinar si alguien simplemente se burló y lo dejó (e introdujo un error). La única vez que los omito es cuando pongo el if y la acción en la misma línea. Yo tampoco hago eso muy a menudo. De hecho, prefiero el espacio en blanco introducido al colocar la llave en su propia línea, aunque después de años de programación similar a K&R C, terminar la línea con una llave es una práctica que tengo que superar si el IDE no lo impone. yo.

if (condition) action();  // ok by me

if (condition) // normal/standard for me
{
   action();
}

23

Creo que es una cuestión de pautas para el proyecto en el que está trabajando y el gusto personal.

Por lo general, los omito cuando no son necesarios, excepto algunos casos como los siguientes:

if (something)
    just one statement; // i find this ugly
else
{
    // many
    // lines
    // of code
}

yo prefiero

if (something)
{
    just one statement; // looks better:)
}
else
{
    // many
    // lines
    // of code
}

15

Una de las instancias en las que esto puede morderte es en los viejos tiempos de las macros C / C ++. Sé que esta es una pregunta de C #, pero a menudo los estándares de codificación se transfieren sin las razones por las cuales el estándar se creó en primer lugar.

Si no tiene mucho cuidado al crear sus macros, puede terminar causando problemas con las declaraciones if que no usan el {}.

#define BADLY_MADE_MACRO(x) function1(x); function2(x);

if (myCondition) BADLY_MADE_MACRO(myValue)

Ahora, no me malinterpreten, no estoy diciendo que siempre debas hacer {} solo para evitar este problema en C / C ++, pero he tenido que lidiar con algunos errores muy extraños debido a esto.


2
si solo todo el código se declarase como tal ... suspiro
Nathan Strong

15

Yo solía pensar de la misma manera.

Hasta que un día (¿por qué siempre hay ese "un día" que cambia su vida para siempre?) Pasamos de 24 a 36 horas seguidas sin dormir depurando el código de producción solo para descubrir que alguien no puso llaves combinadas con un cambio de búsqueda / reemplazo .

Fue algo como esto.

 if( debugEnabled ) 
      println( "About to save 1 day of work to some very important place.");
 saveDayData();

Lo que vino después fue

 if( debugEnabled ) 
 //     println( "About to save 1 day of work to some very important place.");
 saveDayData();

Resulta que el sistema generaba 500 mb de registros diarios y se nos pidió que lo detuviéramos. La marca de depuración no era suficiente, por lo que era necesario buscar y reemplazar println.

Sin embargo, cuando la aplicación entró en producción, el indicador de depuración estaba apagado y nunca se llamó al importante "saveDayData".

EDITAR

Ahora, el único lugar donde no uso las llaves es if / try construct.

if( object != null ) try { 
     object.close();
} catch( .....

Después de ver a un desarrollador superestrella haciendo eso.


3
No entiendo. ¿Tiene una variable que controla la depuración (debugEnabled) y aún usa comentarios para deshabilitar la depuración? ¿Por qué no estableciste debugEnabled en falso?
Igor Popov

Este no es exactamente el escenario, pero haces un buen punto. Las cosas estúpidas (como no establecer la depuración en falsa) crean errores sutiles y estúpidos que son más difíciles de encontrar que los errores "obvios". No usar llaves no ayudó demasiado en este caso.
OscarRyz

1
@igor ¿Qué tal porque solo querían eliminar una línea de registro, no todas las líneas de registro?
Gman

14

Para ser franco, lo veo como:

Los buenos programadores programan a la defensiva, los malos programadores no.

Dado que hay varios ejemplos anteriores y mis propias experiencias similares con errores relacionados con el olvido de los aparatos ortopédicos, aprendí el camino difícil SIEMPRE PONER BRAZOS.

Cualquier otra cosa es elegir un estilo personal sobre la seguridad y eso es claramente una mala programación.

Joel incluso menciona esto en Hacer que el código incorrecto parezca incorrecto

Una vez que te pica un error debido a la falta de llaves, aprendes que las llaves faltantes se ven mal porque sabes que es un lugar potencial para que ocurra otro error.


Si las llaves abiertas se colocan en líneas por sí mismas, cualquier lugar en el que dos o más líneas estén sangradas sin un par de llaves se verá mal, al igual que cualquier par de llaves sin igual. Tal uso costará una línea en blanco en los casos en que una ifdeclaración controle un bloque, pero evite la necesidad de un bloque en los casos en que una ifdeclaración controle una sola acción en lugar de un bloque.
supercat

14

Estoy muy feliz de:

foreach (Foo f in foos)
  foreach (Bar b in bars)
    if (f.Equals(b))
      return true;

return false;

Personalmente, no veo por qué

foreach (Foo f in foos)
{
  foreach (Bar b in bars)
  {
    if (f.Equals(b))
    {
      return true;
    }
  }
}

return false;

Es más legible.

Sí, las líneas son gratuitas, pero ¿por qué debería tener que desplazarme por páginas y páginas de código cuando podría ser la mitad del tamaño?

Si hay una diferencia en la legibilidad o mantenibilidad, entonces, seguro, ponga llaves ... pero en este caso no veo ninguna razón para hacerlo.

Además, siempre pondré llaves para anidar si es donde he anidado el de otra persona

if (condition1)
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();

vs

if (condition1)
  if (condition2)
    doSomething();
else (condition2)
  doSomethingElse();

es terriblemente confuso, así que siempre lo escribo como:

if (condition1)
{
  if (condition2)
    doSomething();
  else (condition2)
    doSomethingElse();
}

Siempre que sea posible, uso operadores ternarios, pero nunca los anido .


acabo de ver que esto casi sucede en mi código :) pensé que echaré un vistazo, y he aquí que ya está ahí :)
Noctis

10

Estoy de acuerdo en que "si eres lo suficientemente inteligente como para que alguien te pague por escribir código, debes ser lo suficientemente inteligente como para no depender únicamente de la sangría para ver el flujo del código".

Sin embargo ... se pueden cometer errores, y este es un problema para depurar ... especialmente si estás viendo el código de otra persona.


10

Mi filosofía es que si hace que el código sea más legible, ¿por qué no hacerlo?

Obviamente, debe trazar la línea en alguna parte, como encontrar ese medio feliz entre nombres de variables concisos y excesivamente descriptivos. Pero los corchetes realmente evitan errores y mejoran la legibilidad del código.

Puede argumentar que las personas lo suficientemente inteligentes como para ser codificadores serán lo suficientemente inteligentes como para evitar errores que contengan declaraciones sin corchetes. Pero, ¿puedes decir honestamente que nunca te has tropezado con algo tan simple como un error ortográfico? Minutia como este puede ser abrumador cuando se miran proyectos grandes.


77
Por supuesto, esto es muy subjetivo. Dejarlos apagados en algún momento mejora la legibilidad.
Brian Knoblauch

Es cierto, si alguna vez dejo los corchetes, mantengo una línea, como otros han mencionado. Me han mordido demasiadas veces, pero declaraciones sin corchetes de varias líneas. Incluso si sabe cuidarlo, de vez en cuando puede atraparlo.
James McMahon

10

Siempre hay excepciones, pero argumentaría en contra de omitir llaves solo cuando está en una de las formas:

if(x == y)
   for(/* loop */)
   {
      //200 lines
   }

//rampion's example:
for(/* loop */)
{
   for(/* loop */)
      for(/* loop */)
      {
         //several lines
      }
}

De lo contrario, no tengo ningún problema con eso.


44
Malos ejemplos En ambos casos, factorizaría esa línea 200 para bucle en su propio método, o preferiblemente en varios métodos.
Adam Jaskiewicz

2
Es cierto, pero sucede. Además, cada vez que un bloque es más largo que la pantalla del lector es alta, tendrá este problema. Y no puede controlar la altura de la pantalla de su lector de códigos. Es posible que solo vean un par de líneas a cada lado.
rampion

2
Sí pasa Eso no significa que deba suceder.
Adam Jaskiewicz

3
@AdamJaskiewicz Derecha. Sí pasa Tenemos que pensar en lo que sucede, en lugar de lo que debería suceder. Si pudiéramos limitarnos a lo que debería suceder, no tendríamos que preocuparnos por los errores.
Beska

10

De vez en cuando uso el código de fondo (múltiples declaraciones de uso), pero aparte de eso siempre pongo los corchetes. Simplemente encuentro que aclara el código. Es obvio por algo más que una simple sangría que una declaración es parte de un bloque (y, por lo tanto, probablemente parte de un if, etc.).

He visto el

if (...)
    foo();
    bar();

el error me muerde (o mejor dicho, "yo y mis colegas" - en realidad no presenté el error) una vez . Esto fue a pesar del hecho de que nuestros estándares de codificación en el momento recomendaban el uso de llaves en todas partes. Me tomó un tiempo sorprendentemente largo detectarlo, porque ves lo que quieres ver. (Esto fue hace unos 10 años. Tal vez lo encontraría más rápido ahora).

Por supuesto, si usa "llave al final de la línea", reduce las líneas adicionales incurridas, pero personalmente no me gusta ese estilo de todos modos. (Lo uso en el trabajo y lo encuentro menos desagradable de lo que esperaba, pero sigue siendo un poco desagradable).


Siempre argumento que la coherencia es más importante que el estilo real, ¿por qué deberíamos hacer una excepción solo en el caso de los usos?
Bob

@Bob: Buen punto, y solo lo hago ocasionalmente. No me gustaría fingir que tengo razones reales aquí :) En realidad, hay una razón razonable: anidar los usos (y solo los usos) de esa manera es bastante obvio, y aún así terminas con un bloqueo. No puedo ver el peligro de inmediato.
Jon Skeet

Lo que no quiere decir que no haya ningún peligro, por supuesto.
Jon Skeet

1
La mejor solución a este error: usar Python. (Broma, por supuesto.)
Joel Wietelmann

10

Estoy impresionado y humillado de que mis pares en este campo de la programación de computadoras (ustedes) no se desanimen ante la posibilidad de posibles errores cuando se saltan las llaves en bloques de una sola línea.

Supongo que significa que no soy inteligente. He cometido errores al respecto varias veces. He depurado los errores de otros en torno a esto. He visto que el software se envía con errores debido a esto (RDP a una máquina que ejecuta VS2002 y la fuente de su ventana de reloj se volverá inestable).

Si miro todos los errores que he cometido que podrían haberse evitado con un cambio en el estilo de codificación, la lista es muy larga. Si no hubiera cambiado mi enfoque en cada uno de estos casos, probablemente nunca lo habría logrado como programador. De nuevo, supongo que no soy inteligente. Para compensar, he sido un usuario incondicional de llaves en bloques de una sola línea durante mucho tiempo.

Dicho esto, algunas cosas han cambiado en el mundo que hacen que la regla "usarás llaves en bloques de una sola línea" sea menos relevante hoy que cuando Moisés nos la hizo saber:

  • Algunos lenguajes populares hacen que el problema desaparezca haciendo que la computadora lea la sangría, tal como lo hace el programador (por ejemplo, Python).

  • Mi editor se formatea automáticamente para mí, por lo que las posibilidades de que me engañe con la sangría se reducen mucho.

  • TDD significa que si introduzco un error porque me confunde un bloque de una sola línea, es mucho más probable que lo descubra rápidamente.

  • La refactorización y la expresividad del lenguaje significan que mis bloques son mucho más cortos, y los bloques de una sola línea ocurren con mucha más frecuencia que antes. Hipotéticamente, con una aplicación despiadada de ExtractMethod, posiblemente podría tener solo bloques de una sola línea en todo mi programa. (Me pregunto cómo sería eso)

De hecho, se puede obtener un beneficio distintivo de refactorizar sin piedad y omitir llaves en bloques de una sola línea: cuando ve llaves, puede sonar una pequeña alarma que dice "¡complejidad aquí! ¡Cuidado!". Imagina si esta fuera la norma:

if (condition) Foo();   // normal, everyday code

if (condition) 
{
    // something non-trivial hapening; pay attention!
    Foo();
    Bar();
}

Me estoy abriendo a la idea de cambiar mi convención de codificación a algo así como "los bloques de una sola línea pueden nunca tener llaves" o "si puedes poner el bloque en la misma línea que la condición, y todo cabe dentro de 80 caracteres, omita las llaves ". Ya veremos.


Como ex programador de Java, tengo que estar totalmente de acuerdo con que el formato automatizado sea la respuesta real al problema. Ni siquiera tiene que hacer que su editor agregue llaves automáticamente: solo la sangría automática puede ayudar a evitar muchas ambigüedades. Por supuesto, ahora que me he cambiado a Python, me he acostumbrado a formatear mi código correctamente en primer lugar.
Alan Plum

Siento lo mismo con los frenos. Se trata de la complejidad. Lo ideal sería tener solo bloques de una línea. Eso es lo que yo llamo legibilidad, no llaves innecesarias.
Igor Popov

9

De las tres convenciones:

if(addCurleyBraces()) bugFreeSofware.hooray();

y:

if(addCurleyBraces())
    bugFreeSofware.hooray();

y (que representan cualquier estilo de sangría usando una llave de apertura y una de cierre):

if(addCurleyBraces()) {
    bugFreeSofware.hooray();
}

Prefiero el último como:

  • Me resulta más fácil leer si todas las declaraciones if están escritas de manera uniforme.
  • Puede hacer que el software sea un poco más robusto y libre de errores. Sin embargo, todos los IDE modernos y los editores de texto avanzados tienen buenas características de sangría automática que creo que todos deberían usar siempre que no estropee el formato de comentarios o vaya en contra de los estándares del equipo (en muchos casos es posible crear un esquema de formato personalizado y compártelo con el equipo). Mi punto aquí es que si la sangría se realiza correctamente, el riesgo de introducción de errores se reduce un poco.
  • Prefiero que la expresión booleana y las declaraciones se ejecuten para estar en diferentes líneas. Me gusta poder marcar una fila con fines de depuración. Incluso si estoy usando un IDE donde puedo marcar una declaración y pasar a ella, es una operación interactiva y podría olvidar dónde comencé a depurar o al menos me llevará un poco más de tiempo revisar el código varios veces (ya que tengo que marcar la posición manualmente cada vez durante la depuración).

8

Sus argumentos principales contra el uso de llaves son que usan líneas adicionales y que requieren sangría adicional.

Las líneas son (casi) libres, minimizar el número de líneas en su código no debería ser un objetivo.

Y la sangría es independiente del uso de llaves. En su ejemplo de 'uso' en cascada, sigo pensando que debería sangrarlos incluso cuando omita las llaves.


8

Creo firmemente en escribir código ordenado y conciso, pero siempre usaría llaves. Encuentro que son una forma conveniente de ver rápidamente el alcance en el que existe una línea de código particular. No hay ambigüedad, solo se expone explícitamente frente a usted.

Algunos pueden decir que es un caso de preferencia, pero encuentro que el flujo lógico de un programa es mucho más fácil de seguir si es internamente consistente, y no creo que sea consistente escribir una declaración IF como esta;

if(x < y)
    x = y;
else
    y = x;

Y otro como este;

if(x < y)
{
    x = y;
    x++;
}
else
{
    y = x;
    y++;
}

Prefiero elegir un estilo general y seguir con él :)


7

Uno de los problemas principales es cuando tiene regiones de un solo revestimiento y de otro tipo, junto con la separación de la declaración de control ( for,if , lo que sea) y el extremo de la DECLARACIÓN.

Por ejemplo:

for (...)
{
  for (...)
    for (...) 
    {
      // a couple pages of code
    }
  // which for block is ending here?  A good text editor will tell you, 
  // but it's not obvious when you're reading the code
}

44
¿Por qué tienes un par de páginas de código en tu bucle for?
Adam Jaskiewicz

b / c Soy un terrón insensible y estoy obsesionado con deshacerme del "costo" de las llamadas a funciones. :)
rampion

44
Las dos páginas de código deben estar en una función separada, por lo general.
Jonathan Leffler

1
disculpe, quise decir que estaba jugando el papel de un terrón. Sin embargo, sostengo que el mismo problema puede ocurrir para regiones más cortas, cuando se ve a través de una pequeña ventana gráfica. Y eso está fuera del control del codificador.
rampion

7

Solía ​​ser un gran defensor de "¡las llaves son imprescindibles!", Pero desde que adopté las pruebas unitarias, descubro que mis pruebas unitarias protegen las declaraciones sin llaves de escenarios como:

if (foo)
    snafu();
    bar();

Con buenas pruebas unitarias, puedo omitir con confianza las llaves para declaraciones simples para mejorar la legibilidad (sí, eso puede ser subjetivo).

Alternativamente, para algo como lo anterior, probablemente alinearía eso para que se vea así:

if (foo) snafu();

De esa manera, el desarrollador que necesita agregar bar () a la condición, sería más apto para reconocer la falta de llaves y agregarlas.


2
Usted dijo "No lo necesito" y luego dio una razón para usarlo: ¡legibilidad!
tvanfosson

44
No confiaría en una Prueba de Unidad para encontrar eso. LINT quizás, prueba de unidad no!
Kristen

2
@Kristen: la idea de la prueba unitaria es afirmar el comportamiento del método. Si el comportamiento cambia (como se describió anteriormente), la prueba unitaria fallará. No veo el problema en eso.
Liggy

Pero, ¿por qué confiar en Unit Test para detectar lo obvio que debe solucionarse antes de ir a UT?
Andrew

7

Usa un poco de juicio personal.

if (foo)
  bar();

está bien por sí mismo. A menos que estés realmente preocupado porque los imbéciles pongan algo como esto más tarde:

if (foo)
  bar();
  baz();

Si no está preocupado por los imbéciles, está bien (no lo estoy; si no pueden obtener la sintaxis básica del código, este es el menor de sus problemas)>

A cambio, es mucho más legible.

El resto del tiempo:

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

Cuál ha sido mi favorito desde que tengo memoria. Adicionalmente:

if (foo) {
  bar();
  baz();
} else {
  qux();
}

Funciona para mi.

El espacio vertical en sí mismo no es terriblemente relevante, la legibilidad sí lo es. La llave de apertura en una línea por sí sola detiene la conversación para un elemento sintáctico, hasta que su ojo se mueve hacia la siguiente línea. No es lo que me gusta.


La única vez que prefiero el primer estilo es cuando tengo que volver inmediatamente o arrojar un error en caso de que algo esté mal. Al igual if (parameter == null) return null;.
nawfal

7

Bien, esta es una vieja pregunta que ha sido respondida a muerte. Tengo algo que agregar

Primero solo tengo que decir USE THE BRACES. Solo pueden ayudar a la legibilidad, y la legibilidad (¡para usted y para los demás!) Debe ser muy importante en su lista de prioridades a menos que esté escribiendo ensamblaje. Código ilegible siempre, siempre conduce a errores. Si encuentra que las llaves hacen que su código ocupe demasiado espacio, sus métodos probablemente sean demasiado largos. La mayoría o todos los métodos deben caber dentro de la altura de una pantalla si lo está haciendo bien, y Find (F3) es su amigo.

Ahora para mi adición: hay un problema con esto:

if (foo) bar();

Intente establecer un punto de interrupción que solo se alcanzará si se va a ejecutar bar (). Puede hacer esto en C # colocando el cursor en la segunda mitad del código, pero eso no es obvio y es un poco molesto. En C ++ no podías hacerlo en absoluto. Uno de nuestros desarrolladores más antiguos que trabaja en código C ++ insiste en dividir las declaraciones 'if' en dos líneas por este motivo. Y estoy de acuerdo con él.

Entonces haz esto:

if (foo)
{
    bar(); //It is easy to put a breakpoint here, and that is useful.
}

2
Haga clic derecho en la barra y elija Insertar punto de interrupción ... No es nada difícil. Conoce tus herramientas.
Bob

Hacer clic derecho en la barra indicadora no hace nada; ¿te refieres a hacer clic derecho en el texto? De todos modos, si solo desea que se alcance el punto de ruptura cuando la declaración "if" es verdadera y "bar ()" está en su propia línea, puede colocar el cursor en cualquier lugar de esa línea y presionar F9, o hacer clic con el botón izquierdo margen indicador Sin embargo, si todo el código está en una sola línea, debe colocar el cursor en "barra ()" o hacer clic con el botón derecho exactamente allí antes de presionar F9, y hacer clic en el margen del indicador no funcionará (coloca el punto de interrupción en el ' Si'). No es "difícil", pero requiere menos concentración cuando el código está en dos líneas.
piedra

Oh, ja, ja, haga clic derecho en "bar ()". Te refieres al texto. Gotcha Seguro, o simplemente pulse F9 ...
piedra

>> debe colocar el cursor en "barra ()" o hacer clic con el botón derecho exactamente allí antes de presionar F9, (quise decir colocar el cursor exactamente allí antes de presionar F9 o hacer clic con el botón derecho)
piedra

7

Para que el código con llaves no ocupe mucho espacio, utilizo la técnica recomendada en el libro Code Complete :

if (...) {
    foo();
    bar();
}
else {
    ...
}

No entiendo por qué se modificó, ahorra una línea por cada par de brackets, lo uso todo el tiempo
Eric

2
Esto se conoce más popularmente como estilo K&R. Basado en el libro The C Programming Language de Kernighan y Ritchie: en.wikipedia.org/wiki/The_C_Programming_Language_(book) . Y no debería molestarte.
jmucchiello

¡Gracias! Pensé que era solo un gusto personal. Solía ​​molestarme esta sintaxis, pero la adopté después de leer Code Complete, y realmente la disfruto ahora.
Nathan Prather el

Estaba leyendo todas las respuestas por encima de esta pensando "¿por qué nadie ha sugerido esto todavía?" Hace que el corchete de cierre se alinee con el bloque que se está cerrando, es decir "si" o "mientras", etc., no es un "{" sin sentido. +1.
nickf

Si las llaves abiertas siempre se colocan en líneas por sí mismas, entonces una ifque es seguida por una sola línea con sangría puede reconocerse visualmente como el control de una sola declaración sin necesidad de llaves. El estilo de abrazadera por sí mismo ahorra espacio en blanco en la situación en la que una ifinstrucción controla algo que es semánticamente una sola acción (a diferencia de una secuencia de pasos que solo contiene un solo paso). Por ejemplo, if (someCondition)/ `lanzar una nueva SomeException (...)`.
supercat

6

Digamos que tienes un código:

if (foo)
    bar();

y luego aparece alguien más y agrega:

if (foo)
    snafu();
    bar();

Según la forma en que está escrito, bar (); ahora se ejecuta incondicionalmente. Al incluir las llaves, evita este tipo de error accidental. El código debe estar escrito de tal manera que haga que tales errores sean difíciles o imposibles de cometer. Si estaba haciendo una revisión del código y veía las llaves faltantes, especialmente en varias líneas, crearía un defecto. En los casos en que esté justificado, manténgalo en una línea para que la posibilidad de cometer dicho error se reduzca nuevamente al mínimo.


Ese punto ya se hizo en la pregunta.
Mike Scott

No del todo, en realidad. Sí, mencionó el potencial de este tipo de error, pero estaba hablando de hacer que su código sea a prueba de errores y eliminar el potencial de error como parte de las mejores prácticas.
Elie

¿Existe realmente un código a prueba de errores?
Bob

No, pero puedes hacerlo más difícil. Lea "Los secretos mejor guardados de la revisión del código de pares" por Jason Cohen (vea el enlace al lado de algunas páginas aquí) para tener una mejor idea de por qué hace esto.
Elie

¿Quién es este Mike Scott y por qué es él la respuesta policial? Siempre me sorprende que la gente tenga que decir lo que es obvio. Entonces, ¿por qué Mike no continuó comentando sobre la descripción agregada que los usuarios están publicando sobre este problema? ¿No se refieren todas las respuestas a la pregunta?
bruceatk

6

Reducir líneas no es realmente un buen argumento para soltar llaves. Si su método es demasiado grande, probablemente debería refactorizarse en piezas más pequeñas o reestructurarse. Hacer eso sin duda aumentará la legibilidad más que simplemente sacar los frenos.


5

Siempre los omito cuando es apropiado, como en su primer ejemplo. El código limpio y conciso que puedo ver y comprender al mirar es más fácil de mantener, depurar y comprender que el código que tengo que recorrer y leer línea por línea. Creo que la mayoría de los programadores estarán de acuerdo con esto.

Es fácil que se salga de control si comienzas a hacer múltiples anidaciones, cláusulas if / else, etc., pero creo que la mayoría de los programadores deberían poder decir dónde dibujar la línea.

Lo veo un poco como el argumento a favor if ( foo == 0 )vs if ( 0 == foo ). Este último puede evitar errores para los nuevos programadores (y tal vez incluso ocasionalmente para los veteranos), mientras que el primero es más fácil de leer y comprender rápidamente cuando se mantiene el código.


4

La mayoría de las veces está arraigada como un estándar de codificación, ya sea para una empresa o un proyecto FOSS.

En última instancia, alguien más necesitará asimilar su código y es una pérdida de tiempo importante para cada desarrollador tener que descubrir el estilo específico de la sección de código en la que están trabajando.

Además, imagine que alguien pasa entre Python y un lenguaje Cish más de una vez al día ... En Python, la sangría es parte de la sintaxis de bloque del lenguaje y sería bastante fácil cometer un error como el que usted cita.


+1 para comentarios sobre python. Siempre me sorprende lo "estúpido" que puedo ser al cambiar continuamente de idioma.
Kena

3

Errar en el lado de más seguro: solo un error más que potencialmente no tendrá que corregir.

Personalmente, me siento más seguro si todos mis bloques están envueltos en rizos. Incluso para frases sencillas, estas son anotaciones simples que evitan errores fácilmente. Hace que el código sea más legible en el sentido de que ve claramente lo que hay en el bloque para no confundir el cuerpo del bloque con las siguientes declaraciones fuera del bloque.

Si tengo una línea, normalmente la formateo de la siguiente manera:

if( some_condition ) { do_some_operation; }

Si la línea es demasiado engorrosa, use lo siguiente:

if( some_condition )
{
    do_some_operation;
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.