¿Alguna vez está bien que un condicional tenga efectos secundarios? [cerrado]

10

Estoy tomando un curso intermedio de estructuras de datos como requisito previo para ingresar al programa CS MS en una universidad de la que todos en América han oído hablar. Me llamó la atención una línea de código escrita en clase:

if (a > 33 | b++ < 54) {...}

Esto no pasaría una revisión de código en mi lugar de trabajo. Si escribió un código como este en una entrevista, este sería un ataque significativo contra usted. (Además de ser un condicional con efectos secundarios, es inteligente a expensas de la claridad).

De hecho, nunca he visto un condicional con efectos secundarios, y Google tampoco aparece mucho. Otro estudiante se quedó después de clase para preguntar sobre eso también, así que no soy el único que pensó que esto era extraño. Pero el profesor insistió bastante en que este era un código aceptable y que escribiría algo así en el trabajo. (Su trabajo de FT es como SWE principal en una compañía de la que todos han oído hablar).

No puedo imaginar un mundo en el que esta línea de código sea alguna vez aceptable, y mucho menos deseable. ¿Me equivoco? ¿Esta bien? ¿Qué pasa con el caso más general: condicionales con efectos secundarios? ¿Alguna vez están bien?

rianjs
fuente
77
Esa línea debe ser destruida desde la órbita. Dos veces por si acaso.
Blrfl
8
Una liendre: una única tubería (barra vertical) es un bit a bit o en la mayoría de los idiomas, en lugar de un "o" lógico. No hace un cortocircuito si el lado izquierdo es verdadero. Dado que este condicional tiene efectos secundarios en el lado derecho, hace una diferencia especialmente grande en el resultado.
Jonathan Eunice
2
Hay modismos utilizados en varios idiomas que entrarían en esta categoría, pero porque son "bien conocidos" o "normales" no causan problemas. La línea en la pregunta no parece caer en la categoría de uso idiomático, así que lo evitaría.
Jaydee
2
@ JonathanEunice, sí, algunas personas estaban confundidas acerca de la evaluación de cortocircuito. No es un error tipográfico de mi parte.
rianjs
55
Mira el lado positivo. Ahora conoce una compañía más donde NO desea entrevistar.
John R. Strohm

Respuestas:

23

Hay un efecto secundario semi-condicional que puedo pensar que está bien:while(iter.MoveNext())

Dicho esto, creo que esto cae principalmente en la categoría " nunca es un calificador realmente grande". Puedo pensar en algunos casos raros en los que he visto que es aceptable, pero en general esto es vil y debe evitarse.

Tampoco puedo pensar en un escenario donde esa línea particular sería aceptable, pero tampoco puedo pensar en un escenario donde esa línea particular sería útil , por lo que es difícil imaginar el contexto en el que se encuentra.

Telastyn
fuente
Era solo una línea de usar y tirar en un método durante la clase. No estaba destinado a hacer nada útil.
rianjs
44
De manera equivalente, los while(v = *p++)escaneos de estilo C / C ++ a través de una matriz terminada en cero (por ejemplo, cadena C) son bastante comunes y ampliamente aceptados.
Phil Miller
3
A menudo he considerado que los condicionales de bucle de la forma while(c = input.read() != '\n')son razonablemente idiomáticos.
1
Puede haber algunos modismos aceptables comunes, pero claramente "ser inteligente a expensas de la claridad" cae en el campamento NUNCA.
Julia Hayward
Me olvidé por completo de iter.MoveNext (). Un caso completamente razonable para un condicional que tenga un efecto secundario. ¡Gracias!
rianjs
8

En mi mundo, una lectura de memoria puede considerarse un efecto secundario (p. Ej., Memoria asignada IO).

Ahora, considere lo siguiente:

    while( ( *memory_mapped_device_status_register & READY_FLAG) == 0) {
       // Wait
    }

Y comparar con:

    status = *memory_mapped_device_status_register;
    while( ( status & READY_FLAG) == 0) {
        // Wait
        status = *memory_mapped_device_status_register;
    }

¿Evitar el efecto secundario (la lectura) en la condición ayudó a la legibilidad? ¿O simplemente duplicó el código y agregó desorden?

No está bien que una condición tenga efectos secundarios (si eso hace que el código sea menos legible) y también está bien que una condición tenga efectos secundarios (si eso hace que el código sea más legible). El factor clave es la "legibilidad". Todo lo demás son reglas creadas por tontos en un intento equivocado de mejorar la legibilidad (mientras que a menudo tienen el efecto contrario).

Brendan
fuente
3

Como siempre con tales preguntas, esto es una cuestión de grado. Si hubiera pruebas inequívocas de que cualquier efecto secundario dentro de una ifexpresión siempre conducía a un código peor, entonces no sería legal crear esas expresiones. Los diseñadores de lenguajes pueden ser ideosincrática, los seres humanos falibles, pero no lo son que estúpida.

Dicho esto, ¿cuáles son ejemplos de efectos secundarios justificados dentro de un if? Por ejemplo, suponga que tiene la obligación legal de registrar todo y cualquier acceso a la propiedad Pde una entidad Epara fines de auditoría. (Imagine que está trabajando en una planta de enriquecimiento de uranio, y existen controles legales muy estrictos sobre lo que su código tiene permitido hacer y cómo se supone que debe hacerlo). Luego, cualquiera ifque verifique esa propiedad causará el efecto secundario de El registro de auditoría se está extendiendo.

Esa es una preocupación transversal bastante clara, no afecta su razonamiento sobre el estado del programa (mucho), y puede implementarlo para que sea completamente invisible y no distraiga cuando revisa la línea con el if(oculto lejos en el accesor, o incluso mejor a través de AOP). Yo diría que es un caso bastante claro de un efecto secundario que no es una preocupación. Se pueden imaginar situaciones similares cuando solo desea contar las ejecuciones de sucursales con fines de creación de perfiles, etc.

Cuanto más desaparezcan estas circunstancias atenuantes, más extraña será la construcción. Si un tipo de bucle particular (por ejemplo, if((c = getc()) == 'x') { quit(); }es bien conocido y aceptado por la comunidad lingüística, entonces es mucho menos problemático que cuando lo inventa espontáneamente, etc. Su línea de ejemplo no cumple con ese estándar, pero podría imaginar mucho, mucho más horribles que ni siquiera escribiré, son tan horribles.

Kilian Foth
fuente
2

Aunque es un código realmente maloliente, tiene la ventaja de ser más simple (y quizás más rápido si no tiene un buen compilador de optimización) que el equivalente if (a > 33 | b < 54) {b++; ...} else b++;

pero, por supuesto, es posible optimizarlo de la siguiente manera (¡pero cuidado! ¡Este tiene un comportamiento diferente en caso de desbordamiento!): b++; if (a > 33 | b < 53) {...}

Franki
fuente