Good programming practice prescribes that you do not allow foreign code to mess with a module's data directly, instead they must go through an intermediary, for example an accessor routine.
TIMTOWTDI, with and without exporting. The Moose example appears quite long, but this one also allows setting data as opposed to just reading it from Test1
, where the other three examples would need quite some additional code to handle this case.
unsugared
Module
package Test1;
{
my %hash = (a => 10, b => 30);
sub member_data { return %hash; }
}
1;
Program
use Test1 qw();
Test1::member_data; # returns (a => 10, b => 30)
Moose
Module
package Test1;
use Moose;
has 'member_data' => (is => 'rw', isa => 'HashRef', default => sub { return {a => 10, b => 30}; });
1;
Program
use Test1 qw();
Test1->new->member_data; # returns {a => 10, b => 30}
# can also set/write data! ->member_data(\%something_new)
Sub::Exporter
Module
package Test1;
use Sub::Exporter -setup => { exports => [ qw(member_data) ] };
{
my %hash = (a => 10, b => 30);
sub member_data { return %hash; }
}
1;
Program
use Test1 qw(member_data);
member_data; # returns (a => 10, b => 30)
Exporter
Module
package Test1;
use parent 'Exporter';
our @EXPORT_OK = qw(member_data);
{
my %hash = (a => 10, b => 30);
sub member_data { return %hash; }
}
1;
Program
use Test1 qw(member_data);
member_data; # returns (a => 10, b => 30)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…