Beefy Boxes and Bandwidth Generously Provided by pair Networks
Think about Loose Coupling

Re^3: fields alternative?

by stvn (Monsignor)
on Apr 06, 2011 at 14:02 UTC ( #897793=note: print w/replies, xml ) Need Help??

in reply to Re^2: fields alternative?
in thread fields alternative?

You have explained what he is trying to accomplish, but I actually more was looking to know why he wants to do this. This kind of access control is, in my opinion, a social issue that should not be solved with technology. But since I actually don't know the motivation, I might be wrong on that.

Replace fields with another object system that detect access to a non-declared object variable (run-time or compile-time).

This being perl, there is always a way to access and manipulate object fields no matter what technique you use (yes, even Inside-Out objects can be reached with the right level of black magic). So no matter what features I show you, there is always a way around it for someone who is motivated enough.

Is there an perl object system / framework that supports the above requirements? Moose and Mouse have been considered and fail the last requirement.

Moose has read-only accessors and if you pass unknown attributes to the constructor they will not be added to the underlying object instance. There is also the MooseX::StrictConstructor module which makes passing those unknown attributes an error. Honestly, this, along with some tight type constraints should be enough to validate the data coming from JSON::XS and being passed to the Moose constructor, which seems to be what your goal is.

That all said, none of this will protect the underlying instance structure. But I really think you need to ask yourself, is my environment so hostile that I actually need to protect the instance structure? Can I not enforce things via the accessors and object interface?

Now, if you are really dead set on actually doing this, Moose does provide you the features you need (I suspect Mouse can do this too, but I don't know the actual incantations to do so). So here is the code that you would need in your class BUILD method (or in a common base class if you want, it will still work correctly).

package LockedBox; use Moose; use MooseX::StrictConstructor; use Hash::Util qw[ lock_keys lock_value ]; has bar => ( is => 'ro' ); sub BUILD { my $self = shift; lock_keys( %$self ); foreach my $attr ( $self->meta->get_all_attributes ) { lock_value( %$self, $attr->name ) } }
This basically just locks the instance, then locks each of the values that are defined via Moose. This means that when you create an instance with Moose like so...
my $foo = LockedBox->new( bar => 10 );
You will first get the normal Moose constructor behavior which is to only use the keys that are defined. But since I actually added MooseX::StrictConstructor into this, that means that if you were to do this ...
my $foo = LockedBox->new( bar => 10, baz => 100 );
The code would fail with an exception.

Next, since we locked all the hash keys, if someone were to try and do this ..

$foo->{baz} = 20;
It would die with the error "Attempt to access disallowed key 'baz' in a restricted hash" which is because of Hash::Util::lock_keys.

And lastly, since lock_keys only prevents you from adding new keys but not altering existing ones, we found all the valid keys in Moose and locked those values with Hash::Util::lock_values, which means that this code ...

$foo->{bar} = 20;
Will throw the following error "Modification of a read-only value attempted".

Now, in my opinion, all this is overkill. If the users of your class are violating the encapsulation, then you have a real problem with those users and your documentation should point out such incorrect usage. If these other users are actually co-workers, then you have a social problem on your hands and one that needs to be fixed socially and not technically. In the end, all some jerk needs to do is use Hash::Util to unlock the keys/values and they can get at that, but this really is an explicit violation and should be dealt with.


Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://897793]
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (7)
As of 2018-03-20 08:43 GMT
Find Nodes?
    Voting Booth?
    When I think of a mole I think of:

    Results (248 votes). Check out past polls.