Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things
 
PerlMonks  

Re^4: Overriding bless for inside-out object safety

by BrowserUk (Patriarch)
on Jan 04, 2006 at 19:12 UTC ( [id://520985]=note: print w/replies, xml ) Need Help??


in reply to Re^3: Overriding bless for inside-out object safety
in thread Overriding bless for inside-out object safety

Doesn't overriding bless seems unusually risky though?

I hadn't made up my mind, but having just read freind Ytrew's post, and justification, I do actually agree with you--but for Ytrew's reasoning rather than yours :) I don't have any call for using mod_perl, and almost certainly will never use Class::DBI.

I'm not yet convinced of the benefits of Inside Out objects either. The extra "protection" afforded seems minimal in that any enterprising subversive can bypass it easily enough anyway. I've also had occasion to go direct to instance data within a hash based module via the reference, when that data was not exposed. Most recently I needed access to the underlying IO handle in File::ReadBackwards, but no accessor method is provided. Whether I would do this in production code would depend very much upon my need, the urgancy of that need, and whether it was worth the risk of locally forking a CPAN module in the hope that I could get the changes adopted by the author. I'm would not allow OO dogma to prevent me from getting a working solution. I would probably opt for adding an accessor method to the module at runtime as an interim solution, if I needed access to the data in more than one place. If I only needed it in one place, a big ## !!TBD!! comment would probably suffice (for me).

I'm also not yet convinced whether what xdg is trying to do, with regards to cross-thread objects is either desirable or necessary, nor whether when it is done, if it will be retain sufficient performance to be usable.

I am however, eager to see the results of his efforts and looking forward to trying them out.


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.

Replies are listed 'Best First'.
Re^5: Overriding bless for inside-out object safety
by perrin (Chancellor) on Jan 04, 2006 at 19:20 UTC
    Ytrew makes a good point.

    I don't have any call for using mod_perl, and almost certainly will never use Class::DBI.

    The danger is that even if the author didn't use the code in those environments, releasing it on CPAN means someone else probably will, and will be surprised if there are incompatibilities.

      Hmm. It would be easy to add a Not designed for mod_perl environments! disclaimer to the pod.

      However, given that mod_perl is essentially a hack--a very useful and effective one, but still a hack--I would think that the onus would be upon the users of mod_perl to understand the demands and limitations that environment imposes upon the code it runs, and avoid those modules that it will have problems with, but that will be very useful to those that do not run in that environment.

      Mod_perl may be very good and widely used, but I don't think that compatibility with it should be a requirement imposed upon all CPAN modules.

      From the little I know of what xdg is doing, I wonder if it could ever be compatible with mod_perl?


      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.
        From the little I know of what xdg is doing, I wonder if it could ever be compatible with mod_perl?

        There's only a few things that I've heard of that cause problems for mod_perl.

        • Many inside-out object toolkits use attributes and the CHECK phase to set up various things and that doesn't work under mod_perl

        • Without hooks for Storable, inside-out objects can't be serialized*

        • Perl threads clone the interpreter; mod_perl uses a persistant interpreter. I'd imagine the combination would be ugly, regardless of whether inside-out objects are involved or not

        What I'm working on will address the first two problems. Object::InsideOut does this already today. The last is a tangential issue, though I'm also providing support for inside-out objects and threads, regardless of mod_perl issues.

        *Expecting to serialize an object by violating encapsulation and treating it like a data structure isn't a very good practice to start with as it's inconsistent usage of imperative and object-oriented styles of programming: freeze( $object ) instead of $object->freeze. Thankfully, Storable does the right thing if hooks are provided.

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

        Why is mod_perl 'essentially a hack', and why would you never use Class::DBI?
Re^5: Overriding bless for inside-out object safety
by xdg (Monsignor) on Jan 04, 2006 at 20:01 UTC
    I'm not yet convinced of the benefits of Inside Out objects either. The extra "protection" afforded seems minimal in that any enterprising subversive can bypass it easily enough anyway.

    There is a frequent misconception that the "protection" afforded by inside-out objects is about hiding data. It's not. Encapsulation, from an OO sense, really has to do with objects providing a contractual interface and other parts of the code not needing or being coupled to any details about the implementation of that interface.

    Classic Perl objects encapsulate weakly -- or rather provide what I call 'advisory' encapsulation. You shouldn't access object internals, but nothing prevents you from doing so. Inside-out objects enforce encapsulation. To some, that's important.

    The other encapsulation challenge is in subclassing. With classic Perl objects, subclassing can't be done without violating encapsulation -- subclasses must use the same data structure as the superclass and must be sure not to collide with superclass properties including unpublished private properties. From that sense, inside-out objects can provide not just strong, but complete encapsulation, including for subclassing. (Albeit only for some implementations of inside-out objects and with limitations on doing so for multiple inheritance.)

    recently I needed access to the underlying IO handle in File::ReadBackwards, but no accessor method is provided

    This is actually a good example of what inside-out objects can do well. I recently uploaded File::Marker -- a demonstration module for my upcoming presentation. The object is an IO::File object -- you can use it directly and there are associated properties available through accessors. That's not possible with hash-based objects.

    I'm also not yet convinced whether what xdg is trying to do, with regards to cross-thread objects is either desirable or necessary

    If you read Threads and fork and CLONE, oh my!, you'll see that it's not an optional thing if one wants to be thread-safe (and fork-safe on Win32). The same is true of any XS code with C data structures -- they will not be properly replicated across threads, which is why CLONE was introduced in the first place. What I'm trying to do is minimize how much the average user needs to understand about this to be correct -- I'm trying to make sure that inside-out objects can be written simply and correctly without worrying about all the complex things needed to make them robust. I want it to just "do the right thing".

    I take all the concerns about inside-out objects to heart -- I'm not sure they really are the right solution or whether the benefits they offer are worth the extra complexity. I'm not an advocate in that sense. I love perrin's critiques -- they speak to the pragmatist in me.

    However, I volunteered to give a presentation on inside-out objects, so I've been trying to make sure that I understand all the various ramifications well enough to explain them fully to others. Having gone through all those details myself, I now see the need for an easy, minimalist toolkit to work with them safely and sanely. The technique can and should be fairly explored, not dismissed out of hand due to faulty or sub-optimal implementations.

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

      The technique can and should be fairly explored, not dismissed out of hand due to faulty or sub-optimal implementations.

      I agree wholeheartedly. I've been quietly following your progress in anticipation of trying out the results.

      With respect to the thread safety. I am not convinced is that there is either a need for, or a benefit to, sharing objects between threads. I believe that most everything that can be done by doing so, can also be done, and is (may be) better done through a "messaging" interface.

      My opinion is based upon the results of various prototypes I created for a distributed object architecture several years ago. Cooperating objects could variously exist as

      • Other threads within the same (OS/2) process.
      • Other processes within the same box.
      • Other processes or threads on different boxes.
      • One or more TIRS (The Interactive Reasoning Shell), expert systems running under MVS or AIX.
      • One or more IMS hierarchal DBs.

      We tried various mechanisms, including cross-threaded objects (sic), and on the basis of my experiences then, cross-threaded objects simply ended up getting cross-threaded. Programmed absolutely correctly, they worked reasonably well, but the requirements for the application programmers and object constructors to understand and deploy locking and synchronisation at various levels, meant that they became too easily subject to deadlocks.

      We opted for a message passing paradigm which allowed both application and object writers to essentially ignore locking and synchronisation issues and the SendMessage()/ProcessMessage() infrastructure took care of all that in a dependable manner while still allowing full advantage to be taken of asynchronism.

      In practice, the perceived costs of message-ifying communications, were more than compensated for (in performance terms) by the avoidance of "belt&braces", unnecessary locking and sync-ing. In terms of reliability and programmer productivity, there was no contest.

      So, my opinion is based upon experience, albeit possibly not entirely relevant experience, but I have followed your progress with interest, and open mind, and a desire to try out the results.


      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.
        I am not convinced is that there is either a need for, or a benefit to, sharing objects between threads.

        Ah! I think I see the confusion. The protections are needed even without sharing objects between threads (where changes to an object in one thread are visible in another). Just creating a new thread can break any previously created inside-out object. In any new thread, inside-out objects that use a memory address as the "index" to the inside-out properties will break as the memory address changes. The new thread is a completely separate copy of all the data structures of the original and thus all the refaddr's change.

        use threads; sub dump { my $self = shift; print "name: ", $self->name(), "\n"; } $obj = Some::InsideOut::Class->new( name => "Larry" ); my $thread = threads->create( \&dump, $obj ); $thread->join();

        Without CLONE, $obj in the new thread won't point to the same data as in the original thread. CLONE gives an opportunity to fix up the data structures. Note -- this isn't using threads::shared; changes to $obj in the new thread wouldn't be seen in the original, but CLONE is still necessary.

        I'm not even tackling threads::shared support -- though jdhedden claims to have it working in Object::InsideOut, so it's apparently possible.

        I'm not sold on threads personally, but the real problem comes on Win32 where fork is really creating a thread. CLONE keeps Win32 fork safe for inside-out objects.

        -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
Domain Nodelet?
Node Status?
node history
Node Type: note [id://520985]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others making s'mores by the fire in the courtyard of the Monastery: (2)
As of 2024-04-16 20:32 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found