Re: Is it me or is mod_perl extremely dangerous?
Ben van Staveren <[email protected]>
| Newsgroups | gmane.comp.apache.mod-perl |
|---|---|
| Message-ID | <[email protected]> |
You're also forgetting:
* use strict
* use warnings
HTH...
On 12/07/2011 06:32 PM, Tuomo Salo wrote:
> On Tue, Dec 06, 2011 at 03:55:54PM -0500, Desilets, Alain wrote:
>> package MyClass;
>>
>> my $class_level_attribute;
>>
>> sub new {
>> my ($class) = @_;
>> $self->{instance_level_attribute} = undef;
>> bless $self, $class;
>> return $self;
>> }
>> ------------
>>
>> The idea here is to emulate the concept of "static" (in Java or C++ parlance) class level attributes, i.e., attributes which are tied to the the class itself as opposed to instances of it.
> Please do not do that.
>
> When you use a "my" variable outside a subroutine, you create a variable
> that is completely invisible from anywhere outside of that file. This
> violates some core principles of object oriented programming, and perl
> itself:
>
> * Do not attempt to verify the type of $self. (Tenet #1 from "man perlbot")
> * The object is the namespace. (#6, same source)
> * Don't assume you know the home package of a method (#9)
> * There's more than one way to do it (Perl motto from "man perl")
>
> The first one is violated, since you have a variable that can only be
> seen in your file, and therefore only one type of objects will ever
> be able to see it. Same goes for the third: any method accessing the
> variable is by necessity defined in that very package.
> Violating the second one is the cause for the other two.
>
> The final one is violated, since if someone has decided to do it,
> there is really no way around it.
>
> A demonstration follows.
>
>
> This is the file MyClass.pm, let's say it is downloaded from CPAN.
> It contains a "my" variable at the package level. It also uses the
> variable. (Kind of obvious, since nobody else can see it.)
>
> --------------
> package MyClass;
>
> my $class_level_attribute = "I Am MyClass";
>
> sub new { my ($class) = @_; bless {}, $class; }
> sub output {
> print "My type is @{[ref $_[0]]}";
> print "The attribute is '$class_level_attribute'";
> }
> -------------
>
> Now I really like the way MyClass works, but I would like to change just the
> bit that is in the variable $class_level_attribute. So I create the file
> SubClass.pm:
>
> -------------
> package SubClass;
>
> use base MyClass;
>
> my $class_level_attribute = "I want to be SubClass";
> $::MyClass::class_level_attribute =
> "I want to be SubClass so much that I am ready to break class boundaries";
> -------------
>
> Then I'll try to run it by creating demo.pl
>
> -------------
> #!/usr/bin/perl -Twl
> use strict;
> use lib ".";
>
> use SubClass;
>
> my $object = new SubClass();
> $object->output();
> -------------
>
> ..but I won't be happy:
>
> -------------
> $ chmod +x demo.pl; ./demo.pl
> My type is SubClass
> The attribute is 'I Am MyClass'
> -------------
>
>
> Because I am not in control of MyClass.pm, I cannot make changes to that
> file. If I do, my software will break whenever MyClass.pm is updated.
>
> My other option is to override every subroutine that uses the class level
> attribute. This may also break when the package is updated so that a new
> subroutine starts to access the attribute.
>
> My final option is to copy all functionality from the file to some
> other file; that is, not to use MyClass after all. This is the only
> way I can get the functionality I want. I won't be automatically
> benefiting from any updates to MyClass, but that is the price I have to pay.
>
>
> The correct way to use the scopes for variables is (in my opinion):
>
> - Explicitly global variables ($::Package::variable) in the package's own
> namespace for "final" variables (defaults names of existing instance
> variables, for example) and anything that you absolutely have to save
> to future invocations.
> - Accessors for any instance variables ($object->variable()).
> Never access an instance variable directly, even if you know the
> structure of the object.
> - Lexical variables ("my @args" inside a sub) for everything else,
> and finally:
> - Argument passing ($object->method($variable)) for showing your lexicals
> to other subs.
>
> If you do it this way, then easy things are easy, and hard things are possible.
>
> (bonus: if, in addition, you never "use Exporter" to export anything,
> you'll also get code where every variable name and function call is
> easily traced back to its definition, even without special tools.)
>
> -Tuomo
>
--
Ben van Staveren
phone: +62 81 70777529
email: [email protected]