Pourquoi se soucier des vieux Perl ?
Parce qu'il y a énormément de code Perl caché qui tourne sur de vieux systèmes
Parce qu'on peut donc s'y trouver confronté
Pourquoi ne pas mettre Perl à jour ?
Parce qu'il y a souvent des contraintes et que ce n'est pas toujours possible
Missionné sur un poste d'expert Perl
But : maintenir du vieux code, développer du nouveau
Plate-forme : plus de 1000 serveurs
Certains ont été installés il y a plusieurs années
Vieux systèmes, vieux Perls
Perl 5.000 : octobre 1994
Perl 5.001 : mars 1995
Perl 5.002 : février 1996
Perl 5.003 : juin 1996
Perl 5.004 : mai 1997
Perl 5.005 : juillet 1998
Perl 5.6 : mars 2000
Perl 5.8 : juillet 2002
Perl 5.10 : Noël 2006 ?
core
la distribution standard de Perl, l'ensemble des modules préinstallés avec Perl
pragma
module avec un nom en minuscule, souvent lexical, par exemple strict
et warnings
Au niveau du langage
version
syntaxe
fonctionnalités
Au niveau des modules
version
fonctionnalités
disponibilité
use 5.8
ou require 5.8
Origine de ce prérequis
ajouté par un outil de génération de code, par exemple h2xs
ajouté intentionnellement par l'auteur
Pertinence
si non pertinent, on peut retirer ce prérequis et gagner
peut-être
si pertinent, il faut continuer à chercher
Exemple
use 5.008006
est typique de h2xs
Peut donc généralement être supprimé
Mots-clés et opérateurs
Fonctions
Chaînes
Regexps
Mots-clés et opérateurs
our
(Perl 5.6)
state
(Perl 5.10)
//
(Perl 5.10 ou 5.8+DOR)
our
Généralement utilisé à tort et à travers
Variables privées d'un package peuvent être déclarées avec my
package TwoFlowers; my $config;
Variables globales à usage unique peuvent être placées dans un
bloc no strict
{ no strict; $VERSION = '1.23'; @ISA = qw(Flower); }
Variables publiques déclarées avec vars
use vars qw($DEBUG);
Fonctions
open()
binmode()
open()
Syntaxe très protéiforme avec plusieurs modes différents
Mais déjà en place depuis longtemps
Toutefois, deux ajouts récents sont couramment utilisés
open(FILEHANDLE, $path)
vs open my $fh, $path
Fonctionalité introduite avec Perl 5.6
Syntaxe valide dans les anciens Perls
Mais $fh
pas automatiquement affecté
Solution : créer manuellement le descripteur de fichier
use FileHandle; open my $fh = new FileHandle, $path;
ou, plus lisible
use FileHandle; my $fh = new FileHandle; open $fh, $path;
open()
avec 3 arguments
open($fh, '<', $path);
Syntaxe introduite avec Perl 5.6
Seule solution simple : retransformer en open()
à 2 arguments
open($fh, '<'.$path);
Problème : perte de la protection supplémentaire
Note : le code suivant ne marche pas :-(
my @args = ('>', $path); open(FH, @args);
Chaînes
v-strings
qr//
v-strings
Syntaxe introduite avec Perl 5.6
Tout usage autre que pour définir un numéro de version est à proscrire
Cas non rencontré personnellement
v-strings
Solution : utiliser version
(fonctionne à partir de 5.005_04)
Avantage : interface objet avec surcharge d'opérateurs
Exemple :
use version; my $vers1 = version->new("1.2.3"); my $vers2 = version->new("1.2.5"); if ($vers1 < $vers2) { ... }
v-strings
Solution : revenir à de simples chaînes de caractères ou à des flottants
Avantage : technique éprouvée, utilisée depuis des années
Inconvénient : moins fiable
Exemple avec des flottants :
if ($version > 2.034) { ... }
Exemple avec des chaînes :
if ($version gt "2.034") { ... }
qr//
Syntaxe introduite avec Perl 5.005
Souvent rencontrée dans les suites de test
Typiquement dans like( $result, qr/regexp/ )
Peut donc être remplacée par une chaîne simple sans risque fonctionnel
Utilisation dans du code fonctionnel
Le remplacement de qr//
risque surtout d'entraîner une diminution
de la lisibilité du code, par exemple sur une grosse regexp écrite avec
qr/.../x
Regexps
Assertions
Classes
Motifs étendus
Assertions
\z
(Perl 5.005)
\Z
est vraie en fin de chaîne ou avant un saut de ligne
\z
est vraie en fin de chaîne
Sera vu comme "z"
par Perl 5.004
Donc nécessité de protéger l'utilisation de cette assertion
my $end = $] >= 5.006 ? "\\z" : "\\Z"; substr($path, 0, -$ignore) =~ s/X(?=X*$end)/$CHARS[int(rand($#CHARS))]/ge;
Classes
Classes POSIX [:class:]
(Perl 5.6)
Solution : remplacer par leur équivalent explicite, cf. perlre
Classes Unicode (Perl 5.6)
\x{263a} caractère hexadecimal étendu \N{nom} caractère nommé
\pP Reconnaît la propriété P (nommée). Utiliser \p{Prop} pour des noms longs \X Reconnaît le séquence de caractères Unicode étendue équivalent a (?:\\PM\pM*) \C Reconnaît un caractère d'un seul octet même sous utft8.
Motifs étendus
(?#text)
(Perl 5.003)
(?imsx-imsx)
(Perl 5.003)
(?:pattern)
(Perl 5.003)
(?=pattern)
(Perl 5.003)
(?!pattern)
(Perl 5.003)
(?<=pattern)
(Perl 5.005)
(?<!pattern)
(Perl 5.005)
Motifs étendus
(?>pattern)
(Perl 5.005, experimental)
(?(condition)yes-pattern|no-pattern)
(Perl 5.005, experimental)
(?{ code })
(Perl 5.005, experimental)
(??{ code })
(Perl 5.6, experimental)
Dépendances possibles :
pragmas
modules du core
modules du CPAN
warnings
Introduit dans Perl 5.6
Active et désactive les avertissements de manière lexicale
use warnings;
sub init { no warnings 'redefine'; *DEBUG = \&debug if $debug; }
Catégories d'avertissements personnalisées avec warnings::register
C'est la première cause d'incompatibilité avec les anciens Perl
Pourtant $^W
est disponible depuis Perl 5.0
...
warnings
C'était la première cause d'incompatibilité avec les anciens Perl
JFDI : warnings-compat
$CPAN/S/SA/SAPER/warnings-compat-0.03.tar.gz
$ perl5.00405 -e 'use warnings; warnings::warnif "hello"' hello at -e line 1 $ perl5.00405 -e 'no warnings; warnings::warnif "hello"' $
warnings-compat
Quelques limitations, mais ça marche !
use warnings::register;
{ no warnings 'redefine'; ... }
warnings::warnif "...";
Limitations :
Non lexicale
Catégories non utilisées
base
Introduit dans Perl 5.005
Établit une relation de dérivation de classe
Mais relativement complexe pour son but
Et en conséquence fragile
Déconseillé par plusieurs porters
base
Solution : remplacer par le code équivalent
use base qw(Parse::Syslog);
devient
use Parse::Syslog;
{ no strict; push @ISA, qw(Parse::Syslog); }
constant
Introduit dans Perl 5.004
Mais les fonctionnalités ont évolué
En particulier, les déclarations groupées :
use constant { PROTOCOL_NAME => "http", PROTOCOL_PORT => 80, PROTOCOL_TYPE => "stream", };
doivent être récrites :
use constant PROTOCOL_NAME => "http"; use constant PROTOCOL_PORT => 80; use constant PROTOCOL_TYPE => "stream";
Important : le core évolue !
Vérifier les dates et versions d'introduction
Module::CoreList
, corelist
$ corelist Data::Dumper Data::Dumper was first released with perl 5.005
Vérifier aussi la disponibilité sur le CPAN
Un nombre croissant de modules sont à double vie
Des modules du CPAN sont régulièrement intégrés au core
Des modules du core sont régulièrement mis à disposition indépendamment sur le CPAN
Modules corifiés :
5.004 : CGI
, CPAN
5.005 : Test
5.6 : File::Temp
, Pod::Parser
, Term::ANSIColor
5.8 : Encode
, Filter::Simple
, Locale::Maketext
,
Scalar::Util
, List::Util
, Storable
, Test::More
5.10 : version
, CPANPLUS
et ses nombreuses dépendances
(Archive::Tar
, IO::Zlib
, Module::Pluggable
)
Modules cpanifiés :
2001 : Test::Harness
2002 : Safe
, ExtUtils::MakeMaker
2003 : Data::Dumper
2004 : XSLoader
2005 : Sys::Syslog
2006 : ExtUtils::Install
, threads
, threads::shared
, Exporter
Modules du core évoluent aussi
Ajouts de fonctionnalités
Corrections de bugs
Mises à jour indépendantes de Perl
Utiliser des modules du CPAN
Utilisez des modules du CPAN
Ceci est un ordre, pas une requête
Pas de raison de s'en priver
L'argument « je veux me limiter aux modules du core » n'est pas recevable
Solution simple et efficace :
placer les modules utilisés dans un répertoire privé
use lib
Utilisation de paquets conseillée pour le déploiement et la gestion
CPAN
Les anciennes versions des modules à double vie sont souvent conservés sur le CPAN
BackPAN
Miroir CPAN sans effacement des fichiers
http://backpan.cpan.org/ (maintenu par Elaine Ashton)
http://backpan.perl.org/ (maintenu par Robert Spier)