http://qs321.pair.com?node_id=456031

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

A lot of worry goes into proper naming of public modules (e.g., anything on CPAN). And rightly so - these should be descriptive to the point that it's obvious what the module is doing, and it's also further obvious that no one not doing the same thing would use the same name.

However, I have to wonder what others are doing for their private project-specific modules. Our structure has kind of grown up with us - I started the project barely knowing perl at all, so this just didn't occur to me at the time. Since then, I've started to place some modules in subdirectories off the @INC path, but just got to wondering how normal this might be.

Does anyone actually install all their project modules directly to the perl site_lib? Or do you always use lib ...? Do you put your modules at the top of the namespace, or do you have a hierarchy? Are there any rules (whether hard and fast, or merely rules of thumb) that you follow, whether they are written down or not (yet)?

Just as an example, we have all of our extremely-frequently called object types at the root namespace, e.g., 'X', 'Y', and 'Z' (I'm not going to use 'B' as an example ;-}). I'm actually somewhat loath to move them to a sub-namespace, e.g., 'Object::X', 'Object::Y', and 'Object::Z'. However, they all derive from another type, say 'Object::Base'. The string, 'Object::Base' is only used a handful of times (at the top of 'X', 'Y', and 'Z'), so I don't mind having it more clear.

We have a few modules at the root namespace which really should be buried in a subnamespace, but I've just not gotten around to cleaning that up (under the principle of "it ain't broke, yet").

We then use lib ... combined with FindBin and File::Spec to find the project-specific libraries, which are being run nearly directly out of our version control system, so the path is different for each developer. Because we are running it directly from an extracted copy of the version control system, we obviously also cannot install our modules into the global perl environment, otherwise going back a version wouldn't work very well.

I doubt there is such a thing as a "best practice" for this, since we're all in drastically different problem domains, and different practices make sense in different places. I'd just like to expand my horizons a bit here so I can see other ideas, which I sure as heck won't be able to do staying in this job ;-) other than by asking the community at large. I'm hoping there are some others with ideas that would make a lot of sense in my environment which I just hadn't thought of.

Thanks!

Replies are listed 'Best First'.
Re: How to lay out private modules?
by dragonchild (Archbishop) on May 11, 2005 at 15:31 UTC
    I generally organize based on the "Who cares?" principle. Stuff should located with whoever cares. So, if it's stuff that everyone in the company needs, I put it in the Company:: namespace. If it's something a given application cares about, I put it in the App04:: namespace. Under those, I generally have things like ::Database (for DB stuff), ::Application (for CGI::App-derived stuff), and whatever else I need.

    All of that is in one path not in the standard @INC that gets use-lib'ed from startup.pl. (Yes, I'm a mod_perl nut.)


    • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
    • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"
Re: How to lay out private modules?
by bluto (Curate) on May 11, 2005 at 16:48 UTC
    All of the modules are put under a tree like MyCompany, mainly to keep them as a unit (i.e. in case I ever want to install third-party modules under the same tree). If there are modules that are specific to an application or a specific resource, I put those modules under a subtree of MyCompany. Nothing original here.

    I generally install in a directory outside of perl's tree. This allows me to update my code or perl at different times. Also, if I have more than one perl installed (i.e. not just different versions in the same tree), I don't have to install my modules under each perl's tree. There's probably a clever way of configuring perl to do this when you build it, but I haven't looked into this.

    To access modules from a script I do something like...

    use FindBin qw($RealBin); use lib ("$RealBin/../lib/perl", "/my/well/known/lib/path"); use MyCompany::MyModule;

    The first 'use lib' path is for testing purposes (e.g. just before an install, or on a test machine). The second is the production path and is a full path so that the script can be moved and still work properly.

    This works reasonably well. If you can live with the script not being moved around, I'd suggest not using a full path since it limits changes to the environment. Also, if it weren't too much coding I'd like to be able to turn off the test path during production -- I just haven't thought of a clean/easy way of doing this. I work in a limited environment so that this is not much of a security issue though.

Re: How to lay out private modules?
by Animator (Hermit) on May 11, 2005 at 15:35 UTC

    Something you could use instead of use lib is the PERL5LIB environment variable...

    So far I've some modules which are in a directory which is part of the @INC, and some only in the directory of one of my projects... for some others I have a symlink in a @INC-dir point to another dir (which ofcourse isn't in the @INC)...

      Something you could use instead of use lib is the PERL5LIB environment variable...

      They are exactly the same thing. One is on a per-user basis and the other is on a per-file basis. Which you use is dependent on your needs. Generally, 'use lib' is preferred precisely because it's user-independent.


      • In general, if you think something isn't in Perl, try it out, because it usually is. :-)
      • "What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against?"

        Well, not exactly the same...

        If you move the script when you have 'use lib' then you might need to change the script... (ofcourse this is not true when the path of the modules-directory is relative to the path of the script path, but that's not always the case)

        And ofcourse one can argue wheter or not user-independene is required... if many users are using it then it might be better to put it in a INC-dir (in a subdirectory ofcourse)

        It all depends on one needs... which is why I mentioned it, since not everyone might know about the variable... (which would indicate that they didn't read (or skipped some parts) of the perlrun POD...)

Re: How to lay out private modules?
by Smylers (Pilgrim) on May 12, 2005 at 09:14 UTC

    Something you want to be careful about is avoiding any of your modules having names that clash with modules on Cpan, cos that would get far too confusing.

    An easy way of doing this is putting them all in a namespace which identifies them as being local to your organization. The namespace Local:: is reserved for this, so you can have Local::Foo, Local::Bar, etc, or you can use Your_Organization::Foo, Your_Organization::Bar, etc; in theory putting an underscore somewhere in your organization's namespace should avoid it clashing with anything on Cpan.

    We do the above for any modules which implement our business logic or are otherwise specific to us. For any more general purpose modules we give them a Cpan-type name, so we can then release them to Cpan.

    Smylers

Re: How to lay out private modules?
by hv (Prior) on May 12, 2005 at 11:23 UTC

    For my work application, the modules are installed into an installation-specific directory (which is never in perl's lib hierarchy). They are all named with an application prefix ("NVC::" in this case), but that's more to avoid confusion in coding than confusion on the filesystem.

    Scripts tend to have an early:

    use lib 'lib'; # fixup on install
    which is fixed up at installation to point to the installation's lib directory. (If you run an uninstalled script directly from the CVS checkout directory the unmodified line will also do the right thing, as long as you are in the top-level directory to start with.)

    This system works very cleanly for us, and we have some 40 or so installations of the application (scattered across various revisions of the code) all happily coexisting on a single machine.

    Hugo

      If you are website based you may find some structure based on the java naming conventions useful.
      They use the domain name in reverse to give a distinct lib path to each website

      For example org.perlmonks.monastry, com.ebay.auction etc etc