¿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 usings
juntos 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:
- ¿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.
- ¿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?
- ¿Hay otro argumento que me estoy perdiendo?
Respuestas:
En realidad, la única vez que realmente me mordió fue cuando estaba depurando y comenté bar ():
Aparte de eso, tiendo a usar:
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.
fuente
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í:
Ligeramente más rápido de lo que leí:
Lo leo un poco más lento si se ve así:
Leí esto significativamente más lento que el anterior:
porque no puedo evitar leerlo nuevamente por si acaso y preguntarme si el autor pretendía:
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.
fuente
Si es algo pequeño, escríbalo así:
Si es lo suficientemente largo para dividirse en dos líneas, use llaves.
fuente
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í:
¿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.
fuente
!a || !b
) que ya sea con (!a
) o sin (a && !b
) llaves añadidas.Esto no siempre se considera una mala práctica. Las pautas de codificación del proyecto Mono sugieren no usar llaves si no es necesario. Lo mismo para los estándares de codificación GNU . Creo que es una cuestión de gusto personal como siempre con los estándares de codificación.
fuente
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).
fuente
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.
fuente
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:
yo prefiero
fuente
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 {}.
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.
fuente
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.
Lo que vino después fue
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.
Después de ver a un desarrollador superestrella haciendo eso.
fuente
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.
fuente
if
declaración controle un bloque, pero evite la necesidad de un bloque en los casos en que unaif
declaración controle una sola acción en lugar de un bloque.Estoy muy feliz de:
Personalmente, no veo por qué
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
vs
es terriblemente confuso, así que siempre lo escribo como:
Siempre que sea posible, uso operadores ternarios, pero nunca los anido .
fuente
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.
fuente
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.
fuente
Siempre hay excepciones, pero argumentaría en contra de omitir llaves solo cuando está en una de las formas:
De lo contrario, no tengo ningún problema con eso.
fuente
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
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).
fuente
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:
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.
fuente
De las tres convenciones:
y:
y (que representan cualquier estilo de sangría usando una llave de apertura y una de cierre):
Prefiero el último como:
fuente
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.
fuente
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;
Y otro como este;
Prefiero elegir un estilo general y seguir con él :)
fuente
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:
fuente
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:
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í:
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.
fuente
Usa un poco de juicio personal.
está bien por sí mismo. A menos que estés realmente preocupado porque los imbéciles pongan algo como esto más tarde:
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:
Cuál ha sido mi favorito desde que tengo memoria. Adicionalmente:
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.
fuente
if (parameter == null) return null;
.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:
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:
fuente
Para que el código con llaves no ocupe mucho espacio, utilizo la técnica recomendada en el libro Code Complete :
fuente
if
que 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 unaif
instrucció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 (...)`.Digamos que tienes un código:
y luego aparece alguien más y agrega:
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.
fuente
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.
fuente
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 )
vsif ( 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.fuente
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.
fuente
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:
Si la línea es demasiado engorrosa, use lo siguiente:
fuente