Cleancode

Preview:

DESCRIPTION

Slides for talk on Clean Code given at the 2007 Belgian Perl Workshop. Reference: Damian Conways Perl Best Practices

Citation preview

Clean CodeClean Code

Hendrik Van Belleghem

Belgian Perl Workshop 2007

Hendrik Van Belleghem

Belgian Perl Workshop 2007

It’s all Bruces fault!

Obviously? PragmasObviously? Pragmas

warnings strict

subs : no barewords! refs : no symbolic references! vars : no undeclared variables!

warnings strict

subs : no barewords! refs : no symbolic references! vars : no undeclared variables!

Obviously? Variable namesObviously? Variable names

Variable names should be Short

but not too short $i, $a, $o

Unambiguous $i, $data, $line

Variable names should be Short

but not too short $i, $a, $o

Unambiguous $i, $data, $line

Obviously? Variable namesObviously? Variable names

Variable names should definitely not be generated by Acme::MetaSyntactic:

$thwacke # batman $flrbbbbb # batman $bondelschwaartz #pynchon $ununquadium # elements

Variable names should definitely not be generated by Acme::MetaSyntactic:

$thwacke # batman $flrbbbbb # batman $bondelschwaartz #pynchon $ununquadium # elements

Acme::Metasyntactic?Acme::Metasyntactic?

It’s all BooK’s fault!

Obviously? Variable namesObviously? Variable names

Scalars are single $item

Hashes and arrays are plural @items

Mark booleans with test $found_match

Add reference prefix/suffix $item_ref

Scalars are single $item

Hashes and arrays are plural @items

Mark booleans with test $found_match

Add reference prefix/suffix $item_ref

Braces.. bad?Braces.. bad?

Array definitionmy @list =

( ‘larry’,

‘damian’ );

Any other block?for my $coder ( @list )

{ print “hi $coder\n”; }

Array definitionmy @list =

( ‘larry’,

‘damian’ );

Any other block?for my $coder ( @list )

{ print “hi $coder\n”; }

Braces..good?Braces..good?

Array definitionmy @list = (

‘larry’,

‘damian’

);

Any other block?for my $coder ( @list ) {

print “hi $coder\n”;

}

Array definitionmy @list = (

‘larry’,

‘damian’

);

Any other block?for my $coder ( @list ) {

print “hi $coder\n”;

}

Stay away from $_Stay away from $_

$_ as default argument?-X, abs, alarm, chomp, chop, chr, chroot, cos, defined, eval, exp, glob, hex, int, lc, lcfirst, length, log, lstat, oct , ord, pos, print, quotemeta, readlink, ref, require, reverse, rmdir, sin, split, sqrt, stat, study, uc, ucfirst, unlink

Implicit use m//, s///, y/// for(), map {}, grep {}, while(<>)

$_ as default argument?-X, abs, alarm, chomp, chop, chr, chroot, cos, defined, eval, exp, glob, hex, int, lc, lcfirst, length, log, lstat, oct , ord, pos, print, quotemeta, readlink, ref, require, reverse, rmdir, sin, split, sqrt, stat, study, uc, ucfirst, unlink

Implicit use m//, s///, y/// for(), map {}, grep {}, while(<>)

default input and pattern matching space

Postfix ifPostfix if

buy("secret lair") and

buy("sharks with lasers")

and $mini_me = clone()

if $goal eq "world domination";

if ($goal eq “world domination”)

{ buy(“secret lair”);

buy(“sharks with lasers”);

$mini_me = clone();

}

buy("secret lair") and

buy("sharks with lasers")

and $mini_me = clone()

if $goal eq "world domination";

if ($goal eq “world domination”)

{ buy(“secret lair”);

buy(“sharks with lasers”);

$mini_me = clone();

}

C style loopsC style loops

for (my $slide = 1; $slide < 25 ; $slide++)

{ present($slide); }

for my $slide (1..25)

{ present($slide); }

Cleaner Easier to read

for (my $slide = 1; $slide < 25 ; $slide++)

{ present($slide); }

for my $slide (1..25)

{ present($slide); }

Cleaner Easier to read

PODPOD

Put POD in the source file.. At the end

Check your POD! Podchecker

Use POD templates & stubs NAME, VERSION, SYNOPSIS,..

Put POD in the source file.. At the end

Check your POD! Podchecker

Use POD templates & stubs NAME, VERSION, SYNOPSIS,..

String eval is badString eval is bad

Don’t overuse eval.. Period String eval is recompiled on execution

Use block instead

Are you taint-checking??

Don’t overuse eval.. Period String eval is recompiled on execution

Use block instead

Are you taint-checking??

FilehandlesFilehandles

Bareword filehandles Cannot be localized Passing it to a sub?

Try typeglobs

Better: indirect filehandles From 5.6 onwards

open my $filehandle, ”<filename” or die $!;

Bareword filehandles Cannot be localized Passing it to a sub?

Try typeglobs

Better: indirect filehandles From 5.6 onwards

open my $filehandle, ”<filename” or die $!;

Regexp::CommonRegexp::Common

IP addresses?$ip =~ /$RE{net}{IPv4}/

MAC addresses?$ip =~ /$RE{net}{MAC}/

Credit cards$number =~ /$RE{zip}{VISA}/

IP addresses?$ip =~ /$RE{net}{IPv4}/

MAC addresses?$ip =~ /$RE{net}{MAC}/

Credit cards$number =~ /$RE{zip}{VISA}/

For all your extraordinary regexp needs

Regexp::Common?Regexp::Common?For all your extraordinary regexp needs

It’s all Abigails fault! Dutch Tall Strapping hunk of

manhood

It’s all Abigails fault! Dutch Tall Strapping hunk of

manhood

Regexp DelimitersRegexp Delimiters

Question..

What does this do?

harry s truman was the 33rd u.s. president;

harry s |ruman was |he 33rd u.s. presiden|;

harry($string =~ s{ruman was }{he 33rd u.s. presiden}xms);

Question..

What does this do?

harry s truman was the 33rd u.s. president;

harry s |ruman was |he 33rd u.s. presiden|;

harry($string =~ s{ruman was }{he 33rd u.s. presiden}xms);

RegexpRegexp

Keep it simple! $foo =~ s{foo}{bar}g; $html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsx

Add comments to big Regexp chunks

Use \A and \Z instead of $ and ^

Keep it simple! $foo =~ s{foo}{bar}g; $html =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gsx

Add comments to big Regexp chunks

Use \A and \Z instead of $ and ^

s{ < # opening angle bracket (?: # Non-backreffing grouping paren [^>'"] * # 0 or more things that are neither > nor ' nor " | # or else ".*?" # a section between double quotes (stingy match) | # or else '.*?' # a section between single quotes (stingy match) ) + # all occurring one or more times > # closing angle bracket }{}gsx; # replace with nothing, i.e. delete

AutoloadAutoload

Inheritence precedence? Inheritence precedence?

Catch all method

RefactoringRefactoring

Original code Duplicated code

Move to subroutines

Duplicated subroutines Move to packages

Original code Duplicated code

Move to subroutines

Duplicated subroutines Move to packages

No overkill!

TestsTests

Write tests first Test::Simple & Test::More Test for failures Test the obvious & not so obvious Find a bug? Write a test!

Write tests first Test::Simple & Test::More Test for failures Test the obvious & not so obvious Find a bug? Write a test!

Version controlVersion control

Multiple developers Undo Generate patches Merging/branching

CVS, Subversion, RCS, Perforce, BitKeeper, git

Multiple developers Undo Generate patches Merging/branching

CVS, Subversion, RCS, Perforce, BitKeeper, git

FormatFormat

Compile time definition No runtime changes

Except with eval

Global variables only Output to named filehandle

Compile time definition No runtime changes

Except with eval

Global variables only Output to named filehandle

TieTie

Unknown magic Unpredictable behavior Eg: Tie::Scalar::RestrictUpdates limits changes

Slow Change variable behavior through code

Unknown magic Unpredictable behavior Eg: Tie::Scalar::RestrictUpdates limits changes

Slow Change variable behavior through code

Perl::CriticPerl::Critic

As Module As command line tool As website : http://perlcritic.com

DIY Configurable

As Module As command line tool As website : http://perlcritic.com

DIY Configurable

Perl::CriticPerl::Critic

As Module

use Perl::Critic;my $file = shift;my $critic = Perl::Critic->new();my @violations = $critic->critique($file);print @violations;

As Module

use Perl::Critic;my $file = shift;my $critic = Perl::Critic->new();my @violations = $critic->critique($file);print @violations;

Perl::CriticPerl::Critic

As command line tool As command line tool

lenore:~$ perlcritic -stern strict.pm Code before strictures are enabled at line 3, column 1. See page 429 of PBP. (Severity: 5)Code before warnings are enabled at line 3, column 1. See page 431 of PBP. (Severity: 4)Always unpack @_ first at line 11, column 1. See page 178 of PBP. (Severity: 4)Subroutine does not end with "return" at line 11, column 1. See page 197 of PBP. (Severity: 4)Always unpack @_ first at line 27, column 1. See page 178 of PBP. (Severity: 4)Subroutine does not end with "return" at line 27, column 1. See page 197 of PBP. (Severity: 4)Always unpack @_ first at line 32, column 1. See page 178 of PBP. (Severity: 4)Subroutine does not end with "return" at line 32, column 1. See page 197 of PBP. (Severity: 4)

Perl::CriticPerl::Critic As website : http://perlcritic.com As website : http://perlcritic.com

Perl::CriticPerl::Critic As Module As command line tool As website : http://perlcritic.com

DIY Lots of policies

Configurable

As Module As command line tool As website : http://perlcritic.com

DIY Lots of policies

Configurable

Thank you!Thank you!

どうもありがとうミスターロボット

(domo arigato, Mr Roboto)

どうもありがとうミスターロボット

(domo arigato, Mr Roboto)