26 fév. 2008

Pire que goto ?

Je ne pensais pas vraiment cela possible (même si, dans mon expérience, j'ai vu des morceaux de code dont la pertinence n'avait d'égal que la régularité avec laquelle ils ne fonctionnaient pas), mais j'ai trouvé une construction de code qui a le mérite d'être :

  • illisible
  • dangereuse
  • génératrice d'exceptions

Le tout, sans utiliser de goto.

Il faut revenir à l'ancien temps pour trouver le responsable, et notamment se replonger dans les affres d'un langage qui devient de nos jours aussi ésotérique que le Klingon : j'ai dénommé Fortran, sous sa forme normalisée en 1977 (j'avais 1 an. Argh.). Pour être honnète, je ne prétends pas comprendre la philosophie du langage lui même : il s'agit d'un langage impératif, vaguement fortement typé, et globalement illisible.

Mais revenons à notre problème principale : cette construction de code qui a tant de défauts.

Au début, il y a une bonne intention : simplifier la lecture et l'écriture dans les fichiers. Une fois un fichier ouvert, on peut se contenter d'un seul READ pour lire tout le contenu d'un fichier binaire. Un exemple :

       OPEN(UNIT=1, 
      1     FILE='mon_fichier.dat', 
      1     STATUS='OLD',
      1     FORM='UNFORMATTED'
      1     ACCESS='DIRECT',
      1     RECL=117)

Là, on a ouvert un fichier binaire (form=unformatted) existant (status=old) en accès direct, avec une longeur d'enregistrement de 117 caractères.Pour l'instant, c'est simple (si ce n'est que le code commence en colonne 7 et que la colonne 6 contient un chiffre qui est utilisé par le compilateur comme un caractère de continuation de ligne).

Puis, on lit quelques données

      NREC=1
      READ(1,REC=NREC)
     1     valeur1, valeur2, valeur3, valeur4,
     1     ...,
     1     valeurN

Pour simplifier, j'ai omis les valeur5, 6, ... jusqu'à N.

Cette liste s'appelle une liste d'entrée-sortie. Elle peut contenir autant de valeur que souhaité par le programmeur. Une seule de ces liste peut donc être utilisée pour lire tout le contenu d'un fichier. Jusque là, pas de problème particulier.

Là où ça se gâte, c'est lorsque cette liste est augmentée d'une liste d'entrée-sortie avec boucle implicite :

      INTEGER a(10)
      INTEGER b(10)
      INTEGER c(10)
NREC=1 READ(1,REC=NREC) 1 valeur1, valeur2, valeur3, valeur4, 1 (a(k), b(k), c(k), k=1,10)

Cette instruction est équivalente à (pseudo-code) :

READ(1, REC=NREC) valeur1, valeur2, valeur3, valeur4,
for (k=1; k<=10; ++k) {
  READ(1, REC=NREC) a(k), b(k), c(k)
}

Et voilà le coupable qui se profile au loin :

      INTEGER a(10)
      INTEGER b(10)
      INTEGER c(10)
NREC=1 READ(1,REC=NREC) 1 NB_OBJ, 1 (a(k), b(k), c(k), k=1,NB_OBJ)

Si ce code peut sembler innocent, il n'en est rien : NB_OBJ est peut être supérieur a 10 dans le fichier, auquel cas ce code va systématiquement provoquer une erreur sévère au moment de l'exécution.

Au niveau de la structure, que voit-on ? Il est impossible de tester la valeur de NB_OBJ avant de lire les données dans les tableaux a,b et c. Conséquemment, il est impossible de vérifier le fonctionnement de cette ligne de code sans tester. Et le test dépends très fortement des conditions d'entrée : si les fichiers de test sont mal choisi, le code peut sembler fonctionner.

Ce qui, au final, nous amène à une conclusion : à faire l'économie de l'écriture, on ramasse souvent des problèmes qui ne devraient même pas exister. Et pendant qu'on y est, prions pour que le Fortran 77 ne continue pas à détruire le moral des ingénieurs dans le monde entier.

Commentaires

1. Le vendredi, juillet 13 2012, 18:58 par Krypt

Bonjour,

C'est juste pour signaler trois petites fautes d'accent :
-> La où ça se gate > Là où ça se gâte
->Cette instruction est équivalente a > à

J'en profite pour vous remercier de vos articles qui m'ont permis de m'initier (un peu, je crois que j'ai encore pas mal de chemin) à l'architecture logicielle (même si ce billet ne traite pas de ça).

Aussi, j'ai voulu m'abonner à la newsletter, je crois que le lien contient un slash en trop :
/index.php?/newsletter/form > /index.php?newsletter/form

PS : je n'ai pas trouvé de section pour rapporter les bugs... :(
PS2 : (vraiment entre parenthèses, j'aurais trouvé ça bien une section pour vous contacter, sans que ce soit forcément en rapport avec un billet)

2. Le samedi, juillet 14 2012, 22:33 par Emmanuel Deloget

Bonjour,

Je vais corriger les erreurs citées dès tout de suite. Merci :)

Concernant une éventuelle page de contact, je vais essayer de voire ce que je peux faire. Il doit bien y avoir un plugin pour ça... Dans l'intervalle, il est toujours possible de me contacter via l'adresse email emmanuel@emmanueldeloget.com. Quand à une section pour remonter les bugs, fautes et autres erreurs, je penses que les commentaires dans les billets, c'est aussi fait pour ça :)

Je vais aussi essayer de régler le problème de la newsletter - il semblerait que la dernière mise à jour de dotclear doit à l'origine de ce problème.

En tout cas, merci pour tout !

3. Le dimanche, juillet 15 2012, 13:38 par Krypt

Je constate que cous avez corrigé le lien pour s'inscrire à la newsletter, mais le formulaire contient lui aussi un lien erroné, toujours ce problème de slash. J'ai donc modifié ce lien pour pouvoir m'inscrire, ainsi que celui du mail de confirmation.
Ne sachant pas comment fonctionne DotClear, je n'ai aucune idée d'où peut venir le problème... :(

J'ai trouvé où j'aurais dû signaler l'erreur : Nouveauté de ce blog : la newsletter AL&D.

D'accord pour signaler les fautes que je vois dans les commentaires, mais j'essayerais de ne pas avoir que ça à dire. ;)

4. Le samedi, juillet 21 2012, 12:27 par Emmanuel Deloget

Je ne sais pas encore si c'est dans le plugin ou dans doctlear (si c'est dans doctlear, la modif n'est pas vieille, et si c'est dans le plugin, je ne sais pas de quand elle date), mais il y a une fonction http::concatURL() qui semble avoir été modifiée. Je ne l'ai pas localisée, mais c'est elle qui est appelée pour générer les URL, et il semblerait qu'elle ajoute un / en trop entre l'URL du script et la QUERY_STRING.

Je n'ai pas le temps d'investiguer ça maintenant, donc ça attendra le début du mois prochain.

En tout cas, merci pour les infos :)

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

Fil des commentaires de ce billet