http://qs321.pair.com?node_id=215026


in reply to Perl Programming guidelines/rules

Okay, I'll say good job on the list, [so|but] I'll make a few comments:

use strict and warnings

Glad that's option #1!
use HTML::Template not HERE documents
I disagree... there are times when content really is generated on the fly, and you have no clue where certain things are going to go. Hard to explain, but I think HTML::Template is more of a per-user preference.
no deliberate obfuscation
"Though shall not deliberately murder" :)
As stated previously... s/deliberately//
all files must be documented with POD (Author, Date created, synopsis, description)
Absolutely... that way you know who to blame when something goes wrong :)
OO always to be used where possible
I disagree with this one. Sometimes making code "OO-compliant" is just extra work that just isn't necessary. This is definitely a case-to-case (script-to-script) decision.
Pass by reference
This is another one that really depends on the case. If the data structures being passed to the function may need to be modified, then absolutely... but if the variables passed are just being read, why create a bigger hassle? The example below shows a case where passing by reference just wastes an extra dollar sign and backslash:
sub name_is { my $name = shift; return "My name is " . $$name; } my $name = "mt2k"; print name_is \$name;
No hardcoding of values especially file paths, script names etc
Excellent one! If you start throwing file paths all over the place, you're bound to run into major trouble if the script changes location or environment. At least throw these in a configuration script or in a configuration subroutine at the top of the script.
Config files or config scripts to be used
All for them! Read the last point to understand why.
Do not reinvent wheel always check CPAN
For probably 90% of the cases you'll come across, I would agree with you. As long as you trust someone else's code to be stable and not have any unexpected "features". Chances are, someone's already coded the function you need... why spend hours debugging one you tried to put together yourself :)
minimise coupling, maximise cohesion, maximise reuse
yes, yes and yes.
Always indent logic
Please do! It increases readablity, which means much easier maintenance... plus anybody else who has to look at your code will keep their sanity
Any reused code block above 5 lines must become a sub routine
Absolutely... though I wouldn't restrict it to 5 lines... if you use 3 lines 10 times in a script... that should most definitely become a subroutine.
Always retrieve database rows into hash reference not arrays
Nope. If you know that you're only getting one result back (ie: a primary key), using fetchrow_arrayref() can be quick.
Use CGI CARP
As long as you're not talking about fatalsToBrowser(), then yes. Remember, fatalsToBrowser() might display something to your users you might not want them to see. For production/debugging purposes yes, for code running to online users, no.
Assign CGI parameters to hashes
Definitely! This makes things extremely easy to access, though I must admit I don't know what would happen if you were to have a <select MULTIPLE>. Must look that up sometime.
Version history at bottom of file
If there have been changes worth documenting, then yes.
All subroutines to be commented
Whether as POD or comments, as long as there is at least something to explain what a subroutine does. If it's just a script, I believe comments (that should include a sample use) are fine. If it's a module... there had better be POD :). As a matter of fact, I'll show how I comment my subs:
# get_params # Retrieve all CGI parameters and return # a hash ref containing the data # ie: my $input = get_params; # print $input->{'name'}; sub get_params { my $q = new CGI; my %cgi_data; $cgi_data{$_} = $q->param($_) for ($q->param()); return \%cgi_data; }
Meaningful Subroutine and Variable names to be used
/me shudders at the thought of a script that uses $a, $b, $c, $d type variables. (especially a script that uses $a and $b, whilst using sort as well!)
Constructors must only create objects
Just learning about these at the moment actually! But I do understand the meaning behind this one. A constructor constructs an object... it doesn't fill the object with data :) See, I can learn!
Program flow control to be placed in 'main' method
If by this you mean that program flow is a set of subroutines being called in a row, without a bunch of clutter code in between, then I strongly agree. Subroutines are there to organise the code. If they are only used to make it messy, it doesn't help.
No Global Variables
100% approval there.
use my not local
my() is much better - save yourself the trouble!
All Perl filehandles should be in all uppercase
Yep, I agree completely. I can't really argue why, besides the fact that readability and maintainability are increased. I've just always used uppercase file handles
Always use CGI.pm
For CGI scripts that need to handle data, CGI.pm is a must, if only for reading CGI parameters. Don't do it by hand. The first time I needed to read in data, I processed STDIN and $ENV{'QUERY_STRING'}... horrible! Avoid it like the plague!
Use verbs for subroutines, use nouns for variables, be descriptive and consistent
Agreed. I can't imagine a sub named without a verb...
Do not use $_
There are times when not using $_ decreases readability and might even make things run slower. Take map(), grep(), and quick uses of for{...} for example(s?).
Do no use goto
There is absolutely no reason or excuse for using goto(). You should be using subroutines or a loop to handle these. Want to use goto()? Go back and use QBasic! As a matter of fact, is Perl 6 still going to support goto? It should be removed for the sanity of us all :)
Initialise variables
To expand upon this one, I'd like to add that variables should be declared at the appropriate place in the script. If you need a widely scoped lexical, place it near the top of the script. If you need a variable for only a subroutine, place it at the beginning of that subroutine. What I am saying is group all variable declarations of the same scope together.
Error handling done using Begin blocks at CGI level. All dies are logged
Shame on me... I've never used BEGIN{} for this purpose. The 2nd thing I need to look up regarding this list :)
Where code returns a result it should do so or die with a meaningful error and $!
A definite must. What if you unsuccessfully flock() a file... then you open the file for writing, even though the file has not really been locked... expect trouble if you ignore this tip. In my opinion, this should have been item #2 on this list.

Replies are listed 'Best First'.
Re: Perl Programming guidelines/rules
by Abigail-II (Bishop) on Nov 22, 2002 at 15:26 UTC
    What if you unsuccessfully flock() a file... then you open the file for writing, even though the file has not really been locked... expect trouble if you ignore this tip.
    Are you serious? No, you can't be. You cannot even do what you describe. You can only flock filehandles - and you only get a filehandle after opening a file. You don't first flock, then open. No, you first open, then flock.
    There is absolutely no reason or excuse for using goto().
    Really? You'll find people like Donald Knuth and Dennis Ritchie disagreeing with you. While goto ought to be used with caution, there's no reason to flat out forbid it. Not to mention that there's no alternative for goto &sub in Perl - unless you code similar functionality using XS.
    I can't imagine a sub named without a verb.
    Is new a verb? What about commonly used functions from CGI, like param, header or keywords?
    my() is much better (than local)
    But my isn't a drop-in replacement for local. Certain things that you can localize, you can't my.
    For CGI scripts that need to handle data, CGI.pm is a must, if only for reading CGI parameters. Don't do it by hand. The first time I needed to read in data, I processed STDIN and $ENV{'QUERY_STRING'}... horrible! Avoid it like the plague!
    Hmmm, for programs that only need reading in CGI parameters, I think CGI.pm is overkill, don't you? It's a dinosaur (with a bad name), and not exactly a good example of modular code writing. As for processing STDIN and $ENV {QUERY_STRING}, what do you think CGI.pm does? Get the parameters out of thin air?
    Yep, I agree completely. I can't really argue why, besides the fact that readability and maintainability are increased. I've just always used uppercase file handles.
    I, on the other hand, have hardly used filehandles for the last years (except for the default ones provided by Perl). We have been able to use references to filehandles for filehandle operations ever since 5.000, and since 5.6, open will autovivify one if given an undefined value as first argument.
    /me shudders at the thought of a script that uses $a, $b, $c, $d type variables.
    Ah, so you prefer:
    for (my $array_index_counter = 0; $array_index_counter < @array_of_some_sorts; $array_index_counter ++) { ... }
    The Pascal and Java way. I rather keep the tradition of Fortran, Algol and C, and use $i. It's ok for variables of a limited scope to have short names.
    Whether as POD or comments, as long as there is at least something to explain what a subroutine does.
    Keep your comments brief and short. If most of your subroutines need a lot of comments, it's a sign something is wrong. A good name goes a long way in describing what a subroutine does. And so do named parameters. POD and comments aren't interchangeable. The main purpose of POD is to generate manual pages - it will describe the interface. Comments describe the internals.
    if you use 3 lines 10 times in a script... that should most definitely become a subroutine.
    open my $fh => $file or die "Whatever: $!"; flock $fh => LOCK_SH or die "Whatever: $!"; local $_; while (<$fh>) { ....; } close $fh or die "Whatever: $!";
    That's five, often repeated, lines. You want to factor that out to a subroutine? How often do you think that happens in practise? What about a DBI prepare/execute/fetch combo wrapped in an eval? That's more than three lines as well. Factor it out?

    Abigail

Re: Re: Perl Programming guidelines/rules
by davorg (Chancellor) on Nov 22, 2002 at 11:18 UTC
    There is absolutely no reason or excuse for using goto()

    I think you need to take another look a goto - particularly the description of "goto &NAME". That can be very useful.

    --
    <http://www.dave.org.uk>

    "The first rule of Perl club is you do not talk about Perl club."
    -- Chip Salzenberg