--- Shawn Hinchy <[EMAIL PROTECTED]> wrote:

> Hello all,
> 
> I am writing many cgi scripts and need to have the same variables  
> included in each of them.  I was going to put all these 'global'  
> variables in a separate file that could then be included in the top
> of each cgi script.

I've seen people do this many times and it leads to clunky,
hard-to-debug systems.  Globals should be avoided.  Because they wind
up being spread throughout your code, it's easy for them to get altered
in one spot and not be able to figure out who altered them.  Plus,
programmers can sometimes get confused about where those variables come
from, making bugs with them more difficult to figure out.  Also, any
functions which rely on the existence of globals becomes harder to
refactor/use (e.g., moving it to a module which doesn't have the
globals causes things to break).

Sometimes you *do* have data which everything needs to know about. 
Here are some suggestions:

1.  Put those variables in constants or use the 'Readonly' module from
the CPAN.  
2.  If a function needs one of them, pass it as an argument.
3.  Maybe put the variables in a module where you need to explicitly
request them via Exporter.
4.  Alternately, do number 3 with a config file.

> To include the subroutines I do this:
> 
> require './utilities.pl';

This is Perl 4 syntax.  Actually, it's Perl 3.  Please don't use that. 
http://www.oreillynet.com/onlamp/blog/2006/08/please_stop_using_perl_3.html.
 I know there's still a lot of stuff out there which teaches that and
I'm sorry you've learned from that, but the sooner you avoid that, the
better. 

> In the utilities.pl file I have this:
> 
> #!/usr/bin/perl -wT
> sub foo {}
> 1;

Rename that to something like 'My::Utilities' and try giving Exporter a
try, or any of its competitors.  Here's an example:

  package My::Utilities;

  use strict;
  use warnings; # if your version of Perl supports it

  use base 'Exporter';
  use vars qw(
    @EXPORT_OK
    $BAD_GLOBAL_VAR
    some_sub
  );

  @EXPORT_OK = qw(
    $BAD_GLOBAL_VAR
    COMPANY_NAME
    some_sub
    some_other_sub
  );

  $BAD_GLOBAL_VAR = 'try to avoid globals';
  use constant COMPANY_NAME => 'Acme, Inc';

  sub some_sub {}
  sub some_other_sub {}
  sub cant_get_exported {}

  1;

And in the calling code:

  #!/usr/bin/perl -T

  use strict;
  use warnings;
  use lib 'path/to/your/modules';

  use My::Utilities qw(COMPANY_NAME some_sub $BAD_GLOBAL_VAR);

With that, you have cleaner namespaces.  You only pollute your
namespace with the specific subroutines or constants you're asking for.
 It's obvious where things are coming from.

One problem with 'utilities' modules is that they tend to get very
bloated and programmers start shoving a bunch of stuff in them with no
rhyme or reason.  Then, when you do "require './utilities.pl'", you
wind up getting a bunch of extra subroutines and if you make the
mistake of reusing *any* subroutine name in any of your files, you can
get very mysterious errors, particularly if you forget to turn warnings
on (which, to your credit, you did not :)

I've worked on systems like this and they're not fun.  I recently had a
problem on a legacy system like this where I found a sub  not declared
in the code.  Then I found it was not declared in any of the code which
was 'require'd.  Then I found it wasn't in any of the modules *they've*
required.  I found it in a module which one of the *last* one's
required.  Of course, I first tried grepping through the code, only to
find that the function name in question was reused in a number of
places, so that didn't help, either.  It was very frustrating to work
on.  The system uses some of the "features" you're asking for help
with.  Please don't make the same mistakes :)

Cheers,
Ovid

--

Buy the book -- http://www.oreilly.com/catalog/perlhks/
Perl and CGI -- http://users.easystreet.com/ovid/cgi_course/

-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to