Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Re^2: Beyond Inside-Out

by Anno (Deacon)
on May 30, 2007 at 11:33 UTC ( #618155=note: print w/replies, xml ) Need Help??


in reply to Re: Beyond Inside-Out
in thread Beyond Inside-Out

The purpose of this module (Alter) is to:

  • Allow arbitrary subclassing of any object without interfering with its super or subclasses

    Yes.

  • Only allow access to properties via methods, instead of accessing them directly via (eg) hash keys

    No. Unlike inside-out, Alter doesn't organize object data in hashes keyed by id. Each class sees the object as a single reference (type of its choice). It's up to the class to organize the data further.

  • Automate garbage collection

    Yes. And thread-cloning.

    The mechanism is actually even simpler than your sketch.

    Assume there is a function of a single variable _corona($obj). For each object it produces a single hash(ref) that is autovivified empty on the first call, and stays with the object for its lifetime. This function is not caller-sensitive. The caller-dependent behavior of Alter::ego() can then be described in Perl (code untested):

    package Alter; sub ego { my $obj = shift; my $corona = _corona($obj); my $class = caller; return $corona->{ $class} if exists $corona{$class} ); $corona{ $class} = shift || {}; }
    Thus the mechanism is: Equip each object (magically) with one hidden hash, its corona. Use that hash, keying by class name, to store the individual alter ego of the object for each class.

    The technique does nothing to catch misspelled attribute names, it doesn't know of attributes. It brings back the (good or bad, but old) days when "an object is nothing but a reference", only this time an individual one for every class.

    To your questions, skipping the one about Tye's concern.

  • I don't understand why garbage collection works...

    Garbage collection and thread cloning are magic-aware, that's "all" there's to it (which is a lot). That makes magic a good choice for object data. It's out of band to normal Perl code (like the id-keyed hashes of inside-out), but Perl knows about magic and deals with it.

  • You mention of problem of serialization. Your solution doesn't help with this - you still need to provide Storable hooks for that, no?

    Yes, you need hooks, but with Alter it is easy to provide one generic set of hooks that any class can inherit or even import. All it has to do is give the corona (a normal Perl hash) to the dumper, or to restore the corona of a given object. The equivalent is harder to do with inside-out objects where the object itself (all the dumper gets to see) bears no traces of its data.

    It's like this: Primitive old-style objects tatoo their data on their skin, one tatoo over the other if classes demand. The highly sophisticated inside-out objects store their data in bank vaults on small lexical islands, each in a different class. Hard to trace in case of a sudden death. Alter-stype objects collect their data in a secret pouch with neat compartements for each class, always together, but easy to keep apart.

    Anno

  • Replies are listed 'Best First'.
    Re^3: Beyond Inside-Out
    by kyle (Abbot) on May 30, 2007 at 16:29 UTC

      Thus the mechanism is: Equip each object (magically) with one hidden hash, its corona. Use that hash, keying by class name, to store the individual alter ego of the object for each class.

      This reminds me of another "make inheritance work" technique I'd heard of. Every object is a hash ref (as usual), but every class has their own key into it. Basically every object looks like the $corona in clinton's description. The Alter advantage over that method is mainly privacy. The various classes sharing space can't meddle with each other's attributes. If ego is changed to address tye's concern (so that a class can specify its own name), I'm guessing that Alter loses that advantage too. At that point, you might as well write a base class with ego in it.

        ...reminds me of another "make inheritance work" technique I'd heard of. Every object is a hash ref (as usual), but every class has their own key into it. Basically every object looks like the $corona in clinton's description. The Alter advantage over that method is mainly privacy.

        No, the point isn't privacy, it's being out of band. The corona is attached as a piece of magic to the object which remains free to be anything. That keeps the actual object body uncommitted, a requirement for black-box inheritance.

        Privacy is only secondary, its lack has never been a big deal in Perl OOP (or other Perl, for that matter). The problem isn't that one class can access another's data, the problem is that there is nothing else for it to access. Inside-out and Alter are different ways of addressing that problem.

        Anno

          I may think out loud here a little.

          With Alter's magic corona, you can integrate with an existing anything-based object and be anything you want. It doesn't matter what the other object is, you can get along with it, and it can get along with you.

          This is true also of an inside-out object that uses the reference as a key into its attribute hashes. The problem is that the inside-out object has some overhead in the form of a DESTROY method, and it has to go out of its way to deal with threading.

          They both have to do something special to support Storable (I wonder if my overload trick would help with that, but probably not). They both have some overhead for practically all self-access (ego vs. ident/refaddr/etc.).

          If the magic corona's key is based only on caller, there's a problem with methods called via some avenue other than the package they were compiled in, but that's not such a big deal if you can tell ego what key to use instead.

          So I'm thinking that interoperability-wise, they're about the same. That said, there may be implementation details to worry about, but my head is already swimming a little.

          The technique I wrote about before is another way for classes to work together in an object regardless of what they want to be, but they all have to be aware of it. For that reason, it's not interoperable.

          OK, I think I have a little more clarity now. Thanks for reading.

    Re^3: Beyond Inside-Out
    by clinton (Priest) on May 30, 2007 at 11:40 UTC
      Thanks Anno, that makes a lot of sense

      I would be interested to understand more about Tye's concerns and how valid they are.

        I would be interested to understand more about Tye's concerns and how valid they are.

        The focus of Tye's concerns is the fact that the ego() function uses its caller to decide which alter ego to produce. Here, "caller" means the package that was in force when the call to ego() was compiled. Now, it is possible to do things like

        package Foo; sub Bar::method { my $ego = ego($_[0]); ... }
        That would indeed produce an anomaly: A method in class Bar that accesses the ego belonging to Foo. On the other hand, that would be the described behavior, for better or worse. It isn't something that easily happens by accident while you're writing your accessors. It may even be useful in some situations, I haven't thought about it much. In general, the Alter-approach assumes that methods are compiled in the class their name resides in.

        Tye has another objection which I'm not sure I understand. If I understand it right it is about qualified method calls, in the form

        $obj->Class::method(...);
        but I think an Alter-based class would behave exactly as it should with these.

        Anno

          In general, the Alter-approach assumes that methods are compiled in the class their name resides in.

          That assumption breaks badly for classes that "mix-in" methods from other modules. Plug-ins (e.g. many of the web frameworks) would be a good example of this kind of thing, where a class imports one or more methods from the plug-in.

          -xdg

          Code written by xdg and posted on PerlMonks is public domain. It is provided as is with no warranties, express or implied, of any kind. Posted code may not have been tested. Use of posted code is at your own risk.

    Log In?
    Username:
    Password:

    What's my password?
    Create A New User
    Node Status?
    node history
    Node Type: note [id://618155]
    help
    Chatterbox?
    and all is quiet...

    How do I use this? | Other CB clients
    Other Users?
    Others perusing the Monastery: (6)
    As of 2018-06-25 06:34 GMT
    Sections?
    Information?
    Find Nodes?
    Leftovers?
      Voting Booth?
      Should cpanminus be part of the standard Perl release?



      Results (126 votes). Check out past polls.

      Notices?