Question

Si, comme moi, vous frissonnez sur le site d'une boucle While (True), vous devez également avoir longuement réfléchi à la meilleure façon de la refactoriser. J'ai vu plusieurs implémentations différentes, aucune vraiment meilleure qu'une autre, telle que la minuterie & amp; combinaison de délégués.

Alors, quel est le meilleur moyen de refactorer la boucle While (True) tant redoutée que vous avez vue?

Modifier : comme indiqué dans certains commentaires, mon intention était que cette question soit une "boucle infinie". refactoring, comme l’exécution d’un service de style Windows dans lequel les seules conditions d’arrêt seraient OnStop ou une exception fatale.

Était-ce utile?

La solution

Avons-nous vraiment besoin de refactoriser les boucles while (true) ? Parfois, il s'agit d'une norme de codage et la plupart des développeurs se sont habitués à cette structure. Si vous devez réfléchir sérieusement à la façon de refactoriser ce code, êtes-vous sûr que c'est une bonne idée de le refactoriser?

Goto était un mouton noir dans les normes de codage. J'ai rencontré des algorithmes où goto ont rendu le code beaucoup plus lisible et plus court. Parfois, il ne vaut pas la peine de refactoriser (ou mieux d'utiliser goto ).

D'autre part, vous pouvez éviter tandis que (vrai) la plupart du temps.

Autres conseils

Ma préférence serait

start:

   // code goes here

goto start;

Cela exprime très clairement l'intention. Bonne chance pour dépasser vos normes de codage. (Je me demande combien de karma cela va me coûter).

Qu'est-ce qui est redouté à ce sujet? Essayez de trouver une condition de rupture commune et de la reformuler pour qu'elle devienne la tête de la boucle. Si ce n'est pas possible & # 8211; bien.

Quand je rencontre une boucle while (vraie), cela me dit que

  1. la condition de rupture n'est pas facilement testée en haut (ou en bas) de la boucle,
    • les conditions de pause sont multiples,
    • ou le programmeur précédent était trop paresseux pour factoriser correctement la boucle.

1 et 2 signifie que vous pourriez aussi bien vous en tenir à (vrai). (J'utilise pour (;;) , mais c'est une question de style, à mon avis.) Je suis avec une autre affiche, pourquoi redouter cela? Je redoute les boucles torturées qui sautent dans les cerceaux pour faire rouler la boucle "correctement".

Remplacez True par la condition que vous alliez utiliser pour sortir de la boucle.

Dans le cas d'un service ou d'un thread d'arrière-plan, vous pouvez utiliser:

volatile bool m_shutdown = false;
void Run()
{
    while (!m_shutdown)
    { ... }
}

Pourquoi refactor? Et qu'est-ce qui est "terrible"? à propos de cette construction? Il est largement utilisé et bien compris.

S'il n'est pas cassé, ne le corrigez pas.

Le " courir pour toujours " la situation fait parfois partie d’une machine à états plus grande. De nombreux périphériques intégrés (avec des boucles permanentes) ne fonctionnent pas vraiment pour toujours . Ils ont souvent plusieurs modes de fonctionnement et séquenceront ces modes.

Lors de la création des régulateurs de pompe à chaleur, un mode POST (auto-test à la mise sous tension) fonctionnait pendant un certain temps. Ensuite, il y avait un mode de collecte environnementale préliminaire qui a fonctionné jusqu'à ce que nous ayons déterminé toutes les zones et les thermostats et ce qui ne l'est pas.

Certains ingénieurs ont affirmé que ce qui suivait était le "run-forever". boucle. Ce n'était pas si simple. En réalité, plusieurs modes de fonctionnement ont basculé et se sont effondrés. Il y avait le chauffage, le dégivrage, le refroidissement, la marche au ralenti et d'autres choses.

Ma préférence est de traiter un " toujours " boucle comme un seul mode de fonctionnement - il en existera peut-être d'autres à l'avenir.

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

Dans certaines circonstances, rien de ce que nous avons vu jusqu'à présent ne définit someMode sur False . Mais j'aime bien prétendre qu'il y aura un changement de mode dans une version future.

#define ever 1
for (;ever;)

?

Meh, laissez-le tel quel, alors que (vrai) est probablement aussi lisible que vous allez l'obtenir ..

errr, être un refactoring .....

  • Remplacer la boucle infinie par la récursion infinie :-)

Eh bien, si vous avez un langage qui prend en charge les appels Tail ....

Si vous voulez que cela continue indéfiniment jusqu'à ce que le flux de programmes soit totalement interrompu, je ne vois rien qui cloche avec while (true). Je l'ai rencontré récemment dans un service de collecte de données .NET qui combinait while (true) et thread.sleep pour se réveiller chaque minute et interroger le service de données tiers pour obtenir de nouveaux rapports. J'ai envisagé de le refactoriser avec une minuterie et un délégué, mais j'ai finalement décidé qu'il s'agissait de la méthode la plus simple et la plus facile à lire. 9 fois sur 10, c'est une odeur de code claire, mais quand il n'y a pas de condition de sortie, pourquoi rendre les choses plus difficiles?

Cela ne me dérange pas que la boucle infinie soit contenue dans une fenêtre et meure avec la fenêtre.

Pensez à la récursion Hasselhoff.

void whiletrue_sim(void)
  {
    //some code
    whiletrue_sim();
  }

Avertissement: votre pile risque de déborder, en fonction de la langue, de l'optimiseur et d'autres facteurs.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top