Digamos que tengo una condición booleana a AND b OR c AND d
y estoy usando un lenguaje donde AND
tiene un orden de operación más alto que OR
. Podría escribir esta línea de código:
If (a AND b) OR (c AND d) Then ...
Pero realmente, eso es equivalente a:
If a AND b OR c AND d Then ...
¿Hay algún argumento a favor o en contra que incluya paréntesis extraños? ¿La experiencia práctica sugiere que vale la pena incluirlos para facilitar la lectura? ¿O es una señal de que un desarrollador realmente necesita sentarse y confiar en los conceptos básicos de su idioma?
coding-style
operator-precedence
Jeff Bridgman
fuente
fuente
2 * 3 + 2
puede ser el mismo(2 * 3) + 2
pero el segundo es más fácil de leer.Respuestas:
Los buenos desarrolladores se esfuerzan por escribir código que sea claro y correcto . Los paréntesis en condicionales, incluso si no son estrictamente necesarios, ayudan con ambos.
En cuanto a la claridad , piense en paréntesis como comentarios en el código: no son estrictamente necesarios, y en teoría un desarrollador competente debería ser capaz de descifrar el código sin ellos. Y, sin embargo, estas señales son extremadamente útiles, porque:
Además, los paréntesis adicionales, al igual que las sangrías, los espacios en blanco y otros estándares de estilo, ayudan a organizar visualmente el código de una manera lógica.
En cuanto a la corrección , las condiciones sin paréntesis son una receta para errores tontos. Cuando suceden, pueden ser errores que son difíciles de encontrar, porque a menudo una condición incorrecta se comportará correctamente la mayor parte del tiempo y solo ocasionalmente fallará.
E incluso si lo hace bien, la siguiente persona que trabaje en su código puede no hacerlo, ya sea agregando errores a la expresión o malinterpretando su lógica y, por lo tanto, agregando errores en otros lugares (como señala LarsH correctamente).
Siempre uso paréntesis para expresiones que combinan
and
yor
(y también para operaciones aritméticas con problemas de precedencia similares).fuente
Importa menos si se confía en su conocimiento de la lengua. Lo que más importa es la comprensión del lenguaje del n00b que te sigue.
Escriba su código de la manera más clara e inequívoca posible. Los paréntesis adicionales a menudo (pero no siempre) ayudan. Poner solo una declaración en una línea a menudo ayuda. La consistencia en el estilo de codificación a menudo ayuda.
Hay demasiados paréntesis, pero es una de esas situaciones en las que no necesitará consejo: lo sabrá cuando lo vea. En ese punto, refactorice su código para reducir la complejidad de la declaración en lugar de eliminar el paréntesis.
fuente
There is such a thing as too many parenthesis
- obviamente no eres un lisper;)si
Siempre debes usar paréntesis ... no controlas el orden de precedencia ... el desarrollador del compilador sí. Aquí hay una historia que me sucedió sobre el no uso de paréntesis. Esto afectó a cientos de personas durante un período de dos semanas.
Razón del mundo real
Heredé una aplicación de marco principal. Un día, de la nada, dejó de funcionar. Eso es todo ... poof se detuvo.
Mi trabajo consistía en hacerlo funcionar lo más rápido posible. El código fuente no había sido modificado durante dos años, pero de repente simplemente se detuvo. Traté de compilar el código y se rompió en la línea XX. Miré la línea XX y no podía decir qué haría que la línea XX se rompiera. Pedí las especificaciones detalladas para esta aplicación y no había ninguna. La línea XX no fue la culpable.
Imprimí el código y comencé a revisarlo de arriba hacia abajo. Comencé a crear un diagrama de flujo de lo que estaba sucediendo. El código era tan complicado que apenas podía entenderlo. Dejé de tratar de hacer un diagrama de flujo. Tenía miedo de hacer cambios sin saber cómo ese cambio afectaría el resto del proceso, especialmente porque no tenía detalles de lo que hizo la aplicación o dónde estaba en la cadena de dependencia.
Entonces, decidí comenzar en la parte superior del código fuente y agregar espacios en blanco y frenos de línea para que el código sea más legible. Noté, en algunos casos, si las condiciones se combinaban
AND
yOR
no se distinguía claramente entre qué datos se estabanAND
editando y qué datos se estabanOR
editando. Así que empecé a poner paréntesis alrededor de losAND
y lasOR
condiciones para que sean más legibles.A medida que avanzaba lentamente para limpiarlo, periódicamente guardaba mi trabajo. En un momento intenté compilar el código y sucedió algo extraño. El error había pasado la línea de código original y ahora estaba más abajo. Así que continué, speparating el
AND
yOR
condiciones con parens. Cuando terminé de limpiarlo funcionó. Imagínate.Luego decidí visitar el taller de operaciones y preguntarles si habían instalado recientemente algún componente nuevo en el marco principal. Dijeron que sí, recientemente actualizamos el compilador. Hmmmm
Resulta que el antiguo compilador evaluó la expresión de izquierda a derecha independientemente. La nueva versión del compilador también evaluó expresiones de izquierda a derecha pero código ambiguo, lo que significa una combinación poco clara
AND
yOR
no se pudo resolver.Lección que aprendí de esto ... SIEMPRE, SIEMPRE, SIEMPRE use parens para
AND
condiciones separadas yOR
condiciones cuando se usan en conjunción entre sí.Ejemplo simplificado
IF Product = 191 OR Product = 193 AND Model = "ABC" OR Product = 201 OR Product = 202 AND Model = "DEF" ...
(código lleno de varios de estos)Esta es una versión simplificada de lo que encontré. También había otras condiciones con sentencias lógicas booleanas compuestas.
Recuerdo haberlo cambiado a:
IF ((Product = 191 OR Product = 193) AND Model = "ABC") OR ((Product = 201 OR Product = 202) AND Model = "DEF") ...
No pude reescribirlo porque no había especificaciones. El autor original ya se había ido. Recuerdo una intensa presión. Todo un buque de carga quedó varado en el puerto y no se pudo descargar porque este pequeño programa no funcionó. Sin advertencia. No hay cambios en el código fuente. Solo se me ocurrió preguntarle a las operaciones de red si modificaron algo después de que noté que agregar parens cambiaba los errores.
fuente
Sí, si se mezclan 'y' y 'o'.
También es una buena idea () lo que lógicamente es un cheque.
Aunque lo mejor es usar funciones de predicado bien nombradas y desalojar la mayoría de las comprobaciones y condiciones allí, dejando si es simple y legible.
fuente
a AND b
probable que deba reemplazarse con una función o un valor de bool precalculado que tenga un nombre más descriptivo.Los paréntesis son semánticamente redundantes, por lo que al compilador no le importa, pero eso es una pista falsa: la verdadera preocupación es la legibilidad y comprensión del programador.
Voy a tomar una posición radical aquí y dar un cordial "no" a los paréntesis
a AND b OR c AND d
. Todo programador debe saber de memoria que la precedencia en las expresiones booleanas NO> Y> O , al igual que recordar Por favor, disculpe a mi querida tía Sally por las expresiones algebraicas. La puntuación redundante solo agrega desorden visual la mayor parte del tiempo en el código sin beneficio en la legibilidad del programador.Además, si siempre usa paréntesis en expresiones lógicas y algebraicas, entonces renuncia a la capacidad de usarlas como marcador de "algo complicado está sucediendo aquí, ¡cuidado!" Es decir, en los casos en que desea anular la precedencia predeterminada y hacer que se evalúe la suma antes de la multiplicación, o OR antes de AND, los paréntesis son una buena bandera roja para el próximo programador. Demasiado uso de ellos cuando no son necesarios, y te conviertes en el niño que lloró lobo.
Haría una excepción para cualquier cosa fuera del ámbito del álgebra (booleana o no), como las expresiones de puntero en C, donde cualquier cosa más complicada que las expresiones idiomáticas estándar como
*p++
op = p->next
probablemente debería estar entre paréntesis para mantener la desreferencia y la aritmética recta. Y, por supuesto, nada de esto se aplica a idiomas como Lisp, Forth o Smalltalk que usan alguna forma de notación polaca para las expresiones; pero para la mayoría de los idiomas principales, la precedencia lógica y aritmética está totalmente estandarizada.fuente
AND
vsOR
es un caso bastante básico que me gustaría que los otros desarrolladores de mi equipo sepan. Me preocupa que a veces "usar paréntesis para mayor claridad" sea realmente "usar paréntesis para no tener que preocuparme nunca por conocer la precedencia"..member
antes que los operadores unarios, unarios antes que los operadores binarios,*
y/
antes+
y-
antes<
y>
y==
antes de&&
antes de||
antes de la asignación. Esas reglas son fáciles de recordar porque coinciden con mi "sentido común" acerca de cómo se usan normalmente los operadores (por ejemplo, no daría==
mayor prioridad+
o dejaría de1 + 1 == 2
funcionar), y cubren el 95% de las preguntas de prioridad que tendría .Como yo lo veo:
SÍ Pros:
SÍ Contras:
NO Pros:
SIN contras:
fuente
3 * a^2 + 2 * b^2
más fácil de leer que(3 * (a^2)) + (2 * (b^2))
, porque el formato y la precedencia son familiares y estándar. Del mismo modo, podría (para ser extremo) prohibir el uso de funciones y macros (¡o compiladores!) Para que la semántica de su código sea más explícita. Obviamente no estoy abogando por eso, pero espero responder a su pregunta de por qué debe haber limitaciones (un equilibrio) para hacer las cosas explícitas.Si nadie más tendría que mirar mi código nuevamente, no creo que me importe.
Pero, desde mi experiencia:
Casi siempre hago esto porque confío en mi capacidad de leer rápidamente y no cometer pequeños errores mucho más con los padres que con nada más.
En su caso, casi seguramente haría algo como:
Sí, es más código. Sí, puedo hacer operadores bool de lujo en su lugar. No, no me gusta la posibilidad de que al escanear el código 1+ años en el futuro interprete mal los sofisticados operadores bool. ¿Qué pasa si estaba escribiendo código en un idioma que tenía una prioridad AND / OR diferente y tenía que saltar hacia atrás para arreglar esto? Voy a decir: "¡Ajá! ¡Recuerdo esta pequeña cosa inteligente que hice! No tuve que incluir a los padres cuando escribí esto el año pasado, ¡qué bueno que recuerdo ahora!" si eso sucede (o peor, ¿alguien más que no estaba al tanto de esta inteligencia o fue arrojado a una situación de tipo "arreglar lo antes posible")?
La separación con () hace que sea mucho más sencillo hojear y comprender rápidamente ...
fuente
ab = a AND b
?ab
permanecerá sin cambios si noa AND b
.Caso general
En C #, la multiplicación y la división tienen prioridad sobre la suma y la resta.
Aún así, StyleCop, una herramienta que aplica el estilo común en toda la base de código con un objetivo adicional para mitigar el riesgo de errores introducidos por código que puede no ser lo suficientemente claro, tiene la regla SA1407 . Esta regla generará una advertencia con un código como este:
Está claro que el resultado es
7
y no9
, pero aún así, StyleCop sugiere poner paréntesis:Su caso particular
En su caso particular, existe una precedencia de AND en comparación con OR en el idioma particular que utiliza.
Así no se comportan todos los idiomas. Muchos otros tratan AND y OR por igual.
Como desarrollador que trabaja principalmente con C #, cuando vi su pregunta la primera vez y leí el fragmento de código sin leer lo que había escrito antes, mi primera tentación fue comentar que las dos expresiones no son iguales. Con suerte, he leído toda la pregunta por completo antes de comentar.
Esta particularidad y el riesgo de que algunos desarrolladores puedan creer que AND y OR tienen la misma prioridad hace que sea aún más importante agregar paréntesis.
No escriba código con el objetivo de demostrar que es inteligente. Escriba código con un objetivo de legibilidad, incluso por personas que pueden no estar familiarizadas con todos los aspectos del lenguaje.
fuente
Como todos dijeron, use paréntesis cada vez que haga que la expresión sea más legible. Sin embargo, si la expresión es complicada, recomendaría introducir nuevas funciones para las subexpresiones .
fuente
Si usa estrictamente el lenguaje en singular, tal vez. Ahora tome todos los idiomas que conoce, desde los más antiguos hasta los más modernos, desde compilados hasta scripting y SQL hasta su propio DSL que ha inventado el mes pasado.
¿Recuerdas las reglas de precedencia exactas para cada uno de estos idiomas, sin mirar?
fuente
"Debo usar paréntesis en las declaraciones lógicas, incluso cuando no sea necesario".
Sí, porque dos personas los encontrarán útiles:
El próximo programador, cuyo conocimiento, competencia o estilo puede ser diferente.
¡El futuro usted que vuelve a este código en una fecha posterior!
fuente
Los condicionales complejos son "álgebra booleana", que usted escribe de alguna manera que, bueno, lo hace ver exactamente como álgebra, y definitivamente usaría parens para álgebra , ¿no es así?
Las reglas realmente útiles son las de negación:
O, en un formato un poco más claro:
que es muy clara simplemente álgebra cuando se escribe como:
Pero también podemos aplicar el pensamiento para la simplificación y expansión algebraica:
aunque en el código tienes que escribir:
o, en un formato un poco más claro:
Básicamente, un condicional sigue siendo solo una expresión algebraica, y al usar claramente el paréntesis, puede aplicar más fácilmente las diversas reglas algebraicas que ya conoce a la expresión, incluido el antiguo concepto de "simplificar o expandir esta fórmula".
fuente
!(A + B) <=> !A + !B
y-1*(A + B) = -A + -B
no debe el operador se han volteado a partir+
de*
la segunda expresión?Usaré paréntesis, incluso si es opcional, porque ayuda a comprender mejor a todos, tanto para el que escribe el código como para el que está listo para ver ese código. En su caso, incluso los operadores booleanos tienen prioridad, podría funcionar bien al principio, pero no podemos decir que lo ayudará en todos los casos. así que prefiero usar paréntesis en cualquier condición que pueda requerirlo u opcionalmente.
fuente
Si. Debe usarlo en cualquier caso cuando considere que su código será más claro. Recuerde que su código debe ser lo suficientemente claro para que otros puedan entenderlo sin leer sus comentarios dentro del código. Por lo tanto, es una buena práctica usar paréntesis y llaves. También tenga en cuenta que puede depender de la práctica particular de su empresa / equipo. Simplemente mantenga un enfoque y no mezcle.
fuente