refactoring - loop - La mejor refactorización para el temido ciclo While(True)
do while en python (12)
Si, como yo, te estremeces en el sitio del ciclo While (True), entonces también debes haber pensado mucho sobre la mejor forma de refactorizarlo. He visto varias implementaciones diferentes, ninguna mejor que ninguna otra, como la combinación de temporizador y delegado.
Entonces, ¿cuál es la mejor forma en que se te ocurrió o se vio que refactorizar el temido ciclo While (True)?
Editar : Como mencioné en algunos comentarios, mi intención era que esta pregunta fuera una refactorización de "ciclo infinito", como ejecutar un servicio de estilo de Windows donde las únicas condiciones de detención serían OnStop o una excepción fatal.
Cuando encuentro un ciclo while (verdadero), eso me dice
- la condición de ruptura no se prueba fácilmente en la parte superior (o inferior) del ciclo,
- hay múltiples condiciones de descanso,
- o el programador anterior era demasiado perezoso para factorizar el ciclo correctamente.
1 y 2 significa que también podría quedarse con el tiempo (verdadero). (Utilizo for(;;)
, pero eso es algo de estilo en mi opinión.) Estoy con otro póster, ¿por qué temer esto? Temo los bucles tortorados que saltan a través de aros para hacer que el bucle ruede "correctamente".
¿Por qué refactorizar? ¿Y qué es tan "terrible" sobre este constructo? Es ampliamente utilizado y bien entendido.
Si no está roto, no lo arregles.
¿Qué tiene tanto miedo? Intente encontrar una condición de corte común y refactorizarla para que sea el jefe del ciclo. Si eso no es posible, bien.
¿Realmente necesitamos refactorizar mientras (verdadero) bucles? A veces es un estándar de codificación y la mayoría de los desarrolladores se han acostumbrado a esta estructura. Si tiene que pensar mucho sobre cómo refactorizar este código, ¿está seguro de que es una buena idea refactorizarlo?
Goto solía ser una oveja negra en estándares de codificación. Conocí algoritmos donde goto hizo el código mucho más legible y más corto. A veces no vale la pena refactorizar (o mejor usar goto ).
Por otro lado, puede evitar mientras (verdadero) la mayor parte del tiempo.
La situación de "correr para siempre" a veces es parte de una máquina de estado más grande. Muchos dispositivos integrados (con bucles de ejecución permanente) en realidad no se ejecutan para siempre . A menudo tienen varios modos de funcionamiento y se secuenciarán entre esos modos.
Cuando construimos los controladores de bomba de calor, hubo un modo de autoprueba de encendido (POST) que se ejecutó por un tiempo. Luego hubo un modo de reunión ambiental preliminar que se ejecutó hasta que descubrimos todas las zonas y termostatos y lo que no.
Algunos ingenieros afirmaron que lo que vino después fue el ciclo de "correr para siempre". No fue tan simple. En realidad, era varios modos de funcionamiento que daban vueltas y vueltas. Hubo calefacción, descongelación, enfriamiento, ralentí y otras cosas.
Mi preferencia es tratar un ciclo "para siempre" como realmente solo un modo operativo, puede haber otros en algún momento en el futuro.
someMode= True
while someMode:
try:
... do stuff ...
except SomeException, e:
log.exception( e )
# will keep running
except OtherException, e:
log.info( "stopping now" )
someMode= False
En algunas circunstancias, nada de lo que hemos visto hasta ahora establece algunos someMode
en False
. Pero me gusta pretender que habrá un cambio de modo en alguna versión futura.
No me importa cuando el ciclo infinito está contenido dentro de una ventana y muere con la ventana.
Piensa en la Recursión de Hasselhoff.
Reemplace True con la condición que iba a usar para salir del circuito.
En el caso de un servicio o un hilo de fondo, puede usar:
volatile bool m_shutdown = false;
void Run()
{
while (!m_shutdown)
{ ... }
}
Si desea que continúe indefinidamente hasta que se produzca un aborto total del flujo del programa, no veo nada malo con el tiempo (verdadero). Lo encontré recientemente en un servicio de recopilación de datos .NET que combinó mientras (verdadero) con thread.sleep para despertarse cada minuto y sondear el servicio de datos de terceros para nuevos informes. Consideré refaccionarlo con un temporizador y un delegado, pero finalmente decidí que este era el método más simple y fácil de leer. 9 veces de cada 10 es un olor a código claro, pero cuando no hay una condición de salida, ¿por qué hacer las cosas más difíciles?
errr, ser una refactorización .....
- Reemplace Infinite Loop con Infinite Recursion :-)
bueno, si tiene un lenguaje que admite llamadas de cola ....
#define ever 1
for (;ever;)
?
Meh, déjalo como está, mientras que (verdadero) es probablemente tan legible como lo que vas a obtener ...
Mi preferencia sería
start:
// code goes here
goto start;
Esto expresa más claramente el intento. Buena suerte superando sus estándares de codificación. (Me pregunto cuánto karma me va a costar).
void whiletrue_sim(void)
{
//some code
whiletrue_sim();
}
Advertencia: su pila puede ser desbordante, dependiendo del idioma, optimizador y otras cosas.