Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

38
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

description

An updated version of the talk I gave at FOSDEM earlier in 2011.This one has a much better "How to approach this in the real world" section.

Transcript of Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Page 1: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

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

Page 2: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Who Am I?

Working at

• 5+ years of code

• 727 modules

• 1107 test files

• Lots of legacy code

• All Perl

Alex Balhatchet

• Super Nerd since 1985

• Perl Hacker since 2002

• Londoner since 2004

• Paid Perl Hacker since 2006

Page 3: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

What's this all about?

• Pragmas

• CPAN

• Best Perl Best Practices

• The Real World

• Questions

Page 4: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Pragmas

Page 5: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Always use strictuse 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

Page 6: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

...and use warningsuse 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

Page 7: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Other Useful Pragmasmake open() and others die on error

use autodie;

use new Perl features

use feature ':5.14'; # enable all of themuse feature 'say';   # enable one at a time

make warnings throw exceptions

use warnings FATAL => 'all';

Page 8: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

CPAN

Page 9: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

The CPANThe CPAN is by far the best thing about Perl.

http://search.cpan.org

98,000 modules! Using CPAN modules means your code gets maintained, bug-fixed and optimized for you!

Page 10: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Picking CPAN ModulesWith 98,000 modules it can be difficult to pick the right one...

Which is the right one for the job?

Page 11: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Picking CPAN ModulesUse the CPAN Testers reports, rt bug tracker, and Reviews. Every Distribution will have these!http://search.cpan.org/dist/Data-Dumper/

Page 12: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Picking CPAN ModulesThe 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!

Page 13: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

The BestPerl Best Practices

Page 14: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Perl Best PracticesPerl Best Practices is an amazing book that was published in 2005

PBP contains some great tips forwriting readable and maintainable Perl code... and some silly ideas like inside-out objects ;-)

But seriously, read it. It will make youa better programmer.

Page 15: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Code in paragraphsCode 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();

Page 16: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Throw ExceptionsThere are 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

Page 17: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Throw ExceptionsPerl 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}; 

Page 18: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Use builtinsBuiltins 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.

Page 19: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Use builtinswhile (my $line = readline $fh) {    # ...}

Is more readable than...

while (my $line = <$fh>) {

    # ...

}

Especially for people less familiar with Perl!

Page 20: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Use builtinsmy @log_files = glob "*.log";

Is more readable (and less prone to error) than...

my @log_files = <*.log>;

(Especially when your syntax highlighter thinks that log is the log() function and highlights it yellow :-))

Page 21: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Use builtinsif (defined $value){    # stuff...}

Is less prone to error than...

if ($value){    # stuff...}

Page 22: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Use builtinswarn "Something went wrong!";

Is way better than...

print STDERR "Something went wrong!";

See perldoc ­f warn for all the awesome details :-)

Page 23: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Use honorary builtinsThere 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);

Page 24: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

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!

Page 25: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Avoid overly confusing idioms and cleverness

What does this do?

my $result =     [ $result1 => $result2 ]  ­>[ $result2 <= $result1 ];

Page 26: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Avoid overly confusing idioms and cleverness

Maybe it's more obvious like this... use List::Util qw(min); my $result = min($result1, $result2);

Page 27: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

The Real World

Page 28: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Why do we want maintainable code?To be able to maintain it of course!

Especially important

• When working on a long-lived project

• When working on a team

• When team members are added frequently

Page 29: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Coding Style Guidelines

• Set out rules for all new development

• Match existing code as closely as is sensible

• Embrace the Best Practices and the Modern

• Give you something concrete to point to when somebody writes something you don't agree with

• Give you something to work from for code reviews

Page 30: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

The Golden RulesWe have an Asimovian set of rules at the top of our Coding Style Guide document...

Rule One: Follow the style of the surrounding code

Rule Two: Follow the rules of the Coding Style Guide

Rule Three: Follow Perl Best Practices

Page 31: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Refactoring for StyleBasically follows the same rules as regular refactoring...

• 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!

Page 32: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Perl::Critic

Perl::Critic, and its executable friend perlcritic, is a tool which will tell you what is wrong with your Perl code. % perlcritic my_script.pl

Page 33: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Perl::Critic#!/usr/bin/perl

use feature 'say';

open(IN, $0);while (<IN>) {    chomp;    for (split //, $_) {        $letters{$_}++;    }}

foreach (sort keys %letters) {    say "$_\t$letters{$_}";}

close(IN);

How many style problems can you spot?

Page 34: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

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!!

Page 35: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Perl::CriticHow we use Perl::Critic at Nestoria...

● Nightly test run critiques code

● Writes output to a separate log file

● If any failures occur, a single file is chosen to be the one to fix for the day. The current “Engineer of the Week” fixes it

● Within 3 months we had zero Perl::Critic violations!

● New violations are solved almost immediately!

Page 36: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Questions etc.

Page 37: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

Questions?

Page 38: Introduction to Writing Readable and Maintainable Perl (YAPC::EU 2011 Version)

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