Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change
 
PerlMonks  

Overriding bless for inside-out object safety

by xdg (Monsignor)
on Jan 04, 2006 at 16:33 UTC ( #520952=perlmeditation: print w/ replies, xml ) Need Help??

I've been experimenting with some approaches for making inside-out objects a little more user friendly. (c.f. Anti-inside-out-object-ism for some of the common complaints). One of the more obscure issues has to do with thread-safety. I presented an approach for that in Threads and fork and CLONE, oh my!. I'm considering ways of making that more automatic and transparent.

One approach I've considered is a helper module that would override/redefine bless to register objects transparently for use in CLONE (which would also be imported automatically). Usage would be just as with a normal constructor:

package My::Class; use InsideOut::Helper qw( bless ); sub new { my $class = shift; my $self = \do { my $scalar }; bless $self, $class; }

Behind the scenes, this bless would do something like this:

my $REGISTRY; sub bless { &CORE::bless; $REGISTRY{ $_[1] }{ refaddr $_[0] } = $_[0]; return $_[0]; }

$REGISTRY would also be used in CLONE to fix up inside-out objects during thread creation.

I'm a little cautious redefining something as critical as bless so I'd like feedback on this idea. Some specific questions I have include:

  • Should bless be automatically redefined or explicitly as shown in the example above? It would almost always be imported, but making it explicit highlights the fact that bless is doing something unusual. Without the import, it could be called as InsideOut::Helper::bless( $self, $class ) of course.

  • Is there anything unusual about bless' syntax or function that I need to watch out for in redefining it? (Should I use a prototype that matches the builtin?)

  • Is redefining bless a bad idea? Should I just import a separate function like register instead to register the object after it's blessed using the built-in bless? E.g. register( bless $self, $class )

Side notes -- the example above is incomplete as inside-out lexical properties also need to be registered somehow for use with CLONE. (I'm working on a good, simple syntax for that.) The InsideOut::Helper name is also just a placeholder as I haven't come up with a name for this module, yet. (That said, what do people think about a new InsideOut top-level name to make a sharper distinction from the more traditional Class? I'm not sure it's needed, but I could see a case for it.)

Also, at least some inside-out generators automatically import a function like id as an alias to refaddr for use like this:

my $NAME_OF{ id $self } = "Larry"; # instead of my $NAME_OF{ refaddr $self } = "Larry";

Do people feel this kind of aliasing is helpful or symbol pollution?

Your feedback is greatly appreciated.

-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.

Comment on Overriding bless for inside-out object safety
Select or Download Code
Re: Overriding bless for inside-out object safety
by revdiablo (Prior) on Jan 04, 2006 at 17:00 UTC

    Unless I misunderstood, you're trying to guage community reaction here? If that's the case, here are my thoughts, for what they're worth:

    • I like your register( bless ... ) idea better. It's not a whole lot more to do, still takes care of a lot of drudgery, but doesn't make me quite so nervous. I don't like overriding builtin functions in general, much less one like bless.
    • Perhaps you could use the Class::InsideOut:: prefix instead of just InsideOut::. Perhaps it's a little too long, I'm not sure, but it seems a bit more descriptive.
    • The refaddr to id alias doesn't bother me all that much, as long as it's done in standard ways. It's certainly less to type. :-)

    Closing, I just want to point out I don't feel very strongly about these opinions. They're just my gut reactions. If you wanted a more thorough discussion... well, maybe someone else will post that. :-)

Re: Overriding bless for inside-out object safety
by rinceWind (Monsignor) on Jan 04, 2006 at 17:04 UTC

    Overriding bless is something I have attempted, see Overriding CORE::GLOBAL::bless. There are some caveats, particularly concerning precisely when the override takes effect. Admittedly, the purpose I was intending was not for production use, but in leak tracing.

    I posted my conclusions here; I have not yet released an updated Devel::Leak::Object, but I may do at some future point.

    Hope this helps

    --

    Oh Lord, won’t you burn me a Knoppix CD ?
    My friends all rate Windows, I must disagree.
    Your powers of persuasion will set them all free,
    So oh Lord, won’t you burn me a Knoppix CD ?
    (Missquoting Janis Joplin)

      I was considering overriding it only for the current package, not globally, but the point in your conclusions about it needing to be done at compile-time are well taken. I went through a similar learning process overrriding rand for Test::MockRandom. The pod for that has a pretty good description of when and how such overriding needs to happen.

      -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.

Re: Overriding bless for inside-out object safety
by perrin (Chancellor) on Jan 04, 2006 at 17:14 UTC
    Overriding bless sounds magical, obscure, and risky. In short, it's all the things I try to avoid in code. I'd consider it a last resort.

      With respect for your oft-expressed and totally consistant views on what you will amd will not use in your production codebase. Based upon those previously expressed views, you would use neither threads nor inside-out objects.

      Is there any chance you would have use for what xdg is doing, whether it overrode bless or not?


      Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
      Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
      "Science is about questioning the status quo. Questioning authority".
      In the absence of evidence, opinion is indistinguishable from prejudice.
        You're right, I probably wouldn't use inside out objects anyway, so take my advice with a big grain of salt. Doesn't overriding bless seems unusually risky though? I've seen a lot of posts here and on the mod_perl and Class::DBI lists over the years about things that break nearby when people mess with the core pieces of perl's OO machinery.
Re: Overriding bless for inside-out object safety
by Anonymous Monk on Jan 04, 2006 at 18:36 UTC
    Should bless be automatically redefined or explicitly as shown in the example above? It would almost always be imported, but making it explicit highlights the fact that bless is doing something unusual. Without the import, it could be called as InsideOut::Helper::bless( $self, $class ) of course.

    I'd suggest that you call it "register" instead, as you proposed later. And force the user to export only the functions they need, explicitly. That way, it's easier to maintain: if you export fifteen functions, I need to check the codebase to see if any of those fifteen functions are still in use before I can remove the module from the codebase. If you only export what you actually use, then maintaining the code and removing unused modules becomes much easier. I'm lazy; I'd rather write down what I know when I know it (such as what functions I'm using from a given module), rather than waste time trying to reconstruct what I've forgotten.

    Is redefining bless a bad idea? Should I just import a separate function like register instead to register the object after it's blessed using the built-in bless? E.g. register( bless $self, $class )

    I don't see the need to redefine "bless"; just tell people to use "register" instead of "bless". You call the core "bless" function, so you should be able to use register exactly as you do "bless". In general, I find redefining builtin functions is always more confusing than not doing so. If I read "register", I know immediately that I don't know what's going on, and that I need to learn more. If I read "bless", I might be fooled into the wrong assumptions.

    Just my $0.02
    --
    Ytrew

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlmeditation [id://520952]
Approved by Limbic~Region
Front-paged by astaines
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (10)
As of 2014-09-03 07:29 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite cookbook is:










    Results (35 votes), past polls