Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer

Trying to be stricter...

by Henri Icarus (Beadle)
on Jun 01, 2001 at 02:31 UTC ( #84775=perlquestion: print w/replies, xml ) Need Help??

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?


Replies are listed 'Best First'.
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 =)


    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"'
      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.


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

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.
Re: Trying to be stricter...
by princepawn (Parson) on Jun 01, 2001 at 04:23 UTC
    I've been watching this thread grow and grow, and to date, no one seems to want to mention the various modules designed to store config info:

    Config::IniFiles AppConfig

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:
    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!)

      Trying to use a filename (as opposed to a module name) doesn't work on my Perl (5.005 on Linux). It throws a syntax error. The man page on use offers some insight as to why:
      It is exactly equivalent to
      BEGIN { require Module; import Module LIST; }
      except that Module must be a bareword.
      Therefore, to use use, the constants file must be a proper module ending in .pm, and the above use '' (); syntax is a syntax error.


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 sub big_list { return qw(some enormous list of variables); } # And then in my program... require; 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

Re: Trying to be stricter...
by pmas (Hermit) on Jun 01, 2001 at 15:26 UTC

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://84775]
Approved by root
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2023-02-08 04:20 GMT
Find Nodes?
    Voting Booth?
    I prefer not to run the latest version of Perl because:

    Results (40 votes). Check out past polls.