[couverture de Linux Dossiers 2]
[couverture de Linux Magazine 46]

Introduction à la programmation en Perl (6/7)

Article publié dans Linux Magazine 46, janvier 2003. Repris dans Linux Dossiers 2 (avril/mai/juin 2004).

Copyright © 2002-2003 - Sylvain Lhullier.

[+ del.icio.us] [+ Developers Zone] [+ Bookmarks.fr] [Digg this] [+ My Yahoo!]

Ce document est généré à partir du source XML fourni par Sylvain à l'adresse http://sylvain.lhullier.org/publications/perl.html.

Chapeau

Voici le sixième article de notre série introductive à la programmation en Perl ; nous allons aborder ici l'usage et la rédaction de modules, c'est-à-dire de bibliothèques ou encore librairies. Perl tire sa puissance de la richesse des modules existants ; peu d'autres langages (voire aucun) ne peuvent prétendre être aussi riche que Perl. Par exemple, quasiment tous les protocoles réseau auxquels vous pouvez penser sont accessibles en Perl en utilisant un module existant.

Utilisation de modules

Nous allons aborder ici l'usage des modules, c'est-à-dire de bibliothèques ou encore librairies. Perl tire sa puissance de la richesse des modules existants ; peu d'autres langages (voire aucun) ne peuvent prétendre être aussi riche que Perl. Par exemple, quasiment tous les protocoles réseau auxquels vous pouvez penser sont accessibles en Perl en utilisant un module existant.

En quelques mots, un module est un ensemble de fonctions regroupées dans un fichier. Ces fonctions y sont regroupées car elles touchent toutes à un même domaine, à un même ensemble de fonctionnalités autour d'une même utilisation, d'un même protocole ...

La première chose que je vous invite à faire, c'est à lancer la commande perl -V : elle affiche toute sorte d'informations, dont le contenu de la variable @INC. Cette variable de type tableau contient la liste des répertoires où seront recherchés les modules. Le nom INC rappelle étrangement (et c'est voulu) la notion d'include en C. L'ordre des répertoires de cette variable est important car si un module vient à être présent dans deux répertoires, seule l'occurrence présente dans le premier répertoire de la liste comptera (mais ce cas proviendrait plutôt d'une erreur de nommage ou d'installation).

Utilisation d'un premier module

Il existe de nombreux modules déjà installés sur votre système ; une distribution de Perl inclut les modules les plus utilisés.

Ainsi, le module nommé Math::Trig ; permet d'accéder à des fonctions mathématiques de trigonométrie autres que les seuls cosinus et sinus prédéfinis dans Perl sous les noms de cos et sin.

Je vous invite à taper la commande perldoc Math::Trig dans un terminal ; vous visualiserez ainsi la documentation de ce module. Cette commande perldoc fonctionne un peu comme la commande man ; vous verrez détaillées les fonctionnalités auxquelles vous avez accès avec un module donné. Vous taperez 'q' pour quitter.

On voit ici que nous avons accès à des fonctions comme tan, acos ou asin ainsi qu'à des fonctions de conversion entre unités d'angles ou bien à la valeur de pi. De petits exemples simples d'utilisations vous sont aussi fournis.

La première ligne de code à écrire pour utiliser un module est la suivante :

    use NomDuModule;

Dans bien des cas, cette instruction ajoute des fonctions et des variables à l'espace de nommage (nous reviendrons sur ce point dans la suite). Pour notre exemple, la ligne est :

    use Math::Trig;

Cette ligne devra être placée dans chaque script qui fait usage du module et être exécutée avant tout usage de fonctions ou de variables du module. Typiquement toutes les lignes use sont regroupées au début du script.

Vous remarquerez que la ligne use strict; que je vous ai conseillé de placer dans chaque script, n'est en fait que le chargement d'un module ; ce module ayant pour rôle de rendre la syntaxe Perl plus coercitive. Le nom des modules de ce type est en minuscule. Ils sont appelés modules pragmatiques. Ils ont pour objet de modifier ou d'étendre la sémantique de Perl. Ainsi diagnostics permet d'avoir des messages d'erreurs plus complets (vous pouvez charger sur CPAN la version 1.2-alpha1 qui vous permet d'avoir ces messages avec des explications en français).

Revenons à notre module Math::Trig. Voici un exemple de code Perl l'utilisant (j'en plagie ici la documentation) :

    use Math::Trig;
    $x = tan(0.9);
    $y = acos(3.7);
    $z = asin(2.4);
    $pi_sur_deux = pi/2;
    $rad = deg2rad(120);

Je laisse au lecteur le soin de deviner (ou plutôt comprendre) ce que font ces instructions. Une fois chargé, un module n'est pas "déchargeable".

D'autres modules

Voici l'exemple d'un autre module : File::Copy ; il permet certaines manipulations de fichiers lourdes à mettre en œuvre avec de simples appels système. Il est par exemple possible de copier un fichier vers un autre (fichiers disque ou flux de données), ou d'en déplacer un d'une partition vers une autre (impossible avec l'appel système rename). Comme l'indique perldoc File::Copy :

    use File::Copy;
    copy("file1","file2");
    copy("Copy.pm",\*STDOUT);
    move("/dev1/fileA","/dev2/fileB");

Voici un autre exemple de module en action. Il s'agit du module Net:FTP qui nous permet d'accéder très simplement aux fonctionnalités d'un client FTP. Voici, par exemple, comment se connecter sur un serveur (en mode passif, car j'ai un firewall), changer de répertoire et télécharger un fichier :

    #!/usr/bin/perl -w
    use strict;
    use Net::FTP;
    my $ftp = Net::FTP->new("ftp.cpan.org",
       Debug => 0, Passive =>1 ) or die("$!");
    $ftp->login("anonymous",'-anonymous@');
    $ftp->cwd("/pub/CPAN/");
    $ftp->get("ls-lR.gz");
    $ftp->quit();

On remarquera au passage la notation objet (new, ->) ; beaucoup de modules l'utilisent. Même si nous ne verrons la programmation objet que dans une prochaine partie, il est aisé de comprendre comment utiliser de tels modules (de toute façon la documentation des modules comporte des exemples).

Quoi de plus simple finalement pour faire du FTP client ? Comment faisais-je avant pour mettre à jour mon site web des seules pages que j'ai modifiées depuis la dernière fois ???

Où trouver les modules ?

C'est très bien tout cela, mais comment trouver le module qui répond à mon problème ? Pour cela je dois vous présenter l'archive de tous les modules Perl, j'ai nommé CPAN (Comprehensive Perl Archive Network). Cette archive recense tous les modules diffusés pour Perl.

Je vous invite à visiter le site http://www.cpan.org/ vous y trouverez de tout à propos de Perl. Vous pouvez télécharger les sources de l'interpréteur (Perl source code), des versions compilées (Perl binary distributions) disponibles pour de très nombreuses plate-formes, ainsi que de la documentation sur les modules et de quoi les télécharger. Le lien intéressant est : CPAN modules, distributions, and authors (search.cpan.org). Une page vous est proposée avec de nombreuses sections listant des modules regroupés par thème, ainsi qu'un champ de saisie servant à la recherche de mots clefs dans les modules. Je vous invite à entrer SMTP et à voir la variété des modules qui gravitent autour de ce protocole ; le module le plus intéressant est sûrement Net::SMTP (plus le nom d'un module est court et semble canonique, plus il y a de chance qu'il soit intéressant). Différents liens permettent de visualiser la documentation (le perldoc correspondant) ainsi que de télécharger le module le cas échéant.

L'installation de modules CPAN n'est pas au menu de ce document, je ne vais pas m'appesantir sur la question ; juste deux mots pour vous dire que les commandes perl Makefile.PL, make, make test et make install sont la clef du succès. Les modules CPAN sont présents sous forme de package dans toute bonne distribution Linux. Par exemple sous Debian, il s'agit des paquets libxxx-yyy-perl (où xxx-yyy correspond au nom du module Xxx::Yyy mis en minuscules).

Même si vous n'installez pas de module, CPAN n'en reste pas moins la source majeure d'informations sur les modules de votre système. Vous vous rendez par exemple compte que le module Net::SMTP répond à vos besoins, vous vérifiez alors que ce module est présent sur votre système en tapant perl -e 'use Net::SMTP' et vous n'avez plus qu'à l'utiliser. La documentation sera accessible par perldoc Net::SMTP

Juste pour sourire deux minutes, je vous invite à rechercher dans CPAN un module nommé Sex écrit un premier avril et d'en lire la documentation (ainsi que le code) ...

Écrire un module

Après avoir manipulé des modules existants et avoir parlé de CPAN, nous allons maintenant apprendre à écrire nos propres modules.

Premier exemple

Pour écrire un module, nous devons créer un fichier indépendant du ou des scripts qui l'utilisent. L'extension de ce fichier est impérativement .pm : par exemple Utils.pm Ce fichier doit être placé dans un des répertoires listés dans la variable @INC ; pour commencer vous pourriez le placer dans votre répertoire de travail à côté du script qui l'utilisera, car le répertoire . est présent dans ce tableau @INC.

Ce fichier doit contenir une première ligne indiquant le nom du module ; pour cela, vous devez écrire :

    package Utils;

Il est important de voir que le nom du package doit être le même que celui du fichier (à l'extension près). Le fichier peut ensuite contenir des définitions de fonctions. Voici un exemple simple d'un tout petit module complet :

    # --- fichier Utils.pm ---
    package Utils;
    use strict;
    sub bonjour
    {
       my ($prenom) = @_;
       print "Bonjour $prenom\n";
    }
    1;

Il est important de ne pas oublier la dernière ligne, celle qui contient 1; ; nous reviendrons plus tard sur son rôle.

Pour pouvoir utiliser ce module dans un script, il est nécessaire d'invoquer l'instruction use suivie du nom du module. Voici un exemple de l'utilisation du module précédent :

    #!/usr/bin/perl -w
    # --- fichier script.pl ---
    use strict;
    use Utils;   # chargement du module
    Utils::bonjour( "Paul" );

La dernière ligne correspond à l'appel de la fonction bonjour du module Utils. La syntaxe est la suivante : le nom du module est suivi de deux signes deux-points puis du nom de la fonction.

Et les variables ?

Il est possible de déclarer des variables propres au module. Ces variables seront :

Une variable accessible exclusivement aux fonctions du module se déclare avec my (que l'on connaît déjà). Une variable aussi accessible depuis l'extérieur du module se déclare avec our (my pour dire "à moi", our pour dire "à nous"). Avant la version 5.6 de Perl, on utilisait un autre mécanisme dont je ne parlerai pas ici, assurez-vous d'avoir une version récente de Perl (cf perl -v). Ces variables doivent être déclarées en dehors de toute fonction ; les variables déclarées dans les fonctions sont comme toujours locales au bloc dans lequel elles sont déclarées.

    # --- fichier Utils.pm ---
    package Utils;
    use strict;
    # variable accessible
    our $x = 'toto';
    # variable inaccessible
    my $y = 'toto';
    # fonction
    sub bonjour
    {
       # Variable locale
       my ($prenom) = @_;
       print "Bonjour $prenom\n";
       print "$x $y\n";
    }
    1;

Que la variable soit déclarée avec my ou avec our, il est tout à fait possible d'y accéder depuis une fonction du module (ici bonjour). À l'inverse, depuis l'extérieur du module, c'est-à-dire depuis le script, seule la variable $x est accessible.

    #!/usr/bin/perl -w
    # --- fichier script.pl ---
    use strict;  
    use Utils;
    Utils::bonjour( "Paul" );
    # Ok :
    print "$Utils::x\n";
    # Erreur :
    print "$Utils::y\n";

De même que pour les fonctions, les noms de variable sont préfixés par le nom du module puis deux signes deux-points. Ici, le nom complet de la variable est donc Utils::x qu'il faut faire précéder d'un signe dollar, ce qui donne : $Utils::x au final. Il n'y a pas d'erreur de ma part : on n'écrit pas Utils::$x ! :-)

De la dernière ligne d'un module

Jusqu'ici, nous avons toujours placé une ligne 1; à la fin du fichier de notre module. Il faut savoir que cette valeur est la valeur du chargement du module (valeur de l'instruction use Utils;) et qu'elle indique si ce chargement s'est bien passé ou non : une valeur fausse indique un problème, une valeur vraie (comme ici 1) indique au contraire que le chargement s'est bien déroulé. Une valeur fausse mettra fin au script qui fait appel à l'instruction use.

Il est donc tout à fait possible de mettre une autre valeur qu'une valeur constante ; on peut, par exemple, envisager mettre un test en dernière instruction pour vérifier si les conditions sont réunies pour l'usage du module. On pourrait imaginer conditionner le chargement du module à l'ouverture d'un fichier, d'une connexion réseau (ou je-ne-sais-quoi encore...). Je ne donnerai pas d'exemple ici car le cas est rare de la nécessité d'un tel usage, mais il faut savoir que cela est possible.

Répertoires

Voyons maintenant comment créer des modules aux noms composés comme Truc::Utils (nous avons par exemple vu le module Net::FTP). Ces noms composés permettent de regrouper les modules par type d'usages ; par exemple Net correspond à tout ce qui concerne le réseau.

Revenons à notre exemple Truc::Utils. Ce nom Truc correspond à un répertoire qui doit être présent dans un des répertoires de la variable @INC (par exemple .) et le fichier Utils.pm doit être présent dans ce répertoire Truc.

Voici un exemple de tel module :

    # --- fichier Truc/Utils.pm ---
    package Truc::Utils;
    use strict;
    our $x = 'toto';
    sub bonjour
    {  
       my ($prenom) = @_;
       print "Bonjour $prenom\n";
    }
    1;

Et voici un script l'utilisant :

    #!/usr/bin/perl -w 
    # --- fichier script.pl ---
    use strict;  
    use Truc::Utils;
    Truc::Utils::bonjour( "Paul" );
    print "$Truc::Utils::x\n";

Rien de sorcier.

Blocs BEGIN et END

Les amoureux de awk retrouveront ici deux de leurs enfants préférés :-)). Dans un module, il est possible de prévoir deux blocs d'instructions qui seront exécutés soit dès le chargement du module (bloc BEGIN) soit lors de la fin de l'usage du module (bloc END).

    package Utils;
    use strict;
    sub f
    { ...  }
    BEGIN
    {
       print "Chargement du module\n";
    }
    END
    {
       print "Fin d'usage du module\n";
    }
    1;

Notez bien qu'il ne s'agit pas de fonctions (pas de mot clef sub), mais bien de blocs labélisés. Le bloc BEGIN sera exécuté lors de l'instruction use Utils; avant toute autre instruction du module (y compris les use placés dans le module). Le bloc END sera exécuté lors de la fin du programme.

L'usage de ces deux blocs peut être nécessaire lorsque l'utilisation du module est conditionnée par l'obtention d'une ou plusieurs ressources comme un fichier ou une connexion réseau. Ces blocs vont nous servir à préparer le terrain au début et à libérer les ressources à la fin.

Lorsque dans un module sont présentes d'autres instructions que des définitions de variables et des définitions de fonctions, ces instructions sont exécutées au moment du chargement du module. Tout se passe comme si ces instructions figurent dans un BEGIN implicite. L'usage d'un bloc BEGIN permet juste au programmeur d'écrire un code un peu plus lisible et propre, dans la mesure où toutes ces instructions sont regroupées sous un nom (BEGIN) qui rappelle explicitement qu'elles sont exécutées au début.

Notez bien que la programmation objet (lire la suite) a quelque peu rendu ces deux blocs obsolètes voire inutiles.

Introduction à l'export de symboles

Sous ce titre barbare se cache une idée simple : il peut être pénible de toujours écrire le nom complet des fonctions de modules. Je veux dire par là que d'écrire Utils::bonjour à chaque fois que vous voulez appeler cette fonction est sans doute lourd et est quelque peu pénible à la longue. Il existe un moyen pour n'avoir qu'a écrire bonjour sans avoir à rappeler le nom du module qui contient la fonction. En faisant cela nous allons ajouter la fonction dans l'espace de nommage du script.

Placer une fonction ou une variable d'un module dans l'espace de nommage d'un script ou d'un autre module s'appelle faire un export, on parle d'exporter le symbole (fonction ou variable). Ce symbole est donc importé par le script.

Pour avoir la capacité d'exporter des symboles, notre module futur-exportateur doit comporter les lignes suivantes :

    package Utils;
    use Exporter;
    our @ISA = qw(Exporter);

Ces deux nouvelles lignes d'instructions doivent être placées juste après l'instruction package. La première est l'invocation du module Exporter ; avec la seconde on indique que notre module est un (ISA) Exporter (nous reverrons cette syntaxe et ses implications en programmation objet). Notre module est maintenant capable d'exporter des symboles.

Il existe quatre types de symboles (fonctions ou variables) :

Chacun des trois premiers ensembles est associé à une variable déclarée avec our.

Export par défaut de symboles

Les symboles exportés par défaut doivent être listés dans la variable @EXPORT ; il s'agit donc d'un tableau. Il est courant d'initialiser ce tableau avec l'opérateur qw que nous avons déjà vu et sur lequel je ne reviendrai donc pas :

    our @EXPORT = qw(&bonjour &hello $var);

Cette ligne placée dans le module Utils à la suite de la ligne

    our @ISA = qw(Exporter);

va permettre d'utiliser les fonctions bonjour et hello ainsi que la variable scalaire $var sans préfixe dans le script utilisateur. Notez bien que, si les variables doivent être citées avec leur caractère de différentiation de type (le dollar, l'arobase ou le pourcentage), il en est de même avec les fonctions et le signe "et-commercial" (&). Sachez juste que ce et-commercial peut être omis.

Voici comment on peut maintenant utiliser le module en question :

    use Utils;
    bonjour("Paul");
    hello("Peter");
    print "$var\n";

Plutôt simple.

Export individuel de symboles

Un symbole peut être exporté à la demande de celui qui utilise le module. C'est-à-dire que ce symbole n'est pas exporté par défaut, mais il peut faire l'objet d'un export s'il est nommément cité lors de l'instruction use.

Un symbole doit apparaître dans la variable @EXPORT_OK pour être autorisé à être exporté :

    our @EXPORT_OK = qw(&gutenTag &ciao $var2);

Ces trois symboles sont maintenant exportables dans le script utilisant ce module. Pour cela il convient d'ajouter une liste de symboles à l'instruction use :

    use Utils qw(&ciao $var2);
    ciao("Paula");
    print "$var2\n";

Cette ligne importe donc les symboles demandés et ces derniers sont donc utilisables sans préfixe.

Il se trouve qu'une telle ligne n'importe plus les symboles par défaut (ceux de la variable @EXPORT) ; ne me demandez pas pourquoi, je trouve cela aussi stupide que vous ... Pour remédier à cela, il nous faut ajouter à la liste des imports le tag :DEFAULT :

    use Utils qw(:DEFAULT &ciao $var2); 
    bonjour("Paul");
    hello("Peter");
    print "$var\n";
    ciao("Paula");
    print "$var2\n";

Ce mécanisme de sélection des symboles exportés permet à l'utilisateur du module de ne pas trop polluer son espace de nommage et de choisir les seules fonctions dont il aura besoin.

Export par tags de symboles

Il est possible de regrouper les symboles dans des tags. Un tag est une liste de symboles. L'import d'un tag provoque l'import de tous les symboles composant ce tag. La variable qui entre ici en jeu est %EXPORT_TAGS ; il s'agit donc d'une table de hachage. À chaque tag est associée une référence vers un tableau contenant la liste des symboles du tag :

    our %EXPORT_TAGS=(T1=>[qw(&ciao &gutenTag)],
                      T2=>[qw(&ciao $var2)]);

Le tag T1 est associé aux fonctions ciao et gutenTag. Le tag T2 est associé à la fonction ciao et à la variable $var2. Le nom des tags est par convention en majuscules.

Remarque importante : les symboles présents dans les listes associées aux tags doivent absolument être présents dans @EXPORT et/ou @EXPORT_OK. Dans le cas contraire, leur export sera impossible.

Voici un usage de ce module :

    use Utils qw(:T2);
    ciao("Paula");
    print "$var2\n";

Le nom du tag est placé dans la liste des modules précédé par le signe deux-points. Il est possible de combiner les différents types d'accès :

    use Utils qw(:DEFAULT &ciao :T1);
    bonjour("Paul");
    hello("Peter");
    print "$var\n";
    ciao("Paula");
    print "$var2\n";
    gutenTag("Hans");

On voit alors que DEFAULT est un tag.

Exemple complet d'exports

Voici un exemple complet d'usage des exports dans les modules ; j'ai essayé de regrouper toutes les configurations.

Voici le module Utils dans le fichier Utils.pm :

    package Utils;
    use strict;
    use Exporter;
    our @ISA = qw(Exporter);
    our @EXPORT = qw(&f1 &f2);
    our @EXPORT_OK = qw(&f3 &f4 &f5 &f6);
    our %EXPORT_TAGS = (T1 => [qw(&f5 &f6)],
                        T2 => [qw(&f4 &f6)]);
    sub f1 { print "f1\n"; }
    sub f2 { print "f2\n"; }
    sub f3 { print "f3\n"; }
    sub f4 { print "f4\n"; }
    sub f5 { print "f5\n"; }
    sub f6 { print "f6\n"; }
    1;

Et voici un script l'utilisant (après chaque appel de fonction est signalée la raison qui fait qu'il est possible de l'appeler sans préfixe) :

    #!/usr/bin/perl -w
    use strict;
    use Utils qw(:DEFAULT :T2 &f3);
    f1();         # tag DEFAULT
    f2();         # tag DEFAULT
    f3();         # individuellement
    f4();         # tag T2
    Utils::f5();  # pas importée
    f6();         # tag T2

Notez bien le cas de la fonction f5 qui n'est pas importée, mais qui n'en reste pas moins utilisable.

Pour plus d'informations et d'exemples je vous invite à vous référer à perldoc Exporter.

Fonctions inaccessibles

Vous allez me poser la question suivante : comment faire pour rendre une fonction d'un module inaccessible depuis le script ? Et je vous répondrai : cela n'est a priori pas possible (vous allez voir que si finalement).

Vous l'avez compris, Perl n'est pas un langage extrêmement coercitif, notamment par rapport à des langages comme Java ou C++. Il n'y a donc rien de prévu dans le langage pour rendre certaines fonctions uniquement accessibles depuis l'intérieur du module. Est alors apparue la convention suivante : toute fonction ou variable dont le nom commence par un souligné (ou under-score '_') est privée et ne doit pas être utilisée à l'extérieur du module.

Cette confiance en l'utilisateur du module est souvent suffisante et les modules CPAN sont bâtis sur ce modèle.

Néanmoins, si vous êtes outré par ce que je viens d'écrire car vous êtes un fanatique de Java ou autres, il existe un moyen d'écrire des fonctions vraiment internes aux modules. Il faut pour cela déclarer une variable avec my (donc invisible depuis l'extérieur du module) et d'en faire une référence anonyme vers fonction :

    package Utils;
    use strict;
    my $affiche = sub
    {
       my ($n,$m) = @_;
       print "$n, $m\n";
    };

La variable $affiche est donc une variable privée qui pointe vers une fonction anonyme. Son usage est donc réservé aux fonctions déclarées dans le module :

    sub truc
    {
       $affiche->(4,5);
    }

Remarquez que, comme le code Perl est toujours accessible en lecture, il est toujours possible à l'utilisateur du module de prendre le code en copier-coller et d'en faire une fonction personnelle ... Perl n'est pas fait pour les paranoïaques.

Documentation des modules

Documenter son travail est important pour une ré-utilisation du code par d'autres ou même par soi-même plus tard ... En Perl la documentation des modules se fait dans le code même du module. Une syntaxe particulière, nommée POD, permet cela. Les instructions POD commencent toujours par le signe égal (=).

La documentation d'un module commence typiquement ainsi :

    =head1 NAME

    Utils.pm - Useful functions

    =head1 SYNOPSIS

     use Utils;
     bonjour("Paul");

    =head1 DESCRIPTION

     Blabla blabla

    =head2 Exports

    =over

    =item :T1 Blabla

    =item :T2 Blabla

    =back

    =cut

Les tags =head1 définissent des en-têtes de premier niveau (des gros titres) et les tags =head2 définissent des en-têtes de deuxième niveau (des sous-titres). Il est de coutume de mettre les premiers exclusivement en majuscules. Les tags =over, =item et =back permettent de mettre en place une liste. Le reste du texte est libre. Le tag =cut indique la fin du POD.

Les blocs de POD et les portions de code peuvent alterner : cela est même recommandé de documenter une fonction et d'en faire suivre le code. Pour cela vous devez savoir que l'apparition en début de ligne d'un tag POD indique la fin temporaire du code Perl et le début d'un bloc de documentation. La fin de ce POD est signalée à l'aide du tag =cut et le code Perl peut alors reprendre.

    package Utils;

    =head1 FUNCTION hello

     This function prints hello.

    =cut

    sub hello
    {
       my ($firstName) = @_;
       print "Hello $firstName\n";
    }

    =head1 FUNCTION bonjour

     This function prints hello in french.

    =cut
    sub bonjour
    {
       my ($prenom) = @_;
       print "Bonjour $prenom\n";
    }

Comment visualiser une telle documentation, allez-vous me demander ? Rien de plus simple : perldoc est notre allié ! Tapez donc perldoc Utils (ou tout autre nom que vous aurez choisi de donner à votre module) et sa documentation apparaît au format man comme tout bon module CPAN. Quoi de plus simple ?

    NAME
           Utils.pm - Useful functions
    
    SYNOPSIS
           use Utils;
           bonjour("Paul");
    
    DESCRIPTION
           Blabla blabla
    
           Exports
    
           :T1 Blabla
           :T2 Blabla
    
    FUNCTION hello
           This function prints hello.
    
    FUNCTION bonjour
           This function prints hello in french.

Pour plus d'informations et de détails sur ce format, je vous invite à consulter perldoc perlpod où de nombreux exemples sont donnés. Vous pouvez aussi jeter un oeil au code d'un module ou deux dont le perldoc vous intrigue ...

Un dernier mot sur les modules

J'espère que la lecture de cette partie vous a donné envie de structurer votre code en regroupant vos fonctions dans de telles bibliothèques. Vous vous rendrez compte de cette nécessité lorsque vous aurez un fichier de code trop gros à gérer ... Mais même sans cela, n'hésitez pas à faire des modules, ne serait-ce que pour une ré-utilisation de fonctionnalités dans d'autres scripts ou pour partager votre code avec des amis, des collègues voire avec la communauté.

L'auteur

Sylvain Lhullier sylvain@lhullier.org http://sylvain.lhullier.org/

À l'Université de Marne-la-Vallée (http://www.univ-mlv.fr/), il est chargé chaque année d'un module complet d'enseignement en maîtrise informatique ; ce module porte sur des sujets tels que Perl, Perl/Tk, Perl/DBI, Apache, CGI/Perl et consiste en dix semaines d'un cours en amphithéatre et de trois travaux dirigés, ainsi qu'en un examen final et un projet.

Il a travaillé pour Linagora (http://www.linagora.com/) comme consultant formateur et développeur ; il intervenait principalement pour des projets et prestations concernant le développement (Perl, Java, C++, programmation système, PHP, Apache, MySQL, XML etc.).

Il a développé chez feue-Atrid des projets bâtis en Perl (LogTrend, Mioga) et publiés sous GPL.

Il a donné une conférence "Perl : pour quoi faire ?" lors du salon LinuxSolutions de janvier 2004.

Entre autres associations, il est membre et administrateur de l'association "Les Mongueurs de Perl" dont l'objet est de promouvoir le langage Perl en France par des réunions, des conférences etc (http://www.mongueurs.net/). Il y coordonne le groupe de travail "Articles" dont le but est de publier un article dans la presse francophone technique, notamment dans GNU/Linux & Hurd Magazine France (http://www.linuxmag-france.org/) chaque mois. L'auteur tient à remercier très chaleuseusement les autres membres de l'association pour leur aide, leur soutien et les relectures effectuées.

[IE7, par Dean Edwards] [Validation du HTML] [Validation du CSS]