You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 5 Next »

Perl provides no mechanism to hide variables or functions. While it provides mechanisms such as my() that limit the scope of variables, it does nothing to prevent code from accessing any variable or method that is avaialble and dereferenceable from its current scope.

By convention, packages may indicate that a method or variable is not to be used outside the class by prefixing the method or variable name with an underscore (_) [Conway 05]. Perl provides no inherent enforcement of this convention; however, it is followed by many modules in CPAN and other developers. This convention must not be violated.

Noncompliant Code Example

This noncompliant code example provides a Car package that registers cars and keeps track of all cars that it creates.

{
  package Car;

  my %_all_cars;

  sub new {
    my ($class, $type) = @_;
    my $self = {type=>$type};
    bless $self, $class;
    $_all_cars{$self} = 1;
    return $self;
  };

  sub destroy {
    delete $_all_cars{shift};
  };

  sub type {
    my $self = shift;
    return $$self{type};
  }

  sub _get_all_cars {
    return %_all_cars;
  }
}


my $mine = Car->new("Transam");
my $type = $mine->type();
print "I drive a $type.\n";
my $yours = Car->new("Corvette");
$type = $yours->type();
print "You drive a $type.\n";

my %cars = Car::_get_all_cars();
my @all = keys( %cars);
my $count = $#all + 1;
print "There are $count cars on the road.\n";

This program behaves as expected, correctly reporting 2 cars on the road. However, it clearly violates encapsulation, because the _get_all_cars() method is considered private within the Car class.

Compliant Solution

This compliant solution adds a public method and invokes it instead of any private method.

{
  package Car;

  my %_all_cars;

  sub count_cars {
    my @all = keys( %_all_cars);
    return 1 + $#all;
  }

  # ... other methods of Car
}

# ...
my $count = Car::count_cars();
print "There are $count cars on the road.\n";

Exceptions

OOP31:EX0: A class may access private subroutines in classes it is inherited from.

OOP31:EX1: This rule does not apply to classes or modules that do not obey this convention. For instance, the POSIX package provides an API to the system calls endorsed by the POSIX standard. Many of these calls begin with _ but are not meant to be private.

Risk Assessment

Using deprecated or obsolete classes or methods in program code can lead to erroneous behavior.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

OBJ31-PL

info

probable

medium

P12

L1

Automated Detection

Tool

Diagnostic

Perl::Critic

Subroutines::ProtectPrivateSubs

 

Variables::ProtectPrivateVars

Bibliography

[Conway 05]
[CPAN] Elliot Shank, Perl-Critic-1.116 Subroutines::ProtectPrivateSubs, Variables::ProtectPrivateVars
[CPAN] Ragwitz, Florian, POSIX
[Open Group 08]


  • No labels