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.