Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl Monk, Perl Meditation
 
PerlMonks  

Re: Re: Style, *again*

by Juerd (Abbot)
on Apr 08, 2003 at 22:29 UTC ( [id://249102]=note: print w/replies, xml ) Need Help??


in reply to Re: Style, *again*
in thread Style, *again*

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.)

* 4 space indents * 80 characters width. It's okay to give up some whitespace 4 is 2**$x. 1 and 2 are too small to really see the difference (I use very small f +onts). 8 is too large (I want code to fit on 80 char terminals). * No tabs in code (includes indents) Because tabs are not always the same width. * Always Class->method, never method Class (this includes "new"!) See recent discussion, but apart from that: consistency. * Cuddled else: } else { We're still dealing with the if. In my code, } on a line by itself wil +l always mean we're done dealing with the loop/if condition. * Opening curly on the same line as the keyword it belongs to Mostly because blocks without keywords would otherwise be unclear. Consider: if ($foo) { ... } { ... } Very unclear if you put { on its own line. * Closing vertically aligned with that keyword Easy lookup. * Space after comma or semi-colon, but not before * Empty line between logical code chunks * Logical order in comparisons: $foo == 4, but never 4 == $foo * No extra spaces around or inside parens: foo, (bar, baz), quux * Space between keyword and its arguments Normal linguistics/interpunction. * Extra spaces in arrayref constructor: [ foo, bar ] * Extra spaces in hashref constructor: { foo => bar } Because [] and {} are a harder to read. I know this is inconsistent wi +th (), but I really like it this way. * No parens unless needed for clarity * Only &&/||/! where parens would be needed with and/or/not Perl has enough interpunction already * 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]) To indicate precedence rules. I think C<< print (foo), bar >> is misle +ading. * 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 * Explicit returns from subs * Space around index/key if it is complex: $foo{ $bar{baz}{bar} } Clarity and to avoid bugs. * use strict and -w To avoid bugs * Lots of modules, but not to replace few-liners or simple regexes Code re-use is good, but I don't want to add too much overhead. e.g. I + don't use URI::Escape much. * No double spaces except for vertical alignment * No double empty lines Maintainability, consistency. * Guards ("return if ...") are nicer than large else-blocks Maintainability, readability. You don't have to read the rest of the s +ub/loop to see if there's anything else to execute. This also helps k +eeping sub and loop blocks short. * No space between array/hash and index/key: $foo[0], $foo{bar} * No space between ++/-- and the variable I know you dislike this. But I find a space between aggregate and inde +x VERY hard to read. With my parenthofobia, that looks too much like +a function call that way, too. And this is the only way to interpolat +e, and I want consistency. More or less the same applies to ++/--. * No quotes for simple literal hash keys * No C-style loop for skipless iteration * No looping over indexes if only the element is used Readability, laziness. * 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 Readability. * No "outdent"s * No half indents * No double indents * Complex regexes get /x Readability, maintainability. * grep and map EXPR when BLOCK is not needed Speed. * English identifiers Unfortunately, the world speaks English (I prefer Esperanto). If your +code is in English, more people will understand it. * Not the English.pm module I don't see its use. Those names are even harder to remember than the +characters. * Multi-word identifiers have no separation, or are separated by u +nderscores Readability, laziness. * Lowercase identifiers, but uppercase for constants Readability and recognizability. * Whatever tool is useful: no OO when it does not make sense I'm not a purist. I just want to get work done. * It's okay to import symbols Too many people are afraid of importing symbols while importing symbol +s can really clean up code a lot. * 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 i +f it changes, which is VERY bad. * Always check return values where they are important To avoid bugs. Die before something worse happens. (that sounds funny +:) * No spaces around: -> ** These are very tight binding and are quite visible anyhow * Spaces around: =~ !~ * / % + - . << >> comparison_ops & | ^ && | +| ?: assignment_ops => and or xor * Spaces or no spaces, depending on complexity: .. ... x * No space after, unless complex: ~ u+ u- Readability, but regarding .. and x: laziness. * Long lines: break between method calls, -> comes first on a line +, space after it The space here is inconsistent with an earlier rule, but it adds to re +adability here, since the LHS has whitespace (indent) too. * => where it makes sense To indicate key/value relations. * qw where useful Laziness. * qw when importing, but '' when specifying pragma behaviour * () for empty list, not qw() You import a *list* of symbols, but I think C<< no strict qw(refs); >> + looks strange, I want empty lists to look the same everywhere. * -> to dereference, where possible Readability. * No abbreviations (acronyms are okay, and so are VERY common abbr +eviations) NEVER "ary" TIMTOWT abbreviate, and abbreviations are not always clear. * Data type not represented in variable name: "%foo" and "@foo", b +ut not "%foo_hash" or "@foo_array" Sigil and/or index/key brackets already indicates container type. * 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 specific reason. * No one-letter variable names, unless $i or alike * $i is a(n index) counter Common practice. I also find one-letter variable names make code unrea +dable. Have a look at Attribute::Property, where I make an exception. + Can you tell what %p, $P and $p are used for in $p{$P}{$p}? ;) * Dummy variables can be called foo, bar, baz, quux or just dummy No specific reason. I dislike "temp". * Taint mode *only* for setuid programs I hate Perl's tainting system (it slows down coding and execution by W +AY too much), but it is automatically enabled for setuid stuff. * No sub main(), unless it needs to be called more often than once Seems to make sense, but I forgot the specifics. * Subs before main code! I want to use them without parens, and I want strict to catch my typos + early. Also, I want the complete story when reading code, so by the +time I read the main stuff, I already have a clue about what the util +ity functions do. * Declare variables on first use, not before (unless required) To avoid having unused variables around, and to make sure I remove all + instances of a variable when I want to get rid of it. * \cM > \x0d > \015. \r only where it makes sense as carriage retu +rn. Just the way I like it. \r can be any character, but it should act lik +e carriage return. Don't use it when the actual meaning of carriage r +eturn is lost in history (e.g. networking). * List assignment for parameters/arguments, not lots of shifts Readability. And only because Perl doesn't have sub foo ($foo, $bar) +syntax (yet). * Only shift $self from @_ if @_ is used elsewhere in the sub * Direct @_ access is okay in very short subs Laziness, readability, maintainability, speed. * No eval STRING if not needed Avoid bugs. * 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 al +ias Consistency. And I want things to make sense. * No setting of $| when it is not needed Many scripts set $| to true even when it is not needed at all. Especia +lly merlyn's code suffers from this. If there's $|++ in my code, that tells something about the output. * Lexical filehandles Avoiding bugs, catching typos, restricting scope. * No v-strings Nice experiment, but not too useful in my opinion. * Single quotes when double-quote features not used Maintainability and avoiding bugs. * In DBI: value interpolation using placeholders only Security and avoiding bugs. * use base 'BaseClass' instead of use BaseClass and setting @ISA Style. * Comments where code is unclear * Comments usually explain the WHY, not the HOW If what the code does is not clear to people who understand Perl, it s +hould be rewritten. However, why a certain way of doing something was + chosen should be documented, so others don't have to think about all + the options themselves. * POD at the bottom, not top, not interleaved I find it very hard to read code that have both. Partly because =item +and friends are paragraphs and require empty lines because of that. E +ither I'm coding or I'm documenting. One thing at a time, please. * Sane variable scopes Avoiding bugs, adding to clarity. * No local, except for perlvar vars Because no globals. :) * Unbalanced custom delimiters are not metacharacters and not alph +anumeric Readability. I find it very annoying when people use || to delimit reg +exes. It means you must change delimiters if you ever want to add an +alternative. * RHS of complex s///e is delimited by {} {} is used to delimit blocks of code elsewhere too. * Favourite custom delimiter is [] I just like it. * Semi-colon only left out for implicit return or in single-statem +ent block No specific reason. * No $&, $` or $' Speed. * Localization of globals if they're to be changed (local $_ often + avoids weird bugs) Avoiding bugs. I think code in one place should not effect variables i +n another, unless it is clear it will. * Semi-colon not on its own line If semi-colon is on its own line, that means it's a multi line stateme +nt. If I want the ; not to be on the last line, I should add parens. +Readability. * (in|de)crement in void context is post(in|de)crement Dunno. Always did it like that, even though Perl optimizes $foo++; to +++$foo; anyway. * No map or grep in void context Because there's no reason to do it, and doing so makes code very uncle +ar. * ? and : begin lines in complex expressions Readability. I read them as "if so" and "if not" $foo eq $bar ? something complex here : something complex here; * True and false are always implied. No $foo == 0 when testing for + truth. Because not everyone uses pure true and false. Besides that, laziness +and readability.

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

Replies are listed 'Best First'.
Re: Re: Re: Style, *again*
by graff (Chancellor) on Apr 09, 2003 at 00:57 UTC
    * 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.

Re: Re: Re: Style, *again*
by Rich36 (Chaplain) on Apr 09, 2003 at 19:04 UTC

    * 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»

      my $text = <<'    EOT'

      Which part of "Adding the indent spaces to the end marker means code stops working if it changes, which is VERY bad." do you not understand? I'm not sure you even misunderstand it, because you repeat it: "It still has the drawback that if ...".

      Suppose you add 8 spaces to the end marker because it is indented by two levels. But you decide to loop over this code. You add a while (EXPR) { and a }, and being the smart programmer that you are, you indent the block immediately using the easy feature your favourite editor has for doing so. Oops, you just broke the code by changing indentation! Unless you add another 4 spaces to the end marker, your code no longer works.

      I prefer series of concatenations or repeated print statements to error prone sugar.

      As for removing whitespace from the beginning: I usually output HTML and do not care.

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

Re: Style, *again*
by Abigail-II (Bishop) on Apr 10, 2003 at 11:42 UTC
    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

      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.

      It's kind of normal to put the topic (subject) first. 4 is not the topic, because you already know what 4 is. $foo is what you are unsure about.

      Consider these sentences:
      "If the image on the cover is a camel, the book is probably Programming Perl."
      "If a camel is the image on the cover, the book is probably Programming Perl."
      "If foo is 4, ..."
      "If 4 is foo, ..."

      The camel is constant, the image can be anything.

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

        I see.

        I do sometimes write the constant first, because I want to reduce the amount of punctuation. If you write:

        foo $x, $y == 4

        then foo isn't called with arguments $x and $y. You'd need to write that as:

        foo ($x, $y) == 4

        Or

        4 == foo $x, $y

        And since == is a symmetric operation (assuming it's not overloaded), I don't feel strongly for the "topic first" argument. But I can see your point.

        Abigail

        It does make more sense when you read it out loud, but since there's no semantic difference, it sometimes helps to place immutables as the first operand since then you'll get a compiler error out of the simple typo:
        unless ($foo = 4) { ... argle blougat blopf ... }
        when it looks like this:
        unless (4 = $foo) { ... womble ... }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://249102]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (1)
As of 2024-04-25 19:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found