apprentice has asked for the wisdom of the Perl Monks concerning the following question:

I'm looking at some legacy code for a web application where I work, trying to understand what it's doing, specifically with respect to a private namespace package.

Each webpage has it's own script (e.g., somepage.pl). Each of those scripts looks something like this:
#!/usr/bin/perl use strict; use Private; #call a bunch of things to make a page
The 'Private.pm' module looks something like this:
# This is a private namespace where all modules get loaded. # Warning: Don't put any 'use' statements that depend on Exporting int +o a namespace you will actually use in the programs. use strict; use base_class1; use base_class2; use CGI; use DBI; # etc., loads lots of modules
A few other modules 'use' various packages, but mostly do not.
My Question:
What is this 'Private.pm' package doing for the program? Is it allowing main to find and access the other modules? Does it in any way allow the other modules to locate each other (perhaps through main)? And, why do it this way?

Any enlightenment greatly appreciated!

Apprentice

Replies are listed 'Best First'.
Re: Private namespace package question
by count0 (Friar) on Dec 28, 2001 at 20:08 UTC
    From what you've shown, it seems Private.pm's only purpose is to load a group of commonly used modules. This was probably done by the original author(s) to avoid retyping all of those 'use ...' statements into each of the Perl scripts.

    IMHO, this is usually a bad idea, and can be avoided through better design. If each of the scripts always needs each of these modules, they can most likely have much of their workload, and page displaying functionality done through a common module.

    That said, you should also understand clearly what that warning is about. If a module included by Private.pm exports anything (for example, Carp.pm exports carp() and croak()), you will not be able to use it from outside of Private.pm. Instead you will need to fully qualify the name (Carp::carp() for example).
      Thanks, count0, your answer leads me to another question about the warning:

      You say that the warning means that outside of Private.pm I would have to call Carp::carp() since Carp.pm exports carp() (apparently only to Private.pm, doesn't carry over to anything that loaded Private). But, if a module doesn't export anything, doesn't that mean I would have to call its subs in the same way (somemodule::somesub())?

      If that last bit is true, is there any way to have one module load all the modules everything would need and then allow all other modules to use the subs of those modules without having to prepend the package names(as long as they were exported)?

      Thanks again!

      Apprentice

        apprentice wrote:

        is there any way to have one module load all the modules everything would need and then allow all other modules to use the subs of those modules without having to prepend the package names(as long as they were exported)?

        Um, yes, but you really don't want to do it. What it involves is writing a custom import routine in Private.pm and then using goto to call the other modules import routines (this prevents the call stack from being updated):

        sub import { # using goto to avoid updating caller # This will export everything to the package # that called this one goto &Foo::import; }

        Hmm... in retrospect, this also means the you can only export one package's subs from here. This is a tougher problem than I thought. On the other hand, whenever someone winds up trying to do stuff this tricky, it usually means that a redesign should be considered.

        Cheers,
        Ovid

        Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.

(Ovid) Re: Private namespace package question
by Ovid (Cardinal) on Dec 28, 2001 at 22:01 UTC

    count0 sounds correct in that this was probably done to avoid retyping a lot of use statements and that that this is not a good thing. Let me elaborate.

    1. If a script doesn't need a module, it's loaded anyway. No need for that overhead.
    2. It obscures what module you're script is actually using. When you see something like $foo->annihilate;, you probably would like to know what's being annihilated.
    3. What if you need, for one of your programs, to switch CGI for CGI::Lite? Oops! If you include CGI::Lite in the actual program, it's still loading CGI. If you include CGI::Lite in Private.pm, all of your programs needlessly load both.

    In short, while I understand why the original author did this, it takes away control with the only apparent benefit being saving a few keystrokes. You're already saving enough using Perl in the first place :)

    Side note: I am kind of wondering about the "use strict" statement at the top. If all this module is doing is loading other modules, this is useless. "use strict" is lexically scoped, so if you use Private.pm;, you'll gain the benefits of the DBI module, but not of strict. Since strict doesn't have any use in the module, I'm kind of wondering why it's there (other than habit - though it will prevent something like "ues CGI").

    Cheers,
    Ovid

    Join the Perlmonks Setiathome Group or just click on the the link and check out our stats.