A veces, una if
declaración puede ser bastante complicada o larga, por lo que en aras de la legibilidad es mejor extraer las llamadas complicadas antes del if
.
por ejemplo, esto:
if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
// do stuff
}
dentro de esto
bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();
if (b1 || b2)
{
//do stuff
}
(proporcionado ejemplo no es que mal, es sólo para la ilustración ... imaginar otras llamadas con múltiples argumentos, etc.)
Pero con esta extracción perdí la evaluación de cortocircuito (SCE).
- ¿De verdad pierdo SCE cada vez? ¿Existe algún escenario en el que el compilador pueda "optimizarlo" y seguir proporcionando SCE?
- ¿Hay formas de mantener la legibilidad mejorada del segundo fragmento sin perder SCE?
Respuestas:
Una solución natural se vería así:
Esto tiene las ventajas de ser fácil de entender, aplicable a todos los casos y tener un comportamiento de cortocircuito.
Esta fue mi solución inicial: un buen patrón en llamadas a métodos y cuerpos de bucle for es el siguiente:
Se obtienen los mismos beneficios de rendimiento de la evaluación de cortocircuitos, pero el código parece más legible.
fuente
if
" también es una señal de que su función o método es demasiado grande y debe dividirse en otros más pequeños. No siempre es la mejor manera, ¡pero muy a menudo lo es!b2
correctamente y obtendrássomeConditionAndSomeotherConditionIsTrue
, no muy significativo. Además, tengo que mantener un montón de variables en mi pila mental durante este ejercicio (y tbh hasta que deje de trabajar en este ámbito). Yo iría conSJuan76
la solución número 2 o simplemente pondría todo en una función.Tiendo a dividir las condiciones en varias líneas, es decir:
Incluso cuando se trata de varios operadores (&&), solo necesita hacer una sangría avanzada con cada par de paréntesis. SCE todavía entra en acción, no es necesario utilizar variables. Escribir código de esta manera me lo hizo mucho más legible desde hace años. Ejemplo más complejo:
fuente
Si tiene largas cadenas de condiciones y qué mantener algunos de los cortocircuitos, entonces podría usar variables temporales para combinar múltiples condiciones. Tomando su ejemplo, sería posible hacer, por ejemplo,
Si tiene un compilador compatible con C ++ 11, puede usar expresiones lambda para combinar expresiones en funciones, similar a lo anterior:
fuente
1) Sí, ya no tiene SCE. De lo contrario, tendrías eso
funciona de una forma u otra dependiendo si hay una
if
declaración más adelante. Demasiado complejo.2) Esto se basa en opiniones, pero para expresiones razonablemente complejas puede hacer:
Si es demasiado complejo, la solución obvia es crear una función que evalúe la expresión y la llame.
fuente
También puedes usar:
y SCE funcionará.
Pero no es mucho más legible que, por ejemplo:
fuente
b = b || otherComplicatedStuff();
y @SargeBorsch hace una edición para eliminar SCE. Gracias por notar ese cambio @Ant.No creo que esta optimización esté permitida; especialmente
OtherComplicatedFunctionCall()
puede tener algunos efectos secundarios.Prefiero refactorizarlo en una función o una variable con un nombre descriptivo; que preservará tanto la evaluación de cortocircuitos como la legibilidad:
Y a medida que implementamos en
getSomeResult()
función deSomeComplicatedFunctionCall()
yOtherComplicatedFunctionCall()
, podríamos descomponerlos de forma recursiva si aún son complicados.fuente
No, no lo haces, pero se aplica de manera diferente:
Aquí, el compilador ni siquiera se ejecutará
OtherComplicatedFunctionCall()
siSomeComplicatedFunctionCall()
devuelve verdadero.Aquí, ambas funciones se ejecutarán porque deben almacenarse en
b1
yb2
. Ffb1 == true
entoncesb2
no será evaluado (SCE). Pero yaOtherComplicatedFunctionCall()
se ha ejecutado.Si no
b2
se usa en ningún otro lugar, el compilador podría ser lo suficientemente inteligente como para insertar la llamada a la función dentro de if if la función no tiene efectos secundarios observables.Eso depende. ¿ Necesita
OtherComplicatedFunctionCall()
ejecutar debido a efectos secundarios o el impacto en el rendimiento de la función es mínimo? Entonces debe usar el segundo enfoque para mejorar la legibilidad. De lo contrario, apéguese a SCE en el primer enfoque.fuente
Otra posibilidad de que se produzca un cortocircuito y tenga las condiciones en un solo lugar:
Puede poner el ciclo en una función y dejar que la función acepte una lista de condiciones y genere un valor booleano.
fuente
Muy extraño: estás hablando de legibilidad cuando nadie menciona el uso de comentarios dentro del código:
Además de eso, siempre antecedo mis funciones con algunos comentarios, sobre la función en sí, sobre su entrada y salida, y a veces pongo un ejemplo, como puedes ver aquí:
Obviamente, el formato a utilizar para sus comentarios puede depender de su entorno de desarrollo (Visual studio, JavaDoc bajo Eclipse, ...)
En lo que respecta a SCE, supongo que con esto se refiere a lo siguiente:
fuente
La legibilidad es necesaria si trabaja en una empresa y su código será leído por otra persona. Si escribe un programa para usted mismo, depende de usted si desea sacrificar el rendimiento en aras de un código comprensible.
fuente