Devel::EnforceEncapsulation - Find access violations to blessed objects
package BankAccount; sub new { my $pkg = shift; return bless {}, $pkg; } sub balance { my $self = shift; return $self->{balance}; } # ... etc. ... package main; Devel::EnforceEncapsulation->apply_to('BankAccount'); my $acct = BankAccount->new(); print $acct->balance(),"\n"; # ok print $acct->{balance},"\n"; # dies
Copyright 2014 Chris Dolan, <cpan@chrisdolan.net> Copyright 2006 Clotho Advanced Media, Inc., <cpan@clotho.com>
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Encapsulation is the practice of creating subroutines to access the properties of a class instead of accessing those properties directly. The advantage of good encapsulation is that the author is permitted to change the internal implementation of a class without breaking its usage.
Object-oriented programming in Perl is most commonly implemented via blessed hashes. This practice makes it easy for users of a class to violate encapsulation by simply accessing the hash values directly. Although less common, the same applies to classes implemented via blessed arrays, scalars, filehandles, etc.
This module is a hack to block those direct accesses. If you try to access a hash value of an object from it's own class, or a superclass or subclass, all goes well. If you try to access a hash value from any other package, an exception is thrown. The same applies to the scalar value of a blessed scalar, entry in a blessed array, etc.
To be clear: this class is NOT intended for strict enforcement of encapsulation. If you want bullet-proof encapsulation, use inside-out objects or the like. Instead, this module is intended to be a development or debugging aid in catching places where direct access is used against classes implemented as blessed hashes.
To repeat: the encapsulation enforced here is a hack and is easily circumvented. Please use this module for good (finding bugs), not evil (making life harder for downstream developers).
Add strict encapsulation to an existing $other_pkg. The encapsulation changes only apply to instances created after the call.
$other_pkg
The optional policy argument allows you to change the response to an illegal access. By default the policy is croak, which invokes Carp::croak(). The alternative is carp which invokes Carp::carp() instead.
policy
croak
Carp::croak()
carp
Carp::carp()
Remove any encapsulation previously set by apply_to(). This does not affect instances created before this call.
apply_to()
Class::Privacy is a very similar implementation that is, in general, stricter than this module. The key differences:
D::E applies externally post-facto; C::P from inside the code.
D::E allows access from sub/superclasses; C::P does not (deliberately!).
D::E supports all dereferencers from overload.pm; C::P supports %, @, $, and &.
%
@
$
&
D::E allows access from anything in the same package; C::P allows access only from matching package AND file.
Class::InsideOut, Object::InsideOut and Class::Std are all implementations of "inside-out" objects, which offer a stricter encapsulation style at the expense of a less familiar coding style.
(Fatal) You tried to access a hash property directly instead of via an accessor method. The %s values are the object and caller packages respectively.
%s
We care about code quality. This distribution complies with the following quality metrics:
Perl::Critic v0.20 passes
Devel::Cover test coverage at 100%
Pod::Coverage at 100%
Test::Spelling passes
Test::Portability::Files passes
Test::Kwalitee passes
The regression tests do not cover blessed code or glob references.
Any other issues: http://rt.cpan.org/Dist/Display.html?Queue=Devel-EnforceEncapsulation
Clotho Advanced Media Inc., cpan@clotho.com
Maintainer: Chris Dolan
This idea, and the original source code, came from Adrian Howard via Curtis "Ovid" Poe on http://www.perlmonks.org/?node_id=576707|perlmonks.org. Adrian has authorized me to release a variant of his code under the Perl license.
Joshua ben Jore provided crucial improvements that simplified yet generalized the implementation. This module would not be half as useful without his contributions. http://use.perl.org/comments.pl?sid=33253&cid=50863
Ricardo Signes contributed the {policy = 'carp'}> feature (with tests!). http://rt.cpan.org/Ticket/Display.html?id=22024
{policy =
To install Devel::EnforceEncapsulation, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Devel::EnforceEncapsulation
CPAN shell
perl -MCPAN -e shell install Devel::EnforceEncapsulation
For more information on module installation, please visit the detailed CPAN module installation guide.