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

Hello,

Say I want to create a package with this framework:

package my_test_package; # Create a package global. my $ME = undef; # Return the required reference. sub new { # If $ME has been set do not bother doing all the init again. return $ME if defined $ME; my $class = shift; my $self = {}; # A lot of long-winded initialization. bless $self, $class; $ME = $self; return $self; } 1;

The basic idea is to avoid running through all the longwinded setting up several times. This is intended to be run under something such as mod_perl where the object might actually hang around for weeks, leading to performance gains.

My question is 'Is this a good idea?' I can think of the following pros and cons:

Pro:
Creating a new instance of an object is much faster as it needs only return a reference if the init code has been run once already.
Con:
It could prove dangerous if the module is internally altered during use, the same object could be in scope in several places. This shortcut is only usable for unchanging modules (such as allowing object orientated access to fixed configuration values).
Con:
There could be a serious memory penalty if the code is sloppy as it could be possible for garbage collection to never run. Also packages loaded from our package will also persist.
Pro:
Values can persist in the package between different objects. For example if it was a module for keeping track of high scores then a new score object could be created which would have in it all the previous scores for this process. (This "feature" could rapidly become a bug)

I suppose I really want your opinions on wether the risks involved outweigh the benefits. Are there any safeguards that could be put in place to keep the code safer? Any thoughts would be much appreciated.

Replies are listed 'Best First'.
Re: Never letting package objects to go out of scope
by jdporter (Paladin) on Feb 10, 2003 at 14:53 UTC
    Is this a good idea?

    Sure it's a good idea. What you have done is something many people have found it expeditious to do on many occasions. It is a software pattern. In fact, it has a name: Singleton.

    See the extensive discussion of it at the Portland Pattern Repository.
    For a perl-centric view, see scrottie's Perl Patterns wiki.

Re: Never letting package objects to go out of scope
by mowgli (Friar) on Feb 10, 2003 at 14:41 UTC

    I think it would be a good idea to not export the new() constructor and instead use a class method that returns the (only) instance of the class, initializing it if necessary (in OO programming, this is called a Singleton, although I don't know much about design patterns and may well miss something here). While not changing the way the code itself works, calling something like getInstance() instead of new() would make it much more clear to the programmer using the module that he is actually always working with the *same* object - to me, a new() constructor carries the out-of-band information (so to speak) that I actually do create an entirely new object when calling it instead of getting a reference to an existing one.

    It might not make the code safer as such, but I think it might well prevent some bugs from happening.

    --
    mowgli

Re: Never letting package objects to go out of scope
by perrin (Chancellor) on Feb 10, 2003 at 15:31 UTC
Re: Never letting package objects to go out of scope
by LanceDeeply (Chaplain) on Feb 11, 2003 at 03:08 UTC
    If you don't require a stateful object, the Singleton may be the way to go. But if the methods change the state of your shared object, and you have multiple places in your code that call the object, you'll probably have to create separate instances.

    You may want to consider a ResourcePool:

    The ResourcePool is a generic connection caching and pooling management facility. It might be used in an Apache/mod_perl environment to support connection caching like Apache::DBI for non-DBI resources (e.g. Net::LDAP). It's also useful in a stand alone perl application to handle connection pools.

    The key benefit of ResourcePool is the generic design which makes it easily extensible to new resource types.

    The good monks here pointed me towards it after I tried creating a pool for DBI handles.
Re: Never letting package objects to go out of scope
by Anonymous Monk on Feb 10, 2003 at 15:01 UTC
    It has great uses. I'd think it similar to GLOB's. You can universally create one object and keep it for one use. Such as database handles or statement handles. Anything expensive tocreate and you can provide some sort of reset() to change the state back to its original state before use AND is thread safe.