Architecture logicielle & Développement

La Boucle Infinie Qui En Fait N’Est Exécutée Qu’Une Fois

Tags:

Il est des constructions que certains pensent légitimes, et qui pourtant ne le sont pas. On les retrouve de temps en temps dans le code source d’un projet, et il est évident que la lecture n’en est pas facilitée. L’une de des constructions est la terrible Boucle Infinie Qui En Fait N’Est Exécutée Qu’Une Fois.

Le coupable, dans sa grande splendeur, ressemble à ce pseudo-code C++ :

for (;;) {
  // …
  // quelques conditions peuvent permettre de sortir de la boucle
  if (a_condition) break;
  // …
  // au final, on s’assure quand même que la boucle n’est exécutée
  // qu’une seule fois. 
  break;
}

Le but de cette structure de code est généralement de permettre l’exécution du code jusqu’à un certain point, et en cas d’erreur il est alors possible de contrôler la sortie de la boucle pour ensuite exécuter (par exemple) le code qui libérera les ressources créées précédemment.

En d’autre terme, ce code permet, avec une écriture on ne peut moins idiomatique, de ne pas utiliser le mot-clef goto - puisque nous savons tous depuis Djikstra que goto est un mot clef dangereux. Il s’agit donc de reproduire le comportement dangereux de ce mot-clef sans l’utiliser – autrement dit, nous entrons là dans le royaume du non-sens.

Tout problème possédant une solution, comment peut-on éviter d’écrire ce code odieux ? Plusieurs techniques sont à notre disposition.

  • dans un premier temps, si nous désirons contrôler les ressources créées, l’idiome RAII (pour Resource Acquisition Is Initialization) vient à notre secours. L’implémentation de cet idiome est d’une simplicité désarmante : la ressource est encapsulée dans un objet, la création de l’objet crée la ressource ou acquiert celle-ci, et la destruction de l’objet libère la ressource. En C++, si cette ressource est représentée par un bloc de mémoire, les classes std::vector et std::auto_ptr peuvent être utilisées. Dans le cas d’un fichier ou d’un flux, les classes dérivées de std::istream et std::ostream sont à considérer. Toute autre ressource peut être représentée par une classe dédiée. Lorsqu’on sort de la fonction (sur une erreur, par l’envoi d’une exception ou que sais-je), le destructeur sera systématiquement appelée et la ressource sera détruite. Le code client en est simplifié d’autant. L'idiome RAII peut être implémenté dans de nombreux autres langages (Java, C#, et ainsi si suite)
  • Si nous devons gérer plusieurs cas d’erreurs, chaque cas devant initialiser une variable dans le but de retourner un code d’erreur, notre choix se portera sur la génération d’exceptions. Une exception peut être générée avec n’importe quel objet, ce qui peut nous permettre de créer l’objet souhaité (ou plus simplement de générer un code d’erreur, si il s’agit là de notre seul besoin).

D’autres techniques peuvent être mises en oeuvre pour éviter d’avoir à écrire un code douteux au mieux, dangereux au pire. Alors, s’il vous plait, éviter de faire l’erreur d’implémenter cette indécente boucle ! A bon entendeur...

Trackbacks

Aucun trackback.

Les trackbacks pour ce billet sont fermés.

Commentaires

Aucun commentaire pour le moment.

Ajouter un commentaire

Si votre navigateur est compatible, vous pouvez vous aider de la barre d'outils placée au-dessus de la zone de saisie pour enrichir vos commentaires.