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

Does this eliminate a global? Or does it just give the same problem a fancy hat?
package my::data; use strict; use warnings; my $Config ={ # this would be loaded from a config.ini file root => { local => 'c:/local', remote => 'docroot', }, category => { europe => 'europe.html', women => 'women.html', }, }; sub Config{ if (@_ == 4){ $Config->{$_[1]}{$_[2]} = $_[3]; return $_[3]; } elsif (@_ == 3){ if (exists $Config->{$_[1]}{$_[2]}){ return $Config->{$_[1]}{$_[2]}; } else{ return; } } else{ return; } } 1;
After adding
use my::data;
to any module $Config can then be accessed:
$data = my::data->Config('root', 'local');
or changed:
my::data->Config('root', 'local' => 'c:/local_path');

Is this "a way to do it"? Or is it just madness?

Replies are listed 'Best First'.
Re: Using "Class Data as Package Variables" to hold a global
by salva (Canon) on Apr 30, 2005 at 15:07 UTC
    Does this eliminate a global?

    No, it's just a new hat, but on the other hand, there is nothing wrong on using globals for storing global data and for most apps, configuration data is just global data.

    Anyway, I would break the configuration module in two:
    a) a generic class abstracting the configuration access logic.
    b) a module implementing a singleton to access the global configuration specific to the app.

    For example:

    class Config::Foo;

    package Config::Foo; sub new { my $class = shift; my $fn = shift; ## read the configuration file here ## ... bless $this, $class } sub get { my $this=shift; my $key=shift; my $default=shift; exists $this->{$key} ? $this->{$key} : $default; } sub set { my $this=shift; my $key=shift; my $value=shift; $this->{$key}=$value; } 1; --- package MyApp::Config; use Config::Foo; require Exporter; our @EXPORT=qw(config); our @ISA=qw(Exporter); ## (updated!) my $config; sub config { $config=Config::Foo->new('/etc/myapp.conf') unless defined $config; $config; } 1; --- # and in your app use MyApp::Config; my $foo=config->get(foo); config->set(bar => 'new_bar');
      class Config::Foo;

      You had me searching perlfunc there...class? Never seen that before in Perl ;-) I take it you meant package?

      Remember rule one...
        oops, sorry, yes, I meant package!
      salva

      Many thanks. I've had a slight snag with the syntax. If I uncomment the line in the following code I get:

      Can't locate object method "set" via package "config" (perhaps you forgot to load "config"?) at myapp.pl line 9.
      #!/usr/bin/perl use strict; use warnings; use Auto::Config; my $root_local = Auto::Config::config->get(root => 'local'); # This line produces the error message # config->set('root', remote => 'docroot_new'); Auto::Config::config->set('root', remote => 'docroot_new'); print "$root_local\n";

      Do the methods have to be fully qualified like that? Or, more likely, have I goofed?

        I had forgotten to set @ISA, check me original post, I have updated it!
Re: Using "Class Data as Package Variables" to hold a global
by brian_d_foy (Abbot) on Apr 30, 2005 at 17:21 UTC

    By scoping the variable to the file (or class), it's no longer global. Only things in that same file can access it. Some situations can naturally use a file scoped lexical variable: it's the same argument as class versus instance data in other languages.

    Good luck :)

    --
    brian d foy <brian@stonehenge.com>