← Perl EnglishChapter 13 of 13

Best Practices

## Learning Objectives - Write maintainable Perl code - Use strict and warnings - Master debugging techniques - Apply testing practices - Follow conventions ## Essential Pragmas ### Always Use strict ```perl use strict; # Forces: # - Variable declaration (my/our) # - Package qualification for globals # - Bareword protection my $var = "test"; # $untyped = "error"; # Would error ``` ### Always Use warnings ```perl use warnings; # Warns about: # - Using undef values # - Bareword filehandles # - Keyword shadows # - etc. ``` ### Combined ```perl use strict; use warnings; # Or combined use strictures 2; # Equivalent to strict + warnings (CPAN) ``` ### Version Requirement ```perl use 5.014; # Minimum Perl version use 5.010; # Enable features like given/when ``` ## Variable Declaration ### Use my and our ```perl use strict; use warnings; # Lexical (scoped) variables my $local = "scoped"; # Package (global) variables our $global = "package-wide"; # Always declare before use ``` ### Initialize Variables ```perl use strict; use warnings; my $count = 0; # Initialize to known value my @items = (); # Empty array my %data = {}; # Empty hash # Avoid undef where possible ``` ## Naming Conventions ### Variable Names ```perl use strict; use warnings; # snake_case for variables and functions my $first_name = "Alice"; sub calculate_total { } # Descriptive names my $user_count = 0; my $is_valid = 1; # Avoid single letters (except $_ or common loop vars) my $i; # OK for simple loops ``` ### Package Names ```perl # Use capital letters for packages package My::Module; package Data::Processor; # Version with $VERSION our $VERSION = "1.00"; ``` ## Code Layout ### Indentation ```perl use strict; use warnings; if ($condition) { do_something(); if ($other) { do_other(); } } ``` ### Line Length ```perl # Keep lines around 80 characters my $very_long_variable_name = some_function( argument1 => $value, argument2 => $other_value, ); ``` ## Error Handling ### die for Fatal Errors ```perl use strict; use warnings; open my $fh, "<", "file.txt" or die "Cannot open: $!"; ``` ### eval for Recoverable Errors ```perl use strict; use warnings; eval { risky_operation(); }; if ($@) { warn "Error: $@"; # Handle gracefully } ``` ### autodie Pragma ```perl use strict; use warnings; use autodie; # Automatically dies on failure open my $fh, "<", "file.txt"; # Dies if fails ``` ## References ### Always Dereference Properly ```perl use strict; use warnings; my $arr_ref = [1, 2, 3]; # Dereference properly my @arr = @$arr_ref; my $first = $arr_ref->[0]; my $hash_ref = { a => 1 }; my %hash = %$hash_ref; my $val = $hash_ref->{a}; ``` ### Avoid Symbolic References ```perl use strict; use warnings; my $var = "hello"; # Bad - symbolic reference (blocked by strict) # print ${"var"}; # Error with strict # Good - direct reference print $var; ``` ## Subroutines ### Named Parameters ```perl use strict; use warnings; sub create_user { my %args = @_; my $name = $args{name} // "Anonymous"; my $age = $args{age} // 0; # ... } create_user(name => "Alice", age => 30); ``` ### Early Returns ```perl sub process { my ($data) = @_; return unless defined $data; return if $data eq ""; # Main processing } ``` ## File Handles ### Lexical Filehandles ```perl use strict; use warnings; # Always use lexical filehandles open my $fh, "<", "file.txt" or die "Cannot open: $!"; # ... close $fh; # With autodie use autodie; open my $fh, "<", "file.txt"; ``` ## Regular Expressions ### Use /x for Complex Patterns ```perl use strict; use warnings; # Readable regex if ($date =~ / (\d{4}) # Year - # Dash (\d{2}) # Month - # Dash (\d{2}) # Day /x) { print "Year: $1\n"; } ``` ### Compile Regexes ```perl use strict; use warnings; my $pattern = qr/\d{3}-\d{4}/; if ($text =~ $pattern) { print "Match!\n"; } ``` ## Testing ### Basic Testing ```perl use strict; use warnings; sub add { my ($a, $b) = @_; return $a + $b; } # Test my $result = add(2, 3); die "Failed" unless $result == 5; ``` ### Test::More ```perl use strict; use warnings; use Test::More; sub add { my ($a, $b) = @_; return $a + $b; } is(add(2, 3), 5, "add(2,3) returns 5"); is(add(0, 0), 0, "add(0,0) returns 0"); done_testing(); ``` ## Documentation ### POD Documentation ```perl use strict; use warnings; =head1 NAME My::Module - Brief description =head1 SYNOPSIS use My::Module; my $obj = My::Module->new(); =head1 DESCRIPTION Long description... =cut ``` ## Debugging ### print Debugging ```perl use strict; use warnings; use Data::Dumper; my @data = (1, 2, 3); print Dumper(\@data); warn "Debug: $variable"; ``` ### Smart::Comments ```perl use strict; use warnings; use Smart::Comments; my $result = process(); ### Debug: $result ### Expected: 42 ``` ### Devel::NYTProf ```bash # Performance profiling perl -d:NYTProf script.pl nytprofhtml ``` ## Security ### Taint Checking ```perl #!/usr/bin/perl -T use strict; use warnings; # $ARGV[0] is tainted my $input = $ARGV[0]; # Must untaint if ($input =~ /^(\w+)$/) { my $safe = $1; # Now safe } ``` ### Input Validation ```perl use strict; use warnings; # Validate email sub is_valid_email { my ($email) = @_; return $email =~ /^[^\s@]+@[^\s@]+\.[^\s@]+$/; } # Validate number sub is_valid_number { my ($num) = @_; return defined $num && $num =~ /^\d+$/; } ``` ## Performance ### Avoid Global Variables ```perl use strict; use warnings; # Bad - global our $Global_Counter = 0; # Good - lexical my $counter = 0; ``` ### Efficient Data Structures ```perl use strict; use warnings; # Use hashes for lookups my %lookup = map { $_->{id} => $_ } @objects; ``` ### Memoization ```perl use strict; use warnings; use Memoize; sub expensive { my ($n) = @_; # ... } memoize('expensive'); ``` ## Modern Perl ### Use Modern Features ```perl use strict; use warnings; use 5.014; # Given/when given ($value) { when (/^\d+$/) { say "Number" } default { say "Other" } } # State variables sub counter { state $count = 0; return ++$count; } ``` ### CPAN Modules ```perl # Modern alternatives use Path::Tiny qw(path); # Instead of File::Spec use JSON qw(to_json from_json); # Instead of JSON::PP use Try::Tiny; # Instead of eval/die ``` ## Summary - Always use `strict` and `warnings` - Declare variables with `my` or `our` - Use meaningful variable names - Handle errors appropriately (die, eval, autodie) - Use lexical filehandles - Compile regexes when used multiple times - Write tests with Test::More - Document code with POD - Validate all input - Use modern Perl features when beneficial - Use CPAN modules for common tasks

Comments

Comments powered by Giscus

To enable comments, add your Giscus embed code here.

Learn more about Giscus →