Is it good practice to export variables in Perl?
I'm finding it very convenient to pass configuration and other data that is read or calculated once but then used many times throughout a program by using Perl's use
mechanism. I'm doing this by exporting a hash into the caller's namespace. For example:
package Myconfiguration;
my %config;
sub import {
my $callpkg = caller(0);
my $expsym = $_[1];
configure() unless %config;
*{"$callpkg\::$expsym"} = \%config;
}
and then in other modules:
use MyConfiguration (loc_config_sym);
if ( $loc_co开发者_如何学Pythonnfig_sym{paramater} ) {
# ... do stuff ...
}
However, I'm not sure about this as a best practice. Is it better to add a method that returns a hash ref with the data? Something else?
If you only want to read the values of %config
, then why not have a routine to do it for you?
my %config;
sub config_value
{
my ($value) = @_;
return $config{$value};
}
You could export this by default if you wanted to:
package Mypackage;
require Exporter;
@EXPORT = qw/config_value/;
The reason that I would not allow access to the hash all over the place in lots of different modules is that I would have a hard time mentally keeping track of all the places it was being used. I would rather make the above kind of access routine so that, if some bug happened, I could add a print statement to the routine, or something, to find out when the value was being accessed. I don't know if that is related to "best practices" or it is just because I'm stupid, but the kind of confusion created by global variables scares me.
There's no reason you can't have a set routine too:
sub set_value
{
my ($key, $value) = @_;
$config{$key} = $value;
}
I think it's better to work with a copy of the config hash. This way, if you modify some elements, this won't affect the rest of your code.
I usually use simple object (optionally Singleton) for this with a single method like get_property()
.
I suggest never exporting variables. Create a class that can return a reference to a private variable instead. People can then store it in a variable with whichever name they like, and only when they decide they want to use it.
In general, it's best to let the user decide whether or not to import symbols. Exporter makes this easy. Writing a custom import
method to let the user decide what to name imported symbols can be useful on rare occasions but I don't think this is one of them.
package MyConfiguration;
require Exporter;
our @ISA = qw(Exporter);
our @EXPORT_OK = qw(Config);
our %Config;
And then, in your script:
use MyConfiguration;
print $MyConfiguration::Config{key};
or
use MyConfiguration qw(Config);
print $Config{key};
精彩评论