La pratique de Perl: Un plaidoyer pour plus de clarté

Par Hal Pomeranz traduction Philippe Bereski

Après une brève interruption, nous voici de retour pour une seconde année de La pratique de Perl. Ce mois ci, Rob m'a demandé d'écrire un petit document sur la lisibilité des programmes Perl. J'ai donc commencé à travailler dans ce but, mais j'ai rapidement dérivé vers la question de la maintenabilité de code écrit en Perl. Ceci m'a chagriné jusqu'à ce que je me rende compte que la maintenabilité est la principale raison nous poussant à exiger du code lisible. Si une fois écrit, un code n'avait jamais à être relu, la motivation d'écrire du code lisible serait moins importante (note: mais elle serait quand même souhaitable). Ce point de philosophie traité, passons aux différents petits trucs biens utiles que j'ai accumulés au fil des ans.

Quelques mots à propos des boucles

La première règle est "dites ce que vous faites". Comparez ces deux méthodes accomplissant la même tâche :
     grep($array{$_}++, @list);		# Mauvais !

     for (@list) {			# OK 	   
          $array{$_} = 1; 
     }
Je prétends que la seconde forme est préférable à la première car elle indique ce qui ce passe : Nous itérons sur @liste et initialisons chaque entrée du tableau %array à une valeur non nulle. (L'affectation est plus lisible que l'auto-incrémentation). Il existe d'autres façons plus verbeuses d'écrire la boucle "for" ci-dessus. A vous de choisir celle que vous préférez, mais éviter d'utiliser grep() comme opérateur d'itération. En général j'optimise la lisibilité du code plutôt que son exécution.

Autre exemple, examinons les deux boucles perpétuelles suivantes :

     while (1) {			# Mauvais! 	   
     ... 
     }

     for ( ;; ){			# OK 	   
     ... 	
     }
La seconde forme saute mieux aux yeux, elle montre clairement au lecteur que quelque chose d'important est attendu.

Toujours au chapitre des boucles, examinons une autre règle de communication entre l'auteur du code et ses relecteurs : "Soyez brefs". Les "goto" et les "break" sur plusieurs niveaux sont tous deux à éviter pare ce qu'ils empêchent le lecteur d'avoir une vision d'ensemble du flux d'exécution du code. J'ai recherché des exemples illustrant cette règle, mais je n'en ai pas trouvés qui tiennent dans l'espace alloué à cet article. Je pense cependant en avoir assez dit.

Les expression conditionnelles

Toujours au chapitre "Dites ce que vous faites", souvenez vous que vous pouvez toujours utiliser until à la place de while et unless à la place de if.
     &usage() unless (@ARGV);
     until ($value > $LIMIT) {
          ... 	
     }
Vous augmenterez largement la lisibilité de votre code en supprimant les négations dans vos expressions. Perl peut se lire comme de la prose si vous utilisez attentivement ses noms symboliques.

Avec les opérateurs conditionnels postfixés, faites bien attention à placer la partie la plus importante de l'instruction au début de la phrase. C'est pourquoi il vaut mieux écrire :

     open(...) || die ... ;	   	# Recommandé
que
     die ... unless open(...);		# Pas terrible !
Le propos de cette instruction est d'associer un "file handle" à un fichier ou à un sous process. Le code die() n'intervient que pour traiter les exceptions.

De la même façon, évitez de surcharger les expressions conditionnelles avec des opérations qui manipulent les données du programme ou qui ont d'autres effets de bords. Évaluer d'abord une expression pour choisir une branche d'exécution puis exécuter vos opérations.

Parenthèses et fonctions

Ne lésinez pas sur les parenthèses, sans oublier toutes fois qu'une surabondance peut également causer des problèmes. Dans les expressions conditionnelles, les parenthèses supplémentaires aideront le lecteur à analyser l'expression. Elles protègent également l'application contre les modifications réalisées par des programmeurs moins au fait que vous de la précédance des opérateurs.

Perl est extrêmement permissif au sujet des parenthèses dans les listes d'arguments. Parenthèsez toujours les arguments de vos fonctions. Un exemple classique de cette règle est fourni par le "Camel book"(*).

     print (1+2)*3, "\n";	# INCORRECT!
Ceci imprime la valeur de l'expression entre parenthèses, i.e. le nombre trois sans saut de ligne. Cette instruction est syntaxiquement correcte, (un bon point si vous trouvez exactement ce qu'il advient du reste de la ligne), et l'interpréteur Perl ne bronchera pas, mais la sortie sera tout à fait différente de celle produite par :
     print((1+2)*3, "\n");	# CORRECT
qui est certainement ce que souhaitait l'auteur du code.

Si vous n'avez besoin que de quelques valeurs retournées par une fonction, s'il vous plaît, éviter d'utiliser des variables inutiles. En d'autre termes, faites :

     ($login, $name, $home) = (getpwent)[0,6,7];	# Bon
plutôt que :
     ($login, $dummy, $dummy $dummy, $dummy, $dummy, $name, $home) = getpwent; # Mauvais
En dehors de l'économie de saisie, la première forme montre précisément la partie de l'information qui est utilisée.

Pêle-mêle

Un bon principe général consiste à ne jamais se reposer sur les assignations par défaut. Purger vos variables par undef ou une affectation avant de les utiliser pour la première fois. Ceci aide à éviter des erreurs qui pourraient être introduites par des futures modifications.

Les paramètres implicites des fonctions sont subtiles. Vous pouvez parfaitement considérer qu'une fonction Perl s'appliquera à $_ ou @_ si vous ne lui donnez pas d'argument. C'est une particularité bien pratique et je l'utilise constamment (c'est trop pratique pour s'en passer je suppose). Cependant cela rend le code Perl particulièrement obscure pour un novice. En quelques occasions j'ai même constaté des comportements anormaux parce que @_ ne contenait pas ce que je pensais. Sur un point encore plus trivial, je recommande également de toujours utiliser le caractère < pour ouvrir un fichier en lecture, même si c'est l'option par défaut de open().

Ne codez jamais en dur les chemins des fichiers ou les constantes dans vos programmes. Affectez ces valeurs à des variables AU DÉBUT de votre programme. Par exemple, voici les quelques premières lignes d'une application que j'ai écrite pour manipuler un "jukebox" optique sur le réseau :

     #!/usr/bin/perl

     $jukehost = `gator'; 
     $nfsjukedir = `/rd/juke'; 	
     $realjukedir = `/export/jb/jb0'; 	
     $localjukedir = `/jukebox'; 	
     $remotecmd = `/usr/local/etc/jbadm';
Quand un code est écrit de cette façon, le maintenir est un jeu d'enfant.

Refermez toujours vos fichiers et répertoires dès que vous avez fini de les utiliser. Cela évitera les pénuries de file descripteurs dans votre application en même temps que ça la protégera contre les effets de bords causés par des modifications ultérieure, et cela rendra votre code plus clair pour l'hypothétique lecteur externe.

À propos des conventions

Le lecteur attentif aura noté que j'ai traité de la clarté à propos de la syntaxe du langage. Il y a des points non liés au langage, tels que l'indentation, les conventions de nommage des variables et le style des commentaires qui sont également importants. Ce sont également ceux où les querelles de chapelle sont les plus vives.

Pour éviter ce bourbier, (je sais par exemple que tout le monde déteste le style de mes accolades), je suggère une simple et unique règle. Choisissez un standard que tout le monde accepte dans votre organisation et tenez vous y. Même un mauvais standard est préférable à pas de standard du tout. Si vous avez à maintenir du code développé à l'extérieur, conservez alors les conventions qui ont été utilisées par les auteurs originaux.

Un bon point de départ est fourni par un document disponible sur le réseau, Recommended C Style and Coding Standards (il a été préparé par un groupe de travail aux "Bell Labs" et a été modifié par Henry Spencer, David Keppel, et Mark Brader). Il est disponible sous une forme électronique /pub/cstyle.tar.Z que vous pouvez obtenir par ftp depuis ftp.cs.washington.edu.

Pour aller plus loin

Notez bien que ce qui précède s'applique à tous les langages. Certaines constructions peuvent bien sur ne pas exister, mais la clarté doit être indépendante de la syntaxe. Pour une étude plus poussée de ce sujet, commencez par un bon ouvrage sur le style de programmation en C et poursuivez en explorant la bibliographie qu'il vous proposera.

Traduction de ;login: Vol. 19 No. 6, December 1994.

* Le "Camel Book" est historiquement l'ouvrage de référence sur Perl. Il est publié aux Editions O'Reilly & Associates, Inc. Une édition mise à jour pour Perl 5 a été récemment publiée. (ndtr).


Dernière édition: 16 mars 1997 phb
Original 11/26/96ah
Back to the original
Retour à l'index