Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling
 
PerlMonks  

OO Configuration Values (version 2)

by trs80 (Priest)
on Apr 22, 2003 at 23:58 UTC ( [id://252414]=perlmeditation: print w/replies, xml ) Need Help??

Intro
This node is a follow up to my original post on creating Object Oriented Configuration Values. Rather then repeat some of information from that node here, I recommend you read it first if you haven't already. After reading the replies and getting more exposure to various techniques I realized my original approach had some flaws. The intent of this node is to offer a refined approach that is more flexible and removes some potential bottlenecks.
New Information
blokhead had an issue with the fact that each call to new would recreate the methods, this is some expensive overhead since each method is dynamically created. A better way to do this would be create the methods at compile time and simply keep them available in their own class.
My::Config
In the last version we used OurApp::Base , but for this one we move into a slightly modified format. In the initial version each application level call to the module required us to pass in configuration files options, we can do away with that. By creating two slightly more robust core modules we can provide additional flexibility and reduce our per application code. Here is one of our new classes.
package My::Config; use strict; use base ( 'Class::Accessor' ); use Config::Auto; my $base = __PACKAGE__; our $config_hash = {}; bless $config_hash , $base; my $config = Config::Auto::parse( '/home/trs80/my.conf', format => 'equal' ); $base->mk_accessors(keys %{$config}); foreach (keys %{$config}) { $config_hash->$_($config->{$_}); } sub new { return $config_hash; } 1;
It now holds all the information about where to find the configuration files and it only loads the data once and then simply passes the object containing our values out when new is called. This reduces our overhead tremendously since we aren't auto generating methods on every call to My::Config->new(). Which is good in a persistent environment.
Our New Base Class
We have to create a new base class to address our changes to our configuration data. Here is our revised Base module.
package My::Base; use My::Config; sub new { my $self = { }; bless $self , 'My::Base'; } sub config { my ($self) = @_; my $config = My::Config->new(); return $config; } sub AUTOLOAD { my ( $self, $value ) = @_; $AUTOLOAD =~ /.*::(\w+)/; my $command = $1; if ( defined($value) ) { $self->config->$command($value); return; } else { return $self->config->$command; } } 1;
Three Ways to Get What You Want
In the initial version both IlyaM and Ctrl-z expressed some concern with the interface to the configuration values. In this version we modify this access to allow for the initial method along with two new ways.

Our three ways to access it are:
  1. As a My::Config object
  2. As a part of a config method provided by My::Base
  3. As a method name of the My::Base object generated by the AUTOLOAD
Here are the three tests:
!/usr/bin/perl # access config data directly from the My::Config class use My::Config; use strict; my $config = My::Config->new(); print $config->base_directory , "\n"; $config->base_directory("/home/otheruser/"); print $config->base_directory() , "\n";

#!/usr/bin/perl # access configuration data through the My::Base class use My::Base; use strict; my $object = My::Base->new(); print $object->config->base_directory , "\n"; $object->config->base_directory("/home/otheruser/"); print $object->config->base_directory() , "\n";

#!/usr/bin/perl use My::Base; use strict; # access configuration data by name through AUTOLOAD my $object = My::Base->new(); print $object->base_directory , "\n"; $object->base_directory("/home/otheruser/"); print $object->base_directory() , "\n";
Conclusion
The revised way of providing OO oriented access to configuration data improves upon the initial design by further reducing the application level code and providing additional ways to access the information.

Edit by tye, add READMORE

Replies are listed 'Best First'.
Re: OO Configuration Values V2
by rob_au (Abbot) on Apr 23, 2003 at 01:15 UTC
    Firstly, nice post trs80++

    My only comment would be on the use of the __PACKAGE__ pragma for establishing the scope of the singleton of the configuration object. In the comments of the Class::Singleton module, this approach is discussed and dismissed in favour of the full reference to a variable within the current class as determined by the class name passed to the class method. This approach permits better facilitates inheritance allowing inherited namespaces to have their own instance singleton.

    For example, from the instance method of Class::Singleton:

    sub instance { my $class = shift; # get a reference to the _instance variable in the $class package no strict 'refs'; my $instance = \${ "$class\::_instance" }; defined $$instance ? $$instance : ($$instance = $class->_new_instance(@_)); }

    I would only add to this by stating that I have quite happily used this singleton construct without issue in a number of object-orientated projects.

     

    perl -le 'print+unpack("N",pack("B32","00000000000000000000001001001111"))'

Re: OO Configuration Values (version 2)
by vladb (Vicar) on Apr 23, 2003 at 05:28 UTC
    As much as I'd hate this to be a 'me too' post, I find your discussion on representing static config in OO form interesting. In many of my own projects I find myself concentrated on other areas and fail to give enough attention to the configuration piece (as long as there's a way -- any way -- to access my config, I'm ok ;-))

    I probably have a very basic question..

    When you invoke the config() method on your My::Base object, it would create create a brand new instance of the My::Config class. I'm wondering if, eventually, you should be adding a check to see that if the config object has already been created, then you don't re-created anew. There could be an exception to this rule when the config object is flagged 'dirty'. The 'dirty' flag could be toggled when the base directory is reset (via the base_directory() method), for example.

    _____________________
    # Under Construction

      your $config_hash is populated once at CT and afterwards this reference is used all over the place.

      sub new { return $config_hash; }

      hands down this very reference to any new() instance so when you

      $object->config->base_directory("/home/otheruser/");,

      this one-and-only hash is altered and seen altered by each and every instance holding a ref to it

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://252414]
Approved by grep
Front-paged by Enlil
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others drinking their drinks and smoking their pipes about the Monastery: (7)
As of 2024-03-29 01:11 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found