http://www.perlmonks.org?node_id=247509


in reply to Re^2: Encapsulation through stringification - a variation on flyweight objects
in thread Encapsulation through stringification - a variation on flyweight objects

The problem with the "normal" perl OO model is that you can interfere accidentally with "private" methods and attribute.

This kind of assertion demands an example. I humbly await your response.

------
We are the carpenters and bricklayers of the Information Age.

Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

  • Comment on Re3: Encapsulation through stringification - a variation on flyweight objects

Replies are listed 'Best First'.
Re: Encapsulation through stringification - a variation on flyweight objects
by Abigail-II (Bishop) on Apr 02, 2003 at 15:45 UTC
    package Foo; sub new {return bless {} => shift} sub oogle {my $shelf = shift; $self -> {key} = shift} package Bar; our @ISA = qw /Foo/; sub gurgle {my $self = shift; $self -> {key} = shift;}

    Both Bar and Foo happen to use the same key, because there's no encapsulation.

    Perl na(t)ive OO model stinks, because you've to work hard to get encapsulation. (Note: I'm not saying I want private stuff, I just want encapsulation of the implementation). I do not know a common language whose OO model sucks more than Perls.

    Abigail

      Ok. I'm missing something when it comes to encapsulation. Why on earth would you want to prevent Bar from accessing attributes it inherited from Foo? That's always been something I didn't understand in C++ - why private attributes were not inherited ...

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        I don't know about your coding style, but I prefer to use namespaces and lexically scoped variables, to avoid ACCIDENTAL cluttering of values.

        But I concur. The entire concept of namespaces and lexical variables is just stupid. We should just put all our variables and subs in the main namespace.

        Abigail

Re^4: Encapsulation through stringification - a variation on flyweight objects
by adrianh (Chancellor) on Apr 03, 2003 at 00:24 UTC

    This kind of assertion demands an example.

    I live for examples ;-)

    Bob writes a module to manage persistent objects:

    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.

    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.

      Let me get this straight: The basic concern with the lack of truly private attributes/methods has to do with the fact that you may only want to inherit the interface, not the object implementation. You want to know that "I am a Foo" and "Foos can bark", so "I can bark" and not have to think anymore about it. Plus, you want to know that by using Foo's capability to bark, you have not harmed your capability to develop any which way you want.

      Does that accurately sum it up?

      ------
      We are the carpenters and bricklayers of the Information Age.

      Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

      Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.

        Pretty much.

        It might be useful to separate out the concepts of encapsulation and data-hiding.

        A package global variable is encapsulated within it's package (declaring $Foo::fribble does not interfere with $Bar::fribble), but it's not hidden (you can access $Foo::fribble from the Bar package by explicitly stating the package name).

        Contrast this with a lexical variable which is both encapsulated within its scope and hidden from other code (ignoring closures and PadWalker :-)

        Language support for the encapsulation of class state and behaviour is, for me, the big lack in perl5 OO.

        Using the default perl OO style of key/value pairs in a hashref to represent an objects state gives you a single namespace for attributes across all the classes that the object belongs to. The same applies to methods. Using the normal $self->method style means you have a single namespace for methods across all the classes the object belongs to. They are not encapsulated.

        Imagine having to develop functional/procedural perl modules without packages. You would have to make sure that every module used different subroutine names and different global variables. While the situation isn't so desperate in the perl5 OO world, because deep inheritence hierarchies are rare, it can still be a problem.

        In perl5 you cannot encapsulate the implementation details of your class from its public interface easily - its complex (e.g. lexical closures), non-obvious (e.g. inside out objects) and can involve a lot of developer overhead (e.g. prefixing all attributes with the package name and remembering to call all private methods as subroutines).

        This is why I'm looking forward to things like submethods in perl6 ;-)

Re: Re3: Encapsulation through stringification - a variation on flyweight objects
by fruiture (Curate) on Apr 02, 2003 at 19:20 UTC

    Perhaps these examples demonstrate it, although German, they should be understandable. It's kind of a summary of that discussion some time ago.

    --
    http://fruiture.de