Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine

Comment on

( #3333=superdoc: print w/replies, xml ) Need Help??

This kind of assertion demands an example.

I live for examples ;-)

Bob writes a module to manage persistent objects:

package Persist; ... sub uuid { # returns a unique ID for the object. should be # overridden by the subclass }; sub load # load object from persistent store $self->{_change} = 0; }; sub save { my $self = shift; return unless $self->{_change}; # save object to persistent store $self->{_change} = 0; }; sub mark { my $self = shift; # mark and item as changed so it should be saved $self->{_change}++; };

The documented API are the methods uuid, load, save & mark. The hash key _change is an implementation detail.

Now, Mary's writing a module for representing the state of vending machines. She needs the information to persist, finds Persist on CPAN, and decides to use this as her base class.

package VendingMachine; use base qw(Persist); ... sub _loaded { my ($self, $item) = @_; # returns true if $self has a $item loaded # in the machine }; sub vend { my ($self, $item, $money) = @_; die "no items in stock" unless $self->_loaded($item); die "not enough cash" if $money < $item->cost; $self->credit($money)->eject($item); if ($self->{_change} and $money > $item->cost) { $self->give_change($money - $item->cost); }; };

Now, despite sticking to the published API, Mary is going to have a nasty time debugging her code. She'll have to go and read the source for Persist to find out that Bob's implementation detail ($self->{_change} = boolean value indicating whether an object has changed) clashes with her implementation detail ($self->{_change} = object representing available change in the vending machine).

Note this is not deliberate. Mary is not sneaking a look inside Bob's module and using the hash for her own nefarious means - it's an accident.

You get exactly the same issue with "private" methods. What if Bob decides to extend Persist to only load the objects when needed. As part of this he adds a _loaded method that will return true when the object is fully loaded from backing store. Without changing the published API his new version of Persist will break when used with Mary's old VendingMachine module - because it clashes with Mary's _loaded method. Nasty.

There are, of course, ways around these issues. You can use inside out objects to get around problems with attribute clashes. You can use alternate calling styles to get around problems with private methods. However these, and other techniques, all require a fair amount of discipline and expertise to use well.

Good encapsulation is a pretty darn basic feature of an object oriented language. In my opinion its absence hurts perl. It makes it harder to write good modular reusable code. It makes it easier for people to score points in those pointless language flame fests. Good encapsulation should be a basic part of perl (and will be in perl6... huzzah!).

Enough ranting :-) You might also find these exchanges on private attributes and private methods of interest.

In reply to Re^4: Encapsulation through stringification - a variation on flyweight objects by adrianh
in thread Encapsulation through stringification - a variation on flyweight objects by robartes

Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":

  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.
  • Log In?

    What's my password?
    Create A New User
    [Corion]: ambrus: Yeah - we're in that situation too, except that there is no time to do the reorganizing :-/
    [LanX]: ... so my boss started a project with the newest sun servers and invited the traders to come on weekend to test it... and they were so pleased, that they forced him to keep it in production...
    [ambrus]: Corion: sure, this is the long-term plan. The short term is that I have to run this ungodly mess to get results from the new input data today.
    [Corion]: ambrus: Most of our "automation" is tied to process exit codes and a shell pipeline :-\
    [LanX]: ... a week later they realized that one of the databases - which recorded how much the other banks due to this bank - was not correctly plugged
    [ambrus]: Corion: I have no problem with exit codes and shell pipeline. My problem is that the current process requires a lot of manual intervention from me, including editing the source codes.
    [ambrus]: (Also a lot of manual intervention by two or three other co-workers, who do other parts of the process.)
    [ambrus]: Some of the manual part is unavoidable, but not all.
    [choroba]: LanX was there a way to recover the numbers from the remaining information?
    [Corion]: LanX: Ow ;)

    How do I use this? | Other CB clients
    Other Users?
    Others imbibing at the Monastery: (11)
    As of 2017-03-29 11:52 GMT
    Find Nodes?
      Voting Booth?
      Should Pluto Get Its Planethood Back?

      Results (350 votes). Check out past polls.