Beefy Boxes and Bandwidth Generously Provided by pair Networks Bob
We don't bite newbies here... much
 
PerlMonks  

Style, *again*

by Juerd (Abbot)
on Apr 08, 2003 at 19:14 UTC ( #249041=perlmeditation: print w/ replies, xml ) Need Help??

A while ago, I promised some people here and elsewhere that I would try to describe my Perl coding style in 100 rules.

They're in no logical order, and I probably forgot a lot of style aspects. The list is at http://juerd.nl/site.plp/perlstyle, but since it's relevant here, I'll paste the entire list.

Should you care, I prefer vim. Let the holy wars commence! :) - again :)

  • 4 space indents
  • No tabs in code (includes indents)
  • Always Class->method, never method Class (this includes "new"!)
  • Cuddled else: } else {
  • Opening curly on the same line as the keyword it belongs to
  • Closing vertically aligned with that keyword
  • Space after comma or semi-colon, but not before
  • No extra spaces around or inside parens: foo, (bar, baz), quux
  • Extra spaces in arrayref constructor: [ foo, bar ]
  • Extra spaces in hashref constructor: { foo => bar }
  • No parens unless needed for clarity
  • Space between keyword and its arguments
  • No space between keyword and its arguments if the "looks like a function, therefor it is a function" rule applies: print((split)[22]), not print ((split)[22]). (And of course not print (split)[22])
  • No subroutine prototypes if they're ignored anyway
  • No subroutine prototypes just to hint the number of arguments
  • Prototypes enforce context, so use them only if that make sense
  • No globals when access from another package is not needed
  • use strict and -w
  • Lots of modules, but not to replace few-liners or simple regexes
  • No double spaces except for vertical alignment
  • Only &&/||/! where parens would be needed with and/or/not
  • No double empty lines
  • Empty line between logical code chunks
  • Explicit returns from subs
  • Guards ("return if ...") are nicer than large else-blocks
  • No space between array/hash and index/key: $foo[0], $foo{bar}
  • No quotes for simple literal hash keys
  • Space around index/key if it is complex: $foo{ $bar{baz}{bar} }
  • Long lines: indent according to parens, but always 4 spaces (or [], {}, etc)
  • Long lines: continuing lines are indented
  • Long lines: Lines end with operator, unless it's ||/&&/and/or
  • No "outdent"s
  • No half indents
  • No double indents
  • grep and map EXPR when BLOCK is not needed
  • Logical order in comparisons: $foo == 4, but never 4 == $foo
  • English identifiers
  • Not the English.pm module
  • Multi-word identifiers have no separation, or are separated by underscores
  • Lowercase identifiers, but uppercase for constants
  • Whatever tool is useful: no OO when it does not make sense
  • It's okay to import symbols
  • No here-documents, but multi-line q/qq. Even repeated prints are better :)
  • Always check return values where they are important
  • No spaces around: -> **
  • Spaces around: =~ !~ * / % + - . << >> comparison_ops & | ^ && || ?: assignment_ops => and or xor
  • Spaces or no spaces, depending on complexity: .. ... x
  • No space after, unless complex: ~ u+ u-
  • Long lines: break between method calls, -> comes first on a line, space after it
  • => where it makes sense
  • qw where useful
  • qw when importing, but '' when specifying pragma behaviour
  • () for empty list, not qw()
  • -> to dereference, where possible
  • No abbreviations (acronyms are okay, and so are VERY common abbreviations) NEVER "ary"
  • Data type not represented in variable name: "%foo" and "@foo", but not "%foo_hash" or "@foo_array"
  • Sometimes: data type of referent in reference variable names: "$bla_hash" is okay
  • Sometimes: data type 'reference' in raference variable names: "$hashref" is okay
  • No one-letter variable names, unless $i or alike
  • $i is a(n index) counter
  • Dummy variables can be called foo, bar, baz, quux or just dummy
  • Taint mode *only* for setuid programs
  • No sub main(), unless it needs to be called more often than once
  • Subs before main code!
  • Declare variables on first use, not before (unless required)
  • \cM > \x0d > \015. \r only where it makes sense as carriage return.
  • Complex regexes get /x
  • No space between ++/-- and the variable
  • List assignment for parameters/arguments, not lots of shifts
  • Only shift $self from @_ if @_ is used elsewhere in the sub
  • Direct @_ access is okay in very short subs
  • No eval STRING if not needed
  • Constructor "new" does not clone. Only handles a *class* as $_[0]
  • Constructor that clones is called "clone"
  • Constructor can be something else than "new", but "new" is an alias
  • No setting of $| when it is not needed
  • Lexical filehandles
  • No v-strings
  • Single quotes when double-quote features not used
  • In DBI: value interpolation using placeholders only
  • use base 'BaseClass' instead of use BaseClass and setting @ISA
  • Comments where code is unclear
  • Comments usually explain the WHY, not the HOW
  • POD at the bottom, not top, not interleaved
  • Sane variable scopes
  • No local, except for perlvar vars
  • No C-style loop for skipless iteration
  • No looping over indexes if only the element is used
  • 80 characters width. It's okay to give up some whitespace
  • Unbalanced custom delimiters are not metacharacters and not alphanumeric
  • RHS of complex s///e is delimited by {}
  • Favourite custom delimiter is []
  • Semi-colon only left out for implicit return or in single-statement block
  • No $&, $` or $'
  • Localization of globals if they're to be changed (local $_ often avoids weird bugs)
  • Semi-colon not on its own line
  • (in|de)crement in void context is post(in|de)crement
  • No map or grep not in void context
  • ? and : begin lines in complex expressions
  • True and false are always implied. No $foo == 0 when testing for truth.

Juerd
- http://juerd.nl/
- spamcollector_perlmonks@juerd.nl (do not use).

Comment on Style, *again*
Re: Style, *again*
by dws (Chancellor) on Apr 08, 2003 at 19:27 UTC
      Taint mode *only* for setuid programs

    Alas, many exploits start with a wiley h4x0r getting their foot in the door.

      Logical order in comparisons: $foo == 4, but never 4 == $foo

    The latter form is occassionaly useful to quickly signal to the reader that we're interested in array size, not array contents. I.e.,

    foo(@stuff) unless 0 == @stuff;
    It is, however, a matter of style.

      The latter form is occassionaly useful to quickly signal to the reader that we're interested in array size, not array contents

      That doesnt only apply to arrays. When comparing against literals I find using the literal on the left can make for more readable code, as it can emphasise the important part of the conditional. Just like the way it can be more readable to use $_ when doing a lot of regex work on one string. I also find an added advantage of putting the literal first in numeric context is that it avoids the problem of occasionally using "=" instead of "==", which gets caught as an attempt to assign to a read only value instead of (sometimes silently!) overwriting the variable.


      ---
      demerphq

      <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
Re: Style, *again*
by thelenm (Vicar) on Apr 08, 2003 at 19:47 UTC
    Wow, I think your coding style is about the closest to mine that I've ever seen anyone's. We do things differently on a couple of points (I uncuddle my elses, use warnings instead of -w, I interleave my POD, occasionally use here-docs, and prefer pre-increment to post-increment), but 95% agreement is not bad. And you even use Vim. Good style list... it gives some things to think about.

    Oh... and I think you probably have one too many negations in No map or grep not in void context, unless you really mean that you always use map in void context. :-)

    -- Mike

    --
    just,my${.02}

      Oh... and I think you probably have one too many negations in No map or grep not in void context, unless you really mean that you always use map in void context. :-)

      You are right. There's a negation too many :)

      Juerd
      - http://juerd.nl/
      - spamcollector_perlmonks@juerd.nl (do not use).
      

Re: Style, *again*
by gmpassos (Priest) on Apr 08, 2003 at 20:48 UTC
    Well, I wan't to share my code style too, but with less rules, since I think that simple is better, and I will explain some:

  • 2 spaces for ident.
         Because you win horizontal space, is easier, and 2 is just the sufficient to identify the difference of levels.
  • No table (\t) in the code, including index.
        Table doesn't work well in all the editors and OS!
  • Open block in the same line: if (...) {
  • Do not declare else/elsif in the same line of previous close block!:
        if (...) {
        ....
        }
        else { }
  • Blocks, with 1 group of statement, or small blocks, will be in one line:
        if (...) { $x++ ;}
  • Always put the ";", even when is the last in the block: (use like the previous code).
        Because if you put the ";" always, you can add codes after it without care to add the ; in the prevoius. If you cut the ";" and need to put new codes after it, the probability to forget to check the previous line is big, and this make bugs!
  • In foreach use for the scalar the same name of the array plus "_i":
         foreach my $array_i ( @array ) {}
        ## Note that I have an editor that make this for me! ;-P
  • Separate the code in subs, and if make sence build it in OO, or better a Perl Module.
  • Spaces between strings and ",": (a , b, c). But not between string and "("! But for variables use the space: ( %hash , a , b)
  • Spaces when the code open and close alot "(","{": join("x", length( $hash{ $hash2{k}{k2} } )) ;
  • Put ";" separated of the last code: length($foo) ;
        Because if you want to add or change the code ";" is already the position, and avoid the wrong cut of chars:
        length($foo) if $foo ;
  • Use $i,$j,$k... for index, $c for count, and $s for "tmp" string.
  • 1 for true, undef for false, not 0!
  • Use $var shift only for objects, and variables that will be used a lot, or when directly access $_[0] doesn't bring speed!
  • Always Class->method, never method Class (this includes "new"!). (I agree with this too)
  • For q or qq, use "`": $var = q`fooo` ;
        Since "`" is not much used for strings! Better than ~,/, or anoy other.
  • Always use parens: tie( %hans , 'pack' , arg ) ;
  • For returned data always use: return() ;
  • Before each sub make a comment box: (My editor make this for me, useful to mark the point and open a area for comments to:)
        #######
        # FOO # Some comment
        #######

        sub foo {
        ...
        }

  • Well, I think that for now is just this!

    Graciliano M. P.
    "The creativity is the expression of the liberty".

Re: Style, *again*
by Abigail-II (Bishop) on Apr 08, 2003 at 21:25 UTC
    It would be nice if you also indicated why you use those rules. Some of your rules are fairly obvious, but from others, I'd be interesting to hear why you picked them.

    In general, I don't find the list of rules themselves very interesting. What is interesting is knowing why someone picked the rules.

    Abigail

      In general, I don't find the list of rules themselves very interesting. What is interesting is knowing why someone picked the rules.

      Short answer: because anything else is evil and not the one true style. :)

      But here goes: (I'm lazy, so I'm formatting this as code.)

        * Always check return values where they are important

        To avoid bugs. Die before something worse happens. (that sounds funny :)

        But every experienced programmer knows (usually from personal experience) that there really can be a "Fate Worse Than Death"; I shouldn't be surprised if "FWTD" ends up as one of our common acronyms.

        * No here-documents, but multi-line q/qq. Even repeated prints are better :)
        The here-doc end marker cannot be indented, and I don't want something to be outdented in the middle of something that should be indented. Adding the indent spaces to the end marker means code stops working if it changes, which is VERY bad.

        That's actually not true about the here-doc end marker not being able to be indented. pgs. 23-26 (ch. 1.11) of the Perl Cookbook give a few examples of how to do that. Below is an example with 4 space indents in front of each of the lines.

        (my $text = <<' EOT') =~ s/^\s+//gm; This is a test of the multi-line, indented HERE document. EOT print qq($text);

        This code strips out the leading spaces in the text so that you don't have extra spaces there. It still has the drawback that if you change the spacing it will break unless you adjust the <<'    EOT' declaration as well, but at least it lines up better in the code.

        On another note, great list and thanks for sharing it.


        «Rich36»
        Thanks for the annotated list. I don't always make the same decisions, but it's interesting to see where people take an different approach, and why they do that. One question I have, you write:
        Logical order in comparisons: $foo == 4, but never 4 == $foo
        It's inside a bunch of rules for which you give "Normal linguistics/interpunction." as a reason. I don't think that applies for the quoted rule - I'd like to know why you would never write 4 == $foo.

        Abigail

Re: Style, *again*
by zentara (Archbishop) on Apr 09, 2003 at 15:28 UTC
    I'm just a lowly beginner compared to you guys, here is what I use for "style". :-) Just write whatever you want, or cut'n'paste code, then run it thru the following script. Presto! Automatic style.
    #!/usr/bin/perl #usage: $0 script use warnings; $newfile = $ARGV[0]; $outfile = $newfile . '.tmp'; open( FH, $newfile ) or die $!; open( OUT, ">> $outfile" ); while (<FH>) { # $_ =~ s/^\s+//g; #only gets leading whitespace $_ =~ s/^\s+|\s+$//g; #gets trailing also #next if $_ =~ /^\s*$/; #removes blank lines # $_ =~ s/[\t]+//g; #gets tabs and ws inside strings + #and leaves \n print OUT $_ . "\n"; } close FH; close OUT; system( "perltidy", $outfile ); rename( "$outfile.tdy", $newfile ); unlink $outfile; chmod 0755, $newfile; exit;

      Speaking of style... I took the liberty of rewriting your script.

      #!/usr/bin/perl -w use strict; my $infile = shift; my $outfile = "$newfile.tmp"; open my $infh, '<', $infile or die "Cannot open $infile: $!\n"; open my $outfh, '>>', $outfile or die "Cannot open $outfile: $!\n"; while (<$infh>) { s/^\s+//g; s/\s+$//g; print $outfh $_, "\n" or die "Cannot write to $outfile: $!\n"; } close my $outfh or die "Cannot close $outfile: $!\n"; close my $infh or die "Cannot close $infile: $!\n"; system('perltidy', $outfile) == 0 or die "Perltidy failed\n"; rename "$outfile.tdy", $infile or die "Cannot rename $outfile.tdy: $!\ +n"; unlink $outfile or die "Cannot unlink $outfile: $!\n"; chmod 0755, $infile or die "Cannot chmod $infile: $!\n";

      Changes include:

      • use strict
      • Got rid of all global variables, including file handles
      • Modern three argument open to avoid bugs
      • Sane indenting instead of an awful mess
      • Parens only where needed instead of ... I guess at random
      • Error checking on all system stuff. In the real world, many things can go wrong
      • Passing a list of $_ and \n to print instead of a concatenated string, for efficiency
      • Renaming of 'newfile'. Why 'new' anyway?
      I don't understand:
      • why you remove whitespace. perltidy does that for you.
      • why you chmod the file using a hardcoded value (use the original permissions!)
      • why there is no error message that indicates usage if @ARGV != 1
      And you should probably not just filter whitespace like that. The whitespace might be in a string literal!

      Juerd
      - http://juerd.nl/
      - spamcollector_perlmonks@juerd.nl (do not use).
      

        Thanks for "purifying" that script Juerd. :-)
Re: Style, *again*
by awkmonk (Monk) on Apr 09, 2003 at 15:32 UTC

    It's good to see you put so much thought into it. ++

    Far more important though is not any given style of coding but the conformity to that style. There's no more heinous crime than to change the way code is presented half way through a program. Grrrr --.

    What would be ideal then, would be to be able to reconfigure how the source looks when you want to work on it. Hmm something along the lines of a turbo-charged Perl::Tidy springs to min, driven by a users config file. (The include/remove unwanted constructors & POD interleaved/at end would be fun parts to write!).

    P.S 3 space indent lines up nicely with if statements :o)


    'I think the problem lies in the fact that your data doesn't fit my program'.

      In vim you can fold lines. I found it really usefull and I have not tried it - but it should not be difficult to fold POD.
      P.S 3 space indent lines up nicely with if statements :o)
      But, it doesn't align with else, for, while, until and unless.

      /prakash

Re: Style, *again*
by halley (Prior) on Apr 10, 2003 at 20:18 UTC
    My style is easier seen than described, but I'd say my general rules are as follows.
    • reads like natural language where appropriate: few abbreviations or multiple-crammed-words for names, postfix if when it reads better, method before Class when it reads better,
    • interleave pod: name, synopsis, optional abstract, {globals}, {helpers}, methods/functions {pod, code, ...}, description, see also, license/author,
    • help the smart editor within reason: curlies aligned vertically, not afraid to use vertical space, escape properly for weaker color-coders,
    • hash+dash*76 visual cut-here lines to delineate logical sections,
    • standard #TODO: #REVIEW: #HACK, #BUG: comment keywords for future planning and scanning,

    My perltidy does the token-level style: http://www.halley.cc/ed/linux/configs/

    See a reasonable example of my style on CPAN in Data::Binder or Data::Favorites.

    e d @ h a l l e y . c c
Re: Style, *again*
by g00n (Hermit) on Apr 11, 2003 at 06:17 UTC
    why ???
    • Extra spaces in arrayref constructor: [ foo, bar ]
    • Extra spaces in hashref constructor: { foo => bar }
    It just takes up space and not necessarily easier to read. why not ...
    • Extra spaces in arrayref constructor: [foo, bar]
    • Extra spaces in hashref constructor: {foo => bar}

      It just takes up space and not necessarily easier to read.

      I disagree. In my opinion, they are easier to read. Besides that, I want them to look very different since they construct new data structures, while parentheses are only for grouping.

      Juerd
      - http://juerd.nl/
      - spamcollector_perlmonks@juerd.nl (do not use).
      

        I want them to look very different since they construct new data structures, while parentheses are only for grouping

        I'll buy into that.
Re: Style, *again*
by Mr. Muskrat (Abbot) on Apr 22, 2003 at 17:15 UTC
    "Fashion is a variable, but style is a constant." -- Programming Perl 3rd Ed., page 628.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://249041]
Approved by djantzen
Front-paged by newrisedesigns
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others browsing the Monastery: (5)
As of 2014-04-20 08:28 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    April first is:







    Results (485 votes), past polls