Приглашаем посетить
Ломоносов (lomonosov.niv.ru)

Section 5.2.  Package Variables

Previous
Table of Contents
Next

5.2. Package Variables

Don't use package variables in your own development.

Even if you're occasionally forced to use Perl's built-in non-lexical variables, there's no reason to use ordinary package variables in your own development.

For example, don't use package variables to store state inside a module:

    package Customer;

    use Perl6::Export::Attrs;    # See Chapter 17

    
    # State variables...
    our %customer;
    our %opt;

    sub list_customers : Export {
        for my $id (sort keys %customer) {
            if ($opt{terse}) {
                print "$customer{$id}{name}\n";
            }
            else {
                print $customer{$id}->dump( );
            }
        }
        return;
    }
    # and later in...
    package main;
    use Customer qw( list_customers );

    $Customer::opt{terse} = 1;

    list_customers( );

Lexical variables are a much better choice. And if they need to be accessed outside the package, provide a separate subroutine to do that:


    package Customer;

    use Perl6::Export::Attrs;

    
# State variables...
my %customer; my %opt; sub set_terse { $opt{terse} = 1; return; } sub list_customers : Export { for my $id (sort keys %customer) { if ($opt{terse}) { print "$customer{$id}{name}\n"; } else { print $customer{$id}->dump( ); } } return; }
# and elsewhere...
package main; use Customer qw( list_customers ); Customer::set_terse( ); list_customers( );

If you never use package variables, there's no possibility that people using your module could accidentally corrupt its internal state. Developers who are using your code simply cannot access the lexical state variables outside your module, so there is no possibility of incorrectly assigning to them.

Using a subroutine call like Customer::set_terse( ) to store or retrieve module state means that you (the module writer) retain control over how state variables are modified. For example, later in the development cycle it might be necessary to integrate a more general reporting package into the source code:


    package Customer;

    use Perl6::Export::Attrs;

    
# State variables...
my %customer; my %opt; use Reporter; sub set_terse { return Reporter::set_terseness_for({ name => 1 }); } sub list_customers : Export { for my $id (sort keys %customer) { Reporter::report({ name => $customer{$id} }); } return; }

Note that, although there is no longer a $opt{terse} variable inside the package, any code that calls Customer::set_terse( ) will continue to work without change. If $opt{terse} had been a package variable, you would now have to either track down every assignment to it and change that code to call Reporter::set_terseness_for( ), or replace $opt{terse} with a tied variable (see Chapter 19).

Generally speaking, it's bad practice to use variables anywhere in a module's interface. Chapter 17 discusses this point further.

    Previous
    Table of Contents
    Next