An introduction to writing readable Perl code, for people who write Perl that other people may want to read. Covers the most important lessons from Perl Best Practices, and ends by showing how to use Perl::Critic to test that you are meeting the standards set out.
Given at FOSDEM 2011
Introduction to writing readable and maintainable Perl
1. Introduction to writing readable
and maintainable Perl
Or
Perl Best Practices: The Best Bits
Or
Perl is more readable than Java!
Or
Your code is bad and you should feel bad
2. Who Am I?
Alex Balhatchet Working for a small company
Super Nerd since 1985 ~5 years of code
Perl Hacker since 2002 582 modules
Londoner since 2004 Lots of legacy code
Paid Perl Hacker since All Perl
2006
3. Who are you guys?
Perl Oldies?
Perl Newbies?
Curious non-Perl types?
4. I'm here to convince you that Perl can be readable!
my @files = @ARGV;
foreach my $file (@files) {
open(my $fh, '<', $file);
while (my $line = readline($fh)) {
print $line;
}
close($fh);
}
5. Summary
Pragmas
CPAN
Best Perl Best Practices
Legacy Code
Perl::Critic & Perl::Tidy
Questions
7. Always use strict
use strict makes your code safer
requires that all variables are declared with "my", "our", etc.
- stops you from making typos in variable names
stops you from using symbolic (string) references
- stops you from writing terrible terrible code
does not allow non-subroutine barewords
- stops you making typos in subroutine calls
8. ...and use warnings
use warnings ensures that odd things do not silently try to "do
what you mean."
print(undef) - uninitialized value in print()
1 + "bananas" - non-numeric value in addition
%hash = (1, 2, 3); - odd number of elements in hash
9. Other Useful Pragmas
# make open() and others die on error
use autodie;
# enable say(), given(), state, etc.
use feature ':5.10'; # enable all of them
use feature 'say'; # enable one at a time
# make warnings throw exceptions
use warnings FATAL => 'all';
11. The CPAN
The CPAN is by far the best thing about Perl.
http://search.cpan.org
90,000 modules!
Using CPAN modules means your code gets maintained, bug-
fixed and optimized for you!
12. Picking CPAN Modules
With 90,000 modules it can be difficult to pick the right one...
Which is the right one for the job?
13. Picking CPAN Modules
Use the CPAN Testers reports, rt bug tracker, and Reviews.
Every Distribution will have these!
http://search.cpan.org/dist/Data-Dumper/
CPAN Testers: PASS (561) FAIL (8) UNKNOWN (4)
Rating: (9 Reviews)
14. Picking CPAN Modules
The Task::Kensho CPAN module is a documentation-and-
dependencies-only distribution which can be used as a
recommended modules list.
Some highlights are...
App::cpanminus, Test::Most, Try::Tiny,
Devel::NYTProf, Perl::Critic, DateTime,
Config::General, and App::Ack
It's a great starting point!
16. Code in paragraphs
Code which is written in paragraphs is much more readable.
# get ready...
read_commandline_arguments();
init();
# actual work here...
do_stuff();
# output...
format_output();
output_stuff();
17. Throw Exceptions
Modern programming wisdom gives us many reasons
Exceptions win out over error codes.
Impossible to ignore
Functions don't have to try to return two values
Separate exceptional from non-exceptional cases
18. Throw Exceptions
Perl implements Exceptions with strings and die().
die "Exception!";
You can use eval() to catch them, but the Try::Tiny module
gives us Java-style try/catch keywords which are much nicer.
try {
stuff();
}
catch {
# exception is in a lexically scoped $_ variable
}
19. Use builtins
Builtins in Perl are sensible and readable, especially when your
editor has decent syntax highlighting.
Perl is excellent at string manipulation and dealing with lists.
Use it to its full potential.
Perl's builtins have well defined names and behaviours, learn to
love them.
20. Use builtins
while (my $line = readline while (my $line = <$fh>) {
($fh)) { # ...
# ... }
}
warn "warning! something's print STDERR "is this a warning? who
weird"; knows?!";
21. Use builtins
if (defined $value){ if ($value){
# stuff... # stuff...
} }
my @files = glob("*. my @files = <*.txt>;
txt");
22. Use honorary builtins
There are a number of "honorary builtins" which are exported
by core modules.
use Scalar::Util qw(looks_like_number openhandle);
use List::Util qw(first max min shuffle sum);
use List::MoreUtils qw(any all none uniq apply);
23. Avoid overly confusing idioms and cleverness
Perl lets you write code however you want.
TIMTOWTDI - There is more than one way to do it.
A big part of writing readable Perl is about admitting
that some of the ways to do it suck!
24. Avoid overly confusing idioms and cleverness
What does this do?
my $result =
[ $result1 => $result2 ]
->[ $result2 <= $result1 ];
25. Avoid overly confusing idioms and cleverness
Maybe it's more obvious like this...
use List::Util qw(min);
my $result = min($result1, $result2);
27. Be consistent with existing code
This is an important rule, because it often contradicts all the
others I've mentioned:
When dealing with an existing code base, be consistent.
29. Be consistent with existing code
If you change the existing code...
Make sure there are tests
Make sure there are good tests
Change the whole file so that consistency is maintained
Commit your changes to your VCS as a whole, without any
other changes!
30. Perl::Critic
Perl::Critic, and its binary friend perlcritic, is a tool which will tell
you what is wrong with your Perl code.
% perlcritic my_script.pl
32. Perl::Critic
% perlcritic --verbose 11 bad_perl.pl
Bareword file handle opened at line 3, near 'open(IN, $0);'.
InputOutput::ProhibitBarewordFileHandles (Severity: 5)
Using bareword symbols to refer to file handles is particularly
evil because they are global, and you have no idea if that symbol
already points to some other file handle. You can mitigate some of that risk
by......
Contains the full Perl Best Practices text!!
33. Perl::Tidy
Perl::Tidy, and perltidy, is a tool for automatically tidying up Perl code
to make it more readable.
It can...
convert tabs into spaces
restrict lines to 80 characters
automatically line up "=>" characters in hashes and ","'s in lists
add semi-colons where they belong
un-cuddle elses
The perltidyrc file listed in Perl Best Practices can be found here:
http://www.perlmonks.org/?node_id=485885
36. Contact Me
http://kaoru.slackwise.net/
@kaokun on Twitter
My Code
http://search.cpan.org/~kaoru/
https://github.com/kaoru/
Slides
http://www.slideshare.net/kaokun