Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Inside-out objects: encapsulation, spell-check, memory and dumping

by sg (Pilgrim)
on Oct 15, 2007 at 18:41 UTC ( #645000=perlmeditation: print w/replies, xml ) Need Help??

The section on Encapsulation in Chapter 15 of Damian's Perl Best Practices clearly illustrates the several advantages of inside out objects. While I have a sense of the advantages, I lack the knowledge/experience to even summarize them here. However, I suspect that the following twist on that version of inside-out objects still retains the advantages while being simpler (but do not know enough to know for sure).

  • Encapsulation is retained.
  • I suspect the support for spell check in this version is good enough.
  • Regarding memory, this version has one hash per object, but introduces one subroutine per attribute (to support spell checking during run (not compile) time: sub attribute() returns 'attribute'). (I was asked to point out that the update done in response to a comment by chromatic moves the subroutines created to support spell check into members of the hash and so they are repeated for each instance of the object.)
  • I haven't written too many modules and so have no clue if the addition of a sub to dump attributes is sufficient to overcome the "only serious drawback of inside-out objects".

Update: Regarding performance, my inclination is to put the spell-check subs (sub attribute() returning 'attribute') in a BEGIN block under the assumption that the compiler will optimize away these trivial subs.

Update: Modified code to respond to comment by chromatic.

Update - Psychological Aspect: I now understand why I had trouble using the original scheme in PBP. While using that scheme, my mind had to deal with multiple attributes -- there wasn't any single object for my mind to use. The Package name represents a family of potential objects; and the object itself doesn't provide anything to think about since it is just a meaningless un-named scalar; so my mind had to deal with the multitude of "attribute_of" (which overloaded the mind to the point of being almost paralyzing). In the present scheme, my mind works with a single, meaningful hash.

{ package Spellaid; # nothing significant about this name use warnings; use strict; use Scalar::Util qw(refaddr); use Data::Dumper; our $VERSION = '0.1.0'; my %stuff_of; # single hash per object my @vars = qw(name task); { no strict qw(refs); # all the attributes foreach my $var ( @vars ) { =for old_1 *{$var} = sub { return $var; }; # the spell-checker! =cut *{'set_'.$var} = sub { ${$stuff_of{refaddr $_[0]}}{$var} = $_[1 +];}; *{'get_'.$var} = sub { return ${$stuff_of{refaddr $_[0]}}{$var} +;} } } sub new { my($class, @args) = @_; my $obj = bless \do{my $anon_scalar}, $class; my $c; ${$c}{name} = 'the name'; ${$c}{task} = 'the task'; # begin added after commenting out "for old_1" { no strict qw(refs); foreach my $var ( @vars ) { ${$c}{'_'.$var} = sub { return $var; }; } } # end added $stuff_of{refaddr $obj} = $c; return $obj; } =for old_1 sub a_complex_sub { my ($self, $new_name) = @_; # deep inside this complex sub, we need the name ... # issue is to catch mis-spelling of the hash key "name" # print "nom: [", ${$stuff_of{refaddr $self}}{name()}, "]\n"; # next line will fail during run time (_not_ compile time) # but does fail with a Kaboom! # Undefined subroutine &Spellaid::nmae called at <file> <li +ne> # So a good/explicit Kaboom!, albeit a late one. print "nom: [", ${$stuff_of{refaddr $self}}{nmae()}, "]\n"; } =cut # begin added after commenting out "for old_1" sub a_complex_sub { my ($self, $new_name) = @_; # deep inside this complex sub, we need the name ... # the correct way would be to extract the name via: # # my $whatever_for_name = ${$stuff_of{refaddr $self}}{_name}(); # # Typo of whatever_for_name will be caught at compile time, # but we are interested in typos of the attribute "name" # So suppose we make a typo "nmae": my $whatever_for_name = ${$stuff_of{refaddr $self}}{_nmae}(); # the preceding line fail during run time (_not_ compile time) # but failure message will show precisely what went wrong # and where exactly. So we do have a good/explicit # Kaboom!, albeit a late one. # how a_complex_sub() would use name: print "nom: [", ${$stuff_of{refaddr $self}}{$whatever_for_name} +, "]\n"; } # end added sub dump_stuff { print Dumper($stuff_of{refaddr $_[0]}); } 1 } my $s_obj = Spellaid->new(); $s_obj->set_name('the new name'); # set print "task: [",$s_obj->get_task(), "]\n"; # get $s_obj->a_complex_sub(); # spell check $s_obj->dump_stuff(); # data dumper __END__ for old_1 output: # with misspelling task: [the task] Undefined subroutine &Spellaid::nmae called at <file> <line> # without misspellin task: [the task] nom: [the new name] $VAR1 = { 'name' => 'the new name', 'task' => 'the task' }; output after commenting out old_1: # with misspelling task: [the task] Use of uninitialized value in subroutine entry at <file> <line> Can't use string ("") as a subroutine ref while "strict refs" in u +se at <file> <line> # without misspellin task: [the task] nom: [the new name] $VAR1 = { '_name' => sub { "DUMMY" }, 'name' => 'the new name', '_task' => sub { "DUMMY" }, 'task' => 'the task' };

  • Comment on Inside-out objects: encapsulation, spell-check, memory and dumping
  • Download Code

Replies are listed 'Best First'.
Re: Inside-out objects: encapsulation, spell-check, memory and dumping
by Zaxo (Archbishop) on Oct 16, 2007 at 06:36 UTC
    Regarding performance, my inclination is to put the spell-check subs (sub attribute() returning 'attribute') in a BEGIN block under the assumption that the compiler will optimize away these trivial subs.

    Subs are always compiled in BEGIN mode, exclusive of eval tricks. AFAIK, they are only optimized away with a "()" prototype and a constant return value.

    After Compline,
    Zaxo

      Anonymous subroutines are normally generated at runtime.

      Be well,
      rir

Re: Inside-out objects: encapsulation, spell-check, memory and dumping
by chromatic (Archbishop) on Oct 15, 2007 at 23:34 UTC

    Namespaced functions may be at odds with inherited (and especially overridden) methods.

      chromatic, How about the following modifications?:

      Update: incorporated the modifications into the original code; commented out old stuff via

      =for old_1 =cut
      and added new stuff via "begin-end" markers:
      # begin added after commenting out "for old_1" # end added

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlmeditation [id://645000]
Approved by Arunbear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others lurking in the Monastery: (5)
As of 2022-12-04 21:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?