Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Where to store class configuration settings in a module used by multiple applications

by clinton (Priest)
on Feb 09, 2008 at 16:38 UTC ( [id://667187]=perlquestion: print w/replies, xml ) Need Help??

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

Consider this scenario:
  • You're running two or more different websites/applications within a mod_perl process.
  • Both applications use a common module (eg a form validation module)
  • Each website wants a different "base configuration" for said module (eg the list of permitted HTML tags)
  • The module is used in many places throughout the code, so you don't want to have to pass in the configuration every time you call new().

Where do you store this base configuration for each application?

My approach to this has been something like this:

-------------------------------------- package Form::Validator; my %Config; sub set_config { my $class = shift; my %settings = @_; @{$Config{$class}}{keys %settings} = values %settings; } --------------------------------------
Then in each website/application, use a subclassed version of this module:
package Website1::Form::Validator; use base 'Form::Validator';

Do you see any flaws with this approach? Can you suggest a better way of doing this?

thanks

Clint

Replies are listed 'Best First'.
Re: Where to store class configuration settings in a module used by multiple applications
by pc88mxer (Vicar) on Feb 09, 2008 at 18:15 UTC
    (After more carefully reading the problem, I'm only going to suggest the object member solution.)

    You might also consider making the configuration an object member instead of a class member. Then you could have multiple, differently configured Form::Validator objects in existence at the same time. Here's how it would work:

    package Form::Validator; sub new { ... $self->{allowed_tags} = []; # initially empty } sub SetConfig { my $self = shift; $self->{allowed_tags] = [ @_ ]; } package WebSite1::FormValidator; my $fv = new Form::Validator(); $fv->SetConfig(qw(a input ...)); ... package WebSite2::FormValidator; my $fv = new Form::Validator(); $fv->SetConfig(qw(...));

    You could also make the configuration a constructor parameter.

Re: Where to store class configuration settings in a module used by multiple applications (factory)
by tye (Sage) on Feb 10, 2008 at 03:23 UTC

    Subclassing to change configuration seems like a poor use of subclassing. You shouldn't create a subclass in order to change the data values in an object. If you later had some better reason to use inheritance you'd have to fit your inheritance into a existing tree of classes, which would likely be very complicated if you got it to work at all. Inheritance is best reserved more as a "last resort" in a design. The "is a" relationship is too inflexible and so should be invoked sparingly.

    I hate Repeat::The::Really::Long::Class::Name->new() syntax. Package names should be very clear and globally unique and you should only ever mention them once in your code. I much prefer to have a (pre-configure) factory for constructing any objects:

    my $Valid; use Form::Validator( Factory=>\$Valid, AllowedTags=>[...], OtherConfig=>..., ..., ); # ... my $obj= $Valid->new( ... );

    That way you can use the same module two or more ways from the same code. You can store your pre-configured factory in a file-scope lexical, a package global, as a member of each object, anywhere you can store a lexical.

    And, in practice, in Perl, it is often natural to just allow any object to be a factory for its own class. $obj->new( ... ) creates a new object using the configuration information from $obj. Then you may want a way to create a pre-configured but empty object to use just as a factory.

    - tye        

      Of the three solutions mentioned so far, I like yours the most - it's clean and flexible. The only downside is that you need to make the $Valid object available wherever you want to use the module. But, if you consider this to be in the league of "configuration data", then you would usually be doing that anyway, so no biggie.

      thanks Tye

      It occurred to me, after posting the above reply, that the one situation where this doesn't help is with class methods, when the method isn't expecting an object. A class method may require (eg) a base directory, or some other setting which will vary per application, but that you don't want to have to pass in on every use.

      Clint

Re: Where to store class configuration settings in a module used by multiple applications
by pajout (Curate) on Feb 10, 2008 at 11:44 UTC
    Please, excuse typos, that code is writen directly to web form. Consider it as idea, not final code.

    package FormValidator; use strict; use warnings; my %conf;#{app_id1=>conf1,app_id2=>conf2} sub new { my ($class,$conf,$app_id) = @_ $app_id = $ENV{APP_ID} unless defined $app_id; $conf{$app_id} = $conf if defined $conf; return bless $conf{$app_id}, $class; }
    The idea is to distinguish between applications using APP_ID, which can be set in apache configuration. If you want set configuration for some application, you can perform
    #first application $ENV{APP_ID} = 'APP_1'; my $obj_1 = FormValidator->new({foo=>'bar'}); my $obj = FormValidator->new(); print $$obj{foo};#prints 'bar' #second application my $obj_2 = FormValidator->new({foo=>'BAZ'},'APP_2'); my obj = FormValidator->new(); print $$obj{foo};#prints 'BAZ'

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (4)
As of 2024-04-24 01:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found