Perl Best Practices

15.4. Restricted Hashes

Don't use restricted hashes.

Restricted hashes were developed as a mechanism to partially replace pseudohashes. An ordinary hash can be converted into a restricted hash simply by calling one or more of the lock_keys( ), lock_value( ), or lock_hash( ) subroutines provided by the Hash::Util module, which is standard in Perl 5.8 and later.

If the keys of a hash are locked with lock_keys( ), that hash is prevented from creating entries for keys other than the keys that existed at the time the hash keys were locked. If a hash value is locked with lock_value( ), the value for that particular hash entry is made constant. And if the entire hash is locked with lock_hash( ), neither its keys nor their associated values can be altered.

If you build a hash-based object and then lock its keys, no-one can accidentally access $self->{Name} when the object's attribute is supposed to be in $self->{name} instead. That's a valuable form of consistency checking. If you also lock the values before the constructor returns the object, then no-one outside the class can mess with the contents of your object, so you also get encapsulation. And as they're still just regular hashes, you don't lose any appreciable performance.

The problem is that like the now-deprecated pseudohashes, restricted hashes still offer only voluntary security[*]. The Hash::Util module also provides unlock_keys( ), unlock_value( ), and unlock_hash( ) subroutines, with which all that pesky consistency checking and annoying attribute encapsulation can be instantly circumvented.

[*] You know, the type of safety measures that are effective only against well-meaning, law-abiding folk, for whom they're not actually needed. Like airport security.

Категории