---- presentation_topic: Perl Best Practices presentation_title: Perl Best Practices presentation_place: James Squire Pub, Sydney presentation_date: September 21, 2005 ---- = Perl Best Practices Why read it? * It will make you a better *programmer* * It will make you a better *Perl* programmer * You and your team will write better code * More Robust * More Efficient * More Maintainable ---- There are 256 guidelines. Coincidence? Here is the most important one: = Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live And that violent psychopath is most likely you, six months from now. ---- = But why is Damian qualified to write this book? ---- = use Acme::Bleach; package Acme::Bleach; $VERSION = '1.12'; my $tie = " \t"x8; sub whiten { local $_ = unpack "b*", pop; tr/01/ \t/; s/(.{9})/$1\n/g; $tie.$_ } sub brighten { local $_ = pop; s/^$tie|[^ \t]//g; tr/ \t/01/; pack "b*", $_ } sub dirty { $_[0] =~ /\S/ } sub dress { $_[0] =~ /^$tie/ } open 0 or print "Can't rebleach '$0'\n" and exit; (my $shirt = join "", <0>) =~ s/.*^\s*use\s+Acme::Bleach\s*;\n//sm; local $SIG{__WARN__} = \&dirty; do {eval brighten $shirt; exit} unless dirty $shirt && not dress $shirt; open 0, ">$0" or print "Cannot bleach '$0'\n" and exit; print {0} "use Acme::Bleach;\n", whiten $shirt and exit; ---- = The Horror that is SelfGOL ... can print its own source code (self-replicate), rewrite other Perl programs so they can print their own source code (and still perform their original functions), detect un-rewritable Perl programs, play John Conway's Game of Life using its own source code or a specified file as a pattern for the board with a board of arbitrary size, or animate a rotating banner of an arbitrary short amount of text. All this in under 1000 bytes of Perl without using a single if, unless, while, until, for, foreach, goto, next, last, redo, map, or grep. Everything you never wanted to know about Perl, and would have been afraid to ask. #!/usr/bin/perl -s $;=$/;seek+DATA,!++$/,!$s;$_=;$s&&print||$g&&do{$y=($x||=20)*($y||8);sub i{sleep&f}sub'p{print$;x$=,join$;,$b=~/.{$x}/g}$j=$j;sub'f{pop}sub n{substr($b,&f%$y,3)=~tr,O,O,}sub'g{$f=&f-1;($w,$w,substr($b,&f,1),O)[n($f-$x)+ n($x+$f)-(substr($b,&f,1)eq+O)+n$f]||$w}$w="\40";$b=join'',@ARGV?<>:$_,$w x$y;$b=~s).)$&=~/\w/?O:$w)ge;substr($b,$y)=q++;$g='$i=0;$i?$b:$c=$b; substr+$c,$i,1,g$i;$g=~s?\d+?($&+1)%$y?e;$i-$y+1?eval$g:do{$i=-1;$b=$c;p;i 1}';sub'e{eval$g;&e}e}||eval||die+No.$; __DATA__ if($j){{$^W=$|;*_=sub{$=+s=#([A-z])(.*)#=#$+$1#=g}} @s=(q[$_=sprintf+pop@s,@s],q[ if($j){{$^W=$|;*_=sub{$=+s=#([A-z])(.*)#=#$+$1#=g}} #_The_Perl_Journal_# @s=(q[%s],q[%s])x2;%s;print"\n"x&_,$_;i$j;eval} ])x2;$_=sprintf+pop@s,@s;print"\n"x&_,$_;i$j;eval}$/=$y;$"=",";print q<#!/usr/local/bin/perl -sw if(!$s){>.($_=<>).q<}else{@s=(q[printf+pop@s,@s],q[#!/usr/local/bin/perl -sw if(!$s){>.(s$%$%%$g,tr=[=[===tr=]=]=||&d,$_).q<}else{@s=(q[%s],q[%s])x2;%s} ])x2;printf+pop@s,@s} ---- = use Lingua::Romana::Perligata; use Lingua::Romana::Perligata; adnota Illud Cribrum Eratothenis maximum tum val inquementum tum biguttam tum stadium egresso scribe. vestibulo perlegementum da meo maximo . maximum tum novumversum egresso scribe. da II tum maximum conscribementa meis listis. dum damentum nexto listis decapitamentum fac sic lista sic hoc tum nextum recidementum cis vannementa da listis. next tum biguttam tum stadium tum nextum tum novumversum scribe egresso. cis ---- = OK, OK, Some Serious Production Code From the Perl6::Rules Changes file: 0.02 Mon Apr 12 13:23:18 2004 - Updated requirement to 5.8.3 - Removed stupid 'use strict' ;-) ---- = Here's the real reason why ---- {image: images/damian.jpg} ---- * Author of over 50 CPAN modules * Lead designer of Perl 6 * Computer Science Professor * Author of classic book "Object Oriented Perl" * Brilliant Speaker and Writer * Damian has the *authority* to settle arguments ---- = History About 60% of the book material was originally given as a two day course (see PJF advertisement ;-). People who did the course asked: "Why not make it into a book?". Others argued that such an *authorative* book would make it much easier for them to enforce Perl coding standards on their team. BTW, his next book will probably be the subject of PJF's presentation: "How to give great presentations". ---- = Top 10 Development Practices * Design the Module's Interface First * Write the Test Cases Before the Code * Create Standard POD Templates for Modules and Applications * Use a Revision Control System (not SourceSafe ;-) * Create Consistent Command-Line Interfaces * Agree Upon a Coherent Layout Style and Automate It with /perltidy/ * Code in Commented Paragraphs * Throw Exceptions Instead of Returning Special Values or Setting Flags * Add New Test Cases Before you Start Debugging * Don't Optimize Code -- Benchmark It ---- = Top 10 Coding Practices See the book. ---- = Top 10 Module Practices See the book. ---- = Examples ---- = Passing arguments to subroutines Use named arguments for any subroutine that is ever likely to have more than three parameters. Named arguments replace the need to remember an ordering (which humans are poor at) with the need to remember a name (which humans are good at). Don't use: padded( text => $line, centred => 1 ) use: padded({ text => $line, centred => 1 }) Why? ---- = Use block if, not postfix if $sum += $measurement if defined $measurement is ok, but does not scale when you need to change the code. Compare: $sum += $measurement and $count++ and next SAMPLE if defined $measurement; to: if (defined $measurement) { $sum += $measurement; $count++; next SAMPLE; } The second form *scales* better, a common theme throughout the book. ---- = Smart::Comments Damian recommends many modules in the book (detailed in the Appendix). Here's one that I like: use Smart::Comments; my $results = $scenario->project_outcomes(); ### $results Comment-based assertions are also supported: ### check: @candidates >= @elected To switch off in production, simply: # use Smart::Comments; ---- = What's wrong with this code? my $source_file = 'fred.tmp'; my $destination_file = $source_file; # Open both filehandles... use Fatal qw( open ); open my $src, '<', $source_file; unlink $destination_file; open my $dest, '>', $destination_file; # Read, process, and output data, line-by-line... while (my $line = <$src>) { print {$dest} transform($line); } sub transform { return "hello:" . $_[0]; } ---- = Don't be clever [ $a => $b ] -> [ $b <= $a ] ---- = Don't be clever $a <= $b ? $a : $b use List::Util qw(min); min($a, $b) ---- = Object Oriented Perl Traditional Perl O-O has some problems: * Poor encapsulation * Misspelled attributes are trouble at runtime Inside-out objects: * One lexical hash per attribute indexed by object * See Class::Std and Class::Std::Utils * Excellent encapsulation * Misspelled attributes now caught at compile time * DESTROY is now very important ---- * http://www.perl.com/pub/a/2005/07/14/bestpractices.html * http://www.perlcast.com/audio/Perlcast_Interview_003_Damian_Conway.mp3 * http://perlcast.com/audio/Perlcast_Presentation_001_Conway_Channel_OSCON_2005.mp3 * http://www.linuxjournal.com/article/8567 * http://perltraining.com.au/courses/bestpractice.html * http://www.perlmonks.org/index.pl?node_id=477093 (Book Review) * http://www.perlmonks.org/?node_id=488824 (Best Practice or Dodgy Practice?) * http://books.slashdot.org/books/05/09/14/1451238.shtml?tid=145&tid=6 (Usual cheer-leading. Who is Tony Williams?) ---- = CPAN Modules * See recommended module list in PBP * Module::Starter::PBP * ExtUtils::ModuleMaker::PBP * Perl::Critic * Perl::BestPractice ---- Buy the book and thankyou for listening!