Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-08-03 Thread Michael Zedeler

On 2010-07-31 20:23, Carl Mäsak wrote:

* Today we discovered that it's possible to break encapsulation by
detaching a method from an object of one class, and calling that
method on an object of another class. Which means that breaking the
encapsulation of a foreign class is as easy as creating a custom class
with all of the same private attributes, and with a method to print
(or otherwise reveal) them.

* It is my feeling that such encapsulation-breakage shouldn't be
allowed. Do you agree, p6l?
   
I don't really agree. The way OOP is implemented in perl 5 allows 
breaking encapsulation on many different levels, but I believe this has 
turned out to be a strength, since it allows you to use in those (very 
rare?) cases where it is needed.


When I found that all objects in perl 6 had fields, I was kind of put 
off, since it looked to Java-ish. What saves the spirit of perl is that 
people are still free to hack away (and then there are such roles as 
postcircumflex that reintroduces the very terse syntax, perl 5 is known 
for, avoiding the dot-hell of Java).


I believe we have a much larger task at hand, which is to write 
documentation that educates newcomers to use the right tools for the 
right job. I'd never recommend monkeypatching to a rookie programmer (or 
those silly .* and .+ method invocators) and I believe we owe people 
outside the perl community to explain the /intent/ behind the different 
constructs.


Regards,

Michael.



Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-08-03 Thread Carl Mäsak
jnthn++ points out in meatspace that the invocant parameter has a
constraint (by spec but not in Rakudo), which will carry over to the
new class. Which means that only objects of child classes will
signature-bind anyway.

// Carl


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-08-02 Thread Moritz Lenz
Carl Mäsak wrote:
 * It is my feeling that such encapsulation-breakage shouldn't be
 allowed. Do you agree, p6l?

Time may proof me wrong, but I think it's not such a big issue.

Note that encapsulation can be broken in many ways already, wither with
MONKEY_TYPING or by using introspection techniques (which aren't fully
specced yet, but they *will* exist. In case of doubt you can just parse
.perl output).

 * If it isn't allowed, which of the two steps is disallowed?
 *Detaching* a method containing references to private accessor slots
 (thereby extending the syntactic restriction of no private accessors
 outside of the class block), or *attaching* an anonymous method to an
 object belonging to a different class than the one from which it was
 detached (thereby by necessity having to complicate anonymous methods
 somewhat)?

There's a third possiblity - $!foo being bound to the $!foo attribute of
the lexically enclosing class at compile-time. So that re-attaching
methods make them still refer to the old attribute. Not sure if it's a
good idea, just food for thought.

Cheeers,
Moritz
-- 
Moritz Lenz
http://perlgeek.de/ |  http://perl-6.de/ | http://sudokugarden.de/


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-08-02 Thread Carl Mäsak
Carl (), Moritz ():
 * If it isn't allowed, which of the two steps is disallowed?
 *Detaching* a method containing references to private accessor slots
 (thereby extending the syntactic restriction of no private accessors
 outside of the class block), or *attaching* an anonymous method to an
 object belonging to a different class than the one from which it was
 detached (thereby by necessity having to complicate anonymous methods
 somewhat)?

 There's a third possiblity - $!foo being bound to the $!foo attribute of
 the lexically enclosing class at compile-time. So that re-attaching
 methods make them still refer to the old attribute. Not sure if it's a
 good idea, just food for thought.

That's indeed what Stefan proposed as well, and what I currently
believe to be the right way of looking at this. The fact that you
don't mention an error condition in connection to the accessing of the
old attribute makes me realize yet another thing:

class Parent { has $!a; method foo { say $!a } }
class Child is Parent { has $!a }

my $child = Child.new( :a(42), Parent{ :a(5) } );
my $parent-foo = Parent.^can('foo');
$child.$parent-foo(); # works, prints 5\n

Or, in words, just because one detaches/re-attaches a method doesn't
automatically mean that private attribute accesses result in an error.
Specifically, they don't in child classes.

// Carl


Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-07-31 Thread Carl Mäsak
Here's a case where a bug report stumped me and made me feel I'm
missing something:

 http://rt.perl.org/rt3/Ticket/Display.html?id=69260

I'll give a somewhat summarized version of the above page, which
gradually turns into a set of questions and not enough answers:

* It has been decided that attribute slots of the type $!foo are only
allowed *syntactically* within the class block that declares them.
(The exception to this, I guess, is the 'trusts' directive.) But this
means that something like this anonymous method

my $reveal-foo = method { say $!foo }

isn't allowed. I think that's good, because it would provide a very
easy way to break encapsulation of an object; just call
$object.$reveal-foo() on it.

* Today we discovered that it's possible to break encapsulation by
detaching a method from an object of one class, and calling that
method on an object of another class. Which means that breaking the
encapsulation of a foreign class is as easy as creating a custom class
with all of the same private attributes, and with a method to print
(or otherwise reveal) them.

* It is my feeling that such encapsulation-breakage shouldn't be
allowed. Do you agree, p6l?

* If it isn't allowed, which of the two steps is disallowed?
*Detaching* a method containing references to private accessor slots
(thereby extending the syntactic restriction of no private accessors
outside of the class block), or *attaching* an anonymous method to an
object belonging to a different class than the one from which it was
detached (thereby by necessity having to complicate anonymous methods
somewhat)?

I only see those three options:

a. Allow this form of encapsulation breakage.
b. Disallow detaching of certain methods.
c. Disallow attaching of certain anonymous methods.

I must confess I don't particularly like either option. I'm by no
means an OO expert. It would be interesting to hear your views on
this.

// Carl


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-07-31 Thread Brandon S Allbery KF8NH
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 7/31/10 14:23 , Carl Mäsak wrote:
 a. Allow this form of encapsulation breakage.
 b. Disallow detaching of certain methods.
 c. Disallow attaching of certain anonymous methods.
 
 I must confess I don't particularly like either option. I'm by no
 means an OO expert. It would be interesting to hear your views on
 this.

The whole concept of detaching and attaching methods seems suspect to me; in
particular, attaching a method from a class not declared to be related reeks
of monkey patching.  As such, I'd only allow it when monkey patching is enabled.

- -- 
brandon s. allbery [linux,solaris,freebsd,perl]  allb...@kf8nh.com
system administrator  [openafs,heimdal,too many hats]  allb...@ece.cmu.edu
electrical and computer engineering, carnegie mellon university  KF8NH
-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAkxUbRAACgkQIn7hlCsL25URzACfeQwHqlQWs4IL6RdSCkkI1inr
BasAoM0LyLl19dylqoOcMjCfk3kvC9j3
=FyAF
-END PGP SIGNATURE-


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-07-31 Thread Stefan O'Rear
On Sat, Jul 31, 2010 at 08:23:29PM +0200, Carl Mäsak wrote:
 * It has been decided that attribute slots of the type $!foo are only
 allowed *syntactically* within the class block that declares them.
 (The exception to this, I guess, is the 'trusts' directive.) But this
 means that something like this anonymous method
 
 my $reveal-foo = method { say $!foo }
 
 isn't allowed. I think that's good, because it would provide a very
 easy way to break encapsulation of an object; just call
 $object.$reveal-foo() on it.

There is no $!foo.  There is only $!Class::foo, and $!foo is a lexically
scoped alias to it.  This is necessary to allow privacy from your children
to work:

class Class {
has $!foo;  # the mere existance of $!foo is an implementation detail
}

class SubClass is Class {
has $!foo;  # hey why doesn't this work?
}

So $reveal-foo can't be defined because $!foo isn't even in scope.

 * Today we discovered that it's possible to break encapsulation by
 detaching a method from an object of one class, and calling that
 method on an object of another class. Which means that breaking the
 encapsulation of a foreign class is as easy as creating a custom class
 with all of the same private attributes, and with a method to print
 (or otherwise reveal) them.

Calling such methods should fail, because the $!OtherClass:: attributes
don't exist even if the shortnames are the same.

 * It is my feeling that such encapsulation-breakage shouldn't be
 allowed. Do you agree, p6l?

It's not.

 * If it isn't allowed, which of the two steps is disallowed?
 *Detaching* a method containing references to private accessor slots
 (thereby extending the syntactic restriction of no private accessors
 outside of the class block), or *attaching* an anonymous method to an
 object belonging to a different class than the one from which it was
 detached (thereby by necessity having to complicate anonymous methods
 somewhat)?
 
 I only see those three options:
 
 a. Allow this form of encapsulation breakage.
 b. Disallow detaching of certain methods.
 c. Disallow attaching of certain anonymous methods.
 
 I must confess I don't particularly like either option. I'm by no
 means an OO expert. It would be interesting to hear your views on
 this.

Perl philosophy has always been it's not that I have a shotgun, you just
weren't invited, so stay out of my living room.  I don't see any reason for
Perl 6 to break with this - encapsulation should be about helping the
programmer, not helping the sysadmin maintain system security.

-sorear


signature.asc
Description: Digital signature


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-07-31 Thread Stefan O'Rear
On Sat, Jul 31, 2010 at 02:36:02PM -0400, Brandon S Allbery KF8NH wrote:
 On 7/31/10 14:23 , Carl Mäsak wrote:
  a. Allow this form of encapsulation breakage.
  b. Disallow detaching of certain methods.
  c. Disallow attaching of certain anonymous methods.
  
  I must confess I don't particularly like either option. I'm by no
  means an OO expert. It would be interesting to hear your views on
  this.
 
 The whole concept of detaching and attaching methods seems suspect to me; in
 particular, attaching a method from a class not declared to be related reeks
 of monkey patching.  As such, I'd only allow it when monkey patching is 
 enabled.

Methods are just functions.

$object.$method(@args)

is simply sugar for

$method($object, @args)

so disallowing it is not quite that simple.

-sorear


signature.asc
Description: Digital signature


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-07-31 Thread Brandon S Allbery KF8NH
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA1

On 7/31/10 14:38 , Stefan O'Rear wrote:
 On Sat, Jul 31, 2010 at 02:36:02PM -0400, Brandon S Allbery KF8NH wrote:
 The whole concept of detaching and attaching methods seems suspect to me; in
 particular, attaching a method from a class not declared to be related reeks
 of monkey patching.  As such, I'd only allow it when monkey patching is 
 enabled.
 
 Methods are just functions.
 
 $object.$method(@args)
 
 is simply sugar for
 
 $method($object, @args)
 
 so disallowing it is not quite that simple.

That would seem to make it worse (type conformability on the first
positional parameter; does declaring a method not implicitly declare the
type of its positional parameter to be the class that declared it, or a
subclass thereof?) --- but I think you addressed that in your other response.

- -- 
brandon s. allbery [linux,solaris,freebsd,perl]  allb...@kf8nh.com
system administrator  [openafs,heimdal,too many hats]  allb...@ece.cmu.edu
electrical and computer engineering, carnegie mellon university  KF8NH
-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.10 (Darwin)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEUEARECAAYFAkxUbtAACgkQIn7hlCsL25WOkwCgvq2SevYoVtGWSio0q7lVDxWy
Qt8AmM8FijA51vxGjylUwuCq1+zpF9k=
=XroU
-END PGP SIGNATURE-


Re: Breaking encapsulation by detaching a private-variable-accessing method from one object and calling it on another

2010-07-31 Thread Carl Mäsak
Carl (), sorear ():
 * It has been decided that attribute slots of the type $!foo are only
 allowed *syntactically* within the class block that declares them.
 (The exception to this, I guess, is the 'trusts' directive.) But this
 means that something like this anonymous method

     my $reveal-foo = method { say $!foo }

 isn't allowed. I think that's good, because it would provide a very
 easy way to break encapsulation of an object; just call
 $object.$reveal-foo() on it.

 There is no $!foo.  There is only $!Class::foo, and $!foo is a lexically
 scoped alias to it.  This is necessary to allow privacy from your children
 to work:

 class Class {
    has $!foo;  # the mere existance of $!foo is an implementation detail
 }

 class SubClass is Class {
    has $!foo;  # hey why doesn't this work?
 }

 So $reveal-foo can't be defined because $!foo isn't even in scope.

Thanks, that's an excellent way to explain this. It also provides the
answer to this whole thread:

class A {
has $!x;
}

class B {
has $!x;
method foo { say $!x } # really 'say $!B::x'
}

my $b-foo = B.^can(foo);
A.new( :x(42) ).$b-foo(); # doesn't work, can't access $!B::x from A

This solution is a fourth one that I didn't see, and the first one that I like:

d. Disallow illegally accessing a private attribute slot that isn't yours.

It also incidentally answers a random thought I had today after
posting my original email: Hey, jnthn talked about implementing
attribute accesses as array accesses rather than hash accesses -- how
the heck will that work if methods can be detached and re-attached to
objects of a different class? With $!foo really meaning
$!MyClass::foo it makes a lot more sense.

// Carl