🐪 Perl — Guide PRO (Modern Perl / CPAN / Web / DBI / Tests)
Du script UNIX aux APIs web modernes : CPAN, DBI/DBIx, Mojolicious/Dancer2, Regex avancées, profiling NYTProf, sécurité (taint), packaging & CI.
Toolchain & Install
perlbrew/plenv, cpanm, Carton
InstallSyntaxe & Bases
scalaires, arrays, hashes, refs
BasicsRegex avancées
PCRE, lookaround, atomic, named
RegexOne-liners
-ne/-pe, -0777, autosplit
OneModules & CPAN
cpanm, Carton, META.json
CPANOOP (Moose/Moo)
attrs, roles, immutabilité
OOPDBI & DBIx::Class
connect, placeholders, schema
DBIFichiers & IO
encodage, layers, File::Temp
IOProcess/IPC
system, open3, IPC::Run
IPCMojolicious
routing, templates, websockets
MojoDancer2
config, routes, plugins
Dancer2PSGI/Plack
middleware, starman, psgi app
PSGITemplate Toolkit
TT2, INCLUDE_PATH, filters
TTTests (Test::More/Test2)
prove, TAP, Test::Mojo
TestsProfiling & Perf
Devel::NYTProf, Benchmark
PerfDebugging
perl -d, Devel::REPL
DebugUnicode & Texte
binmode, utf8::all, Encode
UTF8Sécurité & Taint (-T)
PATH réduit, Safe, chroot
SecurityScripting sysadmin
cron, journaux, glue sed/awk
OpsPackaging & CI
Carton, Dockerfile, GH Actions
CIXS & FFI
Inline::C, FFI::Platypus
FFIDates & Time
DateTime, Time::HiRes
TimeJSON/YAML/CSV
Cpanel::JSON::XS, YAML::XS
FormatsEmail & MIME
Email::Stuffer, MIME::Lite
MailWeb client
HTTP::Tiny, Mojo::UserAgent
HTTPScraping
Mojo::DOM, WWW::Mechanize
ScrapeQueues/Workers
Minion (Mojo), TheSchwartz
QueueCLI UX
Getopt::Long::Descriptive, Term
CLILogs & Obs
Log::Any/Log4perl, Sys::Syslog
LogsRéférences & Cheat
Docs, livres, liens utiles
Refs- Objectifs **TOOLCHAIN** en prod.
- Patterns robustes.
- Points durs & pièges.
# perlbrew curl -L https://install.perlbrew.pl | bash perlbrew init && perlbrew install perl-5.38.0 && perlbrew switch perl-5.38.0 # plenv git clone https://github.com/tokuhirom/plenv ~/.plenv ~/.plenv/bin/plenv install 5.38.0 && ~/.plenv/bin/plenv global 5.38.0 # cpanm + Carton cpanm Carton echo 'requires "Mojolicious", "==9.45";' > cpanfile carton install carton exec perl -MMojolicious -e 'say $Mojolicious::VERSION'
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **BASICS** en prod.
- Patterns robustes.
- Points durs & pièges.
use v5.36; use strict; use warnings; use utf8;
my $s = "Hello"; my @a = (1,2,3); my %h = (k=>'v');
say $h{k};
# refs
my $ar = \@a; my $hr = \%h;
say $ar->[0]; say $hr->{k};
# sub signatures
sub add($x,$y){ return $x+$y }
say add(2,40);- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **REGEX** en prod.
- Patterns robustes.
- Points durs & pièges.
use v5.36; use strict; use warnings;
my $s = "user:42 email:foo@example.com";
if($s =~ /email:([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,})/){ say $1 }
# lookaround
"abc123xyz" =~ /(?<=abc)\d+(?=xyz)/ and say $&;
# named captures
"foo=99" =~ /(?\w+)=(?\d+)/; say "$+{key} -> $+{val}";
# atomic & possessive
"aaaaab" =~ /a++b/ and say "OK possessive"; - `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **ONE** en prod.
- Patterns robustes.
- Points durs & pièges.
# Compter lignes
perl -ne 'END{print $.,"\n"}' file.txt
# Extraire emails uniques
perl -ne 'print "$1\n" if /([A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+)/' *.log | sort -u
# Remplacer in-place (backup)
perl -i.bak -pe 's/DEBUG\s*=\s*1/DEBUG=0/' app.conf
# JSON pretty
perl -MJSON::PP -e 'print encode_json({ok=>1})'- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **CPAN** en prod.
- Patterns robustes.
- Points durs & pièges.
cpanm Mojolicious DBI DBIx::Class Cpanel::JSON::XS YAML::XS echo 'requires "DBI"; requires "Mojolicious";' > cpanfile carton install # META workflow perl Makefile.PL && make && make test && make install
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **OOP** en prod.
- Patterns robustes.
- Points durs & pièges.
use v5.36; use Moo;
has 'name', is=>'rw';
sub greet($self){ say "Hi, " . $self->name }
my $o = __PACKAGE__->new(name=>'Ada'); $o->greet;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **DBI** en prod.
- Patterns robustes.
- Points durs & pièges.
use DBI;
my $dbh = DBI->connect("dbi:Pg:dbname=app","user","pass",{RaiseError=>1,AutoCommit=>1});
my $tx = eval {
$dbh->begin_work;
my $sth = $dbh->prepare("INSERT INTO users(name) VALUES(?) RETURNING id");
$sth->execute("Ada");
my ($id) = $sth->fetchrow_array;
$dbh->commit; $id;
}; if($@){ $dbh->rollback; die $@ }
print "new id=$tx\n";\n\n# DBIx::Class schema (simplifié)
package My::Schema; use base 'DBIx::Class::Schema'; __PACKAGE__->load_namespaces;
package My::Schema::Result::User; use base 'DBIx::Class::Core';
__PACKAGE__->table('users');
__PACKAGE__->add_columns(qw/id name/); __PACKAGE__->set_primary_key('id');
# usage
my $schema = My::Schema->connect('dbi:Pg:dbname=app','user','pass');
$schema->resultset('User')->create({name=>'Ada'});- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **IO** en prod.
- Patterns robustes.
- Points durs & pièges.
use v5.36; use autodie; use open ':std', ':encoding(UTF-8)';
open my $fh, '<:encoding(UTF-8)', 'in.txt';
while(my $l = <$fh>){ print $l }- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **IPC** en prod.
- Patterns robustes.
- Points durs & pièges.
use IPC::Open3; use Symbol 'gensym'; my $err = gensym; my $pid = open3(undef, \*OUT, $err, 'ls','-la'); while(){ print } while(<$err>){ warn } waitpid $pid, 0;
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **MOJO** en prod.
- Patterns robustes.
- Points durs & pièges.
use Mojolicious::Lite;
plugin 'Config';
under sub($c){ return 1 if $c->req->headers->header('X-Token') // '' eq 'secret'; $c->render(text=>'401',status=>401); return undef; };
get '/health' => sub ($c){ $c->render(json=>{ok=>1}) };
post '/echo' => sub ($c){ $c->render(json=>$c->req->json) };
websocket '/ws' => sub($c){ $c->on(message=>sub($c,$msg){ $c->send("echo:$msg") }) };
app->start;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **DANCER2** en prod.
- Patterns robustes.
- Points durs & pièges.
use Dancer2; get '/hi' => sub { 'hello' }; dance;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **PSGI** en prod.
- Patterns robustes.
- Points durs & pièges.
my $app = sub {
my $env = shift;
return [200, ['Content-Type'=>'text/plain'], ['hello']];
};
use Plack::Builder;
builder {
enable 'Deflater';
enable 'AccessLog';
$app;
};- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **TT** en prod.
- Patterns robustes.
- Points durs & pièges.
[% SET name = 'world' %] Hello [% name | upper %]! [% FOREACH u IN users %]- [% u.name %]\n[% END %]
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **TESTS** en prod.
- Patterns robustes.
- Points durs & pièges.
use Test::More;
use Test::Mojo;
my $t = Test::Mojo->new('MyApp'); # Mojolicious::Lite app in lib/MyApp.pm
$t->get_ok('/health')->status_is(200)->json_is('/ok'=>1);
done_testing();- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **PERF** en prod.
- Patterns robustes.
- Points durs & pièges.
perl -MDevel::NYTProf script.pl
nytprofhtml --open
# micro-bench
use Benchmark qw/:all/;
cmpthese(-1, { split => sub { my @x = split /,/, 'a,b,c' },
regex => sub { 'a,b,c' =~ /(.+),(.+),(.+)/ } });- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **DEBUG** en prod.
- Patterns robustes.
- Points durs & pièges.
perl -d script.pl # b (breakpoint), s / n (step/next), p expr, x \@array
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **UTF8** en prod.
- Patterns robustes.
- Points durs & pièges.
use utf8; use open ':std', ':encoding(UTF-8)'; binmode STDOUT, ':encoding(UTF-8)'; print "éàï — OK\n";
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **SEC** en prod.
- Patterns robustes.
- Points durs & pièges.
#!/usr/bin/env perl -T
$ENV{PATH} = '/usr/bin:/bin'; delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
# Safe open
use autodie; open my $fh, '<', '/var/app/input.txt';
# Validate args
die "bad" unless ($ARGV[0] // '') =~ /^[a-z0-9_-]{1,32}$/i;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **OPS** en prod.
- Patterns robustes.
- Points durs & pièges.
# cron
* * * * * /usr/bin/carton exec -- perl /srv/app/worker.pl >>/var/log/app/worker.log 2>&1
# tail syslog
perl -MFile::Tail -e '$f=File::Tail->new("/var/log/syslog"); while(defined($l=$f->read)){print $l}'- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **CI** en prod.
- Patterns robustes.
- Points durs & pièges.
# Dockerfile
FROM perl:5.38
WORKDIR /app
COPY cpanfile* ./
RUN cpanm Carton && carton install
COPY . .
CMD ["carton","exec","plackup","-Ilib","app.psgi"]
# GitHub Actions (extrait)
- uses: shogo82148/actions-setup-perl@v1
with: { perl-version: '5.38' }
- run: cpanm Carton && carton install
- run: prove -lr t/- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **FFI** en prod.
- Patterns robustes.
- Points durs & pièges.
use FFI::Platypus; my $ffi=FFI::Platypus->new(api=>1);
$ffi->lib('libm.so.6');
my $cos = $ffi->function(cos => ['double'] => 'double');
print $cos->call(0.0);- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **TIME** en prod.
- Patterns robustes.
- Points durs & pièges.
use DateTime; say DateTime->now->iso8601;
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **FORMATS** en prod.
- Patterns robustes.
- Points durs & pièges.
use Cpanel::JSON::XS qw(encode_json decode_json);
use YAML::XS qw(Load Dump);
print encode_json({ok=>1}), "\n";
print Dump({foo=>[1,2,3]});- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **MAIL** en prod.
- Patterns robustes.
- Points durs & pièges.
use Email::Stuffer;
Email::Stuffer->from('x@y')->to('z@w')->subject('Hi')->text_body('ok')->send;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **HTTP** en prod.
- Patterns robustes.
- Points durs & pièges.
use Mojo::UserAgent;
my $ua = Mojo::UserAgent->new; $ua->inactivity_timeout(5);
say $ua->get('https://ifconfig.me')->result->body;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **SCRAPE** en prod.
- Patterns robustes.
- Points durs & pièges.
use Mojo::UserAgent;
my $tx = Mojo::UserAgent->new->get('https://example.com')->result;
say $_->all_text for $tx->dom->find('a')->each;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **QUEUE** en prod.
- Patterns robustes.
- Points durs & pièges.
use Mojolicious::Lite; plugin Minion => { SQLite=>'sqlite:tmp.db' };
app->minion->add_task(slow => sub ($job,$n){ sleep $n; $job->finish('ok') });
get '/enqueue' => sub ($c){ my $id = $c->minion->enqueue(slow=>[2]); $c->render(text=>$id) };
app->start;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **CLI** en prod.
- Patterns robustes.
- Points durs & pièges.
use Getopt::Long::Descriptive;
my ($opt,$usage) = describe_options('%c %o','--host=s','--port=i');
print $usage->text if $opt->help;- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **LOGS** en prod.
- Patterns robustes.
- Points durs & pièges.
use Log::Log4perl;
Log::Log4perl->easy_init($INFO);
my $log=Log::Log4perl->get_logger; $log->info('ok');- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
- Objectifs **REFS** en prod.
- Patterns robustes.
- Points durs & pièges.
- perldoc.perl.org
- modernperlbooks.com
- mojolicious.org
- metacpan.org
- dbix-class.org
- `use v5.36; use strict; use warnings;`
- `use autodie;` pour IO/process
- Encodage explicite (`open` layers, `binmode`)
- Globals implicites
- Regex gourmandes non ancrées
- `system` sans vérification d'état
| KPI | Cible | Action |
|---|---|---|
| Temps d’exécution | Stable | Profiler NYTProf |
| Couverture tests | >=80% | `prove -lr t/` + CI |
| Latence HTTP | p95 maîtrisé | Mojo::UserAgent + timeouts |
- Shebang `#!/usr/bin/env perl`
- `strict/warnings` activés
- `carton install` deps verrouillées
- `perltidy`/`perlcritic` en CI
# t/01_basic.t use Test::More; ok(1,'loaded'); done_testing();
# Template snippet use v5.36; use strict; use warnings;
