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]
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.