Henri Icarus has asked for the wisdom of the Perl Monks concerning the following question:
Greetings from a newcomer.
I've written a whole bunch of CGI code, but never with "use strict". Lately I've been trying to clean up my unstrictly ways, however, one of what I've always thought of as my "good programming practices" seems to be getting in the way, namely that of having an "include" type file with various constant values, directory names, utility subroutines, etc.. that I then requre into the various different CGI scripts that make up my web-app.
Of course, now that I'm being "stricter", any globals defined in those "required" files appear as undeclared variables because perl apparently finishes compiling the first file before compling in the "required" file.
So, what's the wisdom on good perl practice in this regard?
Thanks!
Re: Trying to be stricter...
by arturo (Vicar) on Jun 01, 2001 at 03:55 UTC
|
Disclaimer I don't pretend to give 'accepted wisdom' here, but from my own experience, I'd suggest turning your library of code into a full-blown module that uses the standard Exporter methods to export its variables (including subroutines). Then you just use that module.
It's a bit of work (but then, anything you'll do to retrofit things will be a bit of work, some more than others). This method allows you to only export those variables you want, rather than messing up your namespaces,
and it will be relatively easier to understand later on, plus you can distribute your module to others who might find it useful.
Plus, you'll learn something in the process. I know I did =)
HTH
perl -e 'print "How sweet does a rose smell? "; chomp ($n = <STDIN>);
+$rose = "smells sweet to degree $n"; *other_name = *rose; print "$oth
+er_name\n"'
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
I'd agree with that, but add that it's generally a really good idea to declare your constants as constants, not as variables. Or, to coin a phrase, "If something isn't supposed to vary, why make it a variable?" So instead of having
$Foo = 'bar';
I'd have:
use Exporter;
@ISA = qw(Exporter);
@EXPORT_OK = qw(FOO);
use constant FOO => 'bar';
That way, you won't accidentally alter the value of FOO elsewhere in the program. Plus, it'll be interpolated as a literal, so you might actually gain some speed.
stephen
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Trying to be stricter...
by lestrrat (Deacon) on Jun 01, 2001 at 02:55 UTC
|
Right. "require" happens at runtime, where as
"use" happens at compile-time
So at the point that the compilation occurs, perl sees
the strict, but not the contents of the required
files.
This soudns more like a personal choice and/or project
dependent choice, so I don't know what is the better
way for you to do this.
But if this required file only declares variables
that are used in a particular CGI script, you might as
well declare them in the scope that they are used at...
| [reply] [Watch: Dir/Any] |
Re: Trying to be stricter...
by DBX (Pilgrim) on Jun 01, 2001 at 03:52 UTC
|
Assuming you are putting them in a separate file so that other scripts can use them (otherwise they would probably be in the file that 'require's them), you could put them in a module, then export them. If there's quite a few, you might put them in a separate module in a subroutine, then export only that subroutine. You could write it in such a way that you tell the subroutine what you want and it returns the value, or it can return a hashref with the keys being variable names (although this would require you to rewrite existing scripts). There are other solutions, but it depends how your current scripts are written and how much you have to export. | [reply] [Watch: Dir/Any] |
Re: Trying to be stricter...
by princepawn (Parson) on Jun 01, 2001 at 04:23 UTC
|
| [reply] [Watch: Dir/Any] |
Re: Trying to be stricter...
by Trimbach (Curate) on Jun 01, 2001 at 07:47 UTC
|
I can't vouch for the wisdom of one approach over another, but here's what I've done in the past:
If all I want to import are a batch of config variables, I've require'd a file consisting of subs that return some value or another, like:
# Contents of config.pl
sub big_list {
return qw(some enormous list of variables);
}
# And then in my program...
require config.pl;
my @big_list = big_list();
If I want to import some simple set of subroutines (housekeeping stuff mostly... subs that don't really belong anywhere else) I'll make a file of subs and require them like before, except I'll (obviously) pass values into and out of the sub instead of just "out" as above. If you have a truly global variable that you want your imported subs to see, use "use vars " or "our" to declare your global variable.
Of course, if I have a batch of config variables or subs that actually belong together the best place is to put it into a full-blown module. I won't build a module unless it makes sense, though. I have literally used all three techniques in different parts of the same project. Whichever fits you best. All three techniques are ways to re-use code, and re-using code is right up there with cleanliness and godliness. So, at least in my opinion, it's aaallllll gooooooddddd.
Gary Blackburn
Trained Killer | [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Trying to be stricter...
by bikeNomad (Priest) on Jun 01, 2001 at 04:50 UTC
|
You could either make a module out of your include file with its own package, or you could just make sure that the file ended with something that returns true ( 1; is often seen), and use use:
(in myIncludeFile.pm)
use constant SOME_CONSTANT => 1;
sub whatever { 123 }
1;
(in your CGI file:)
use myIncludeFile ();
Since use xyz; is equivalent to BEGIN { require xyz }, this loads the included stuff at the right time.
updated: used bareword form of use (oops!) | [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] [d/l] [select] |
Re: Trying to be stricter...
by pmas (Hermit) on Jun 01, 2001 at 15:26 UTC
|
| [reply] [Watch: Dir/Any] |
|
|