Beefy Boxes and Bandwidth Generously Provided by pair Networks
We don't bite newbies here... much
 
PerlMonks  

Re^2: fields alternative?

by andreas1234567 (Vicar)
on Apr 06, 2011 at 04:56 UTC ( #897661=note: print w/ replies, xml ) Need Help??


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

(I have spoken with bannaN and his problem seems to be:)

  • fields and JSON::XS don't work together. fields and JSON::PP do work toghether, but JSON::PP is too slow for his application.
  • fields has some nice properties he would like to preserve, such as to catch common programming errors, e.g. accessing a non-declared object variable (e.g. $p->{a})
His strategy is:
  • Create objects in perl and dump object content with JSON::XS
  • Replace fields with another object system that detect access to a non-declared object variable (run-time or compile-time).
Is there an perl object system / framework that supports the above requirements? Moose and Mouse have been considered and fail the last requirement.

--
No matter how great and destructive your problems may seem now, remember, you've probably only seen the tip of them. [1]


Comment on Re^2: fields alternative?
Download Code
Re^3: fields alternative?
by stvn (Monsignor) on Apr 06, 2011 at 14:02 UTC

    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.

    -stvn

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: note [id://897661]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2014-09-21 10:34 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    How do you remember the number of days in each month?











    Results (168 votes), past polls