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

Anti-inside-out-object-ism

by jdhedden (Deacon)
on Dec 09, 2005 at 20:56 UTC ( [id://515650]=perlmeditation: print w/replies, xml ) Need Help??

In the discussion concerning Seeking inside-out object implementations, several monks expressed various reasons for their reluctance to use inside-out objects. Here's the list I gathered from that thread:

I don't want to use inside-out objects because:

  1. Hash-based objects are the standard. Using a different object API may lead to maintainability issues.
  2. Inside-out object classes aren't compatible with hash-based object classes.
  3. Inside-out objects are just another kludge on top of Perl's already kludgy OO mechanisms.
  4. I haven't had any problems using hash-based objects. The encapsulation and compile-time checking advantages of inside-out objects aren't important enough to induce me to use them.
  5. The encapsulation provided by inside-out objects is unenforcable because the source code is available.
  6. Inside-out objects require a DESTROY method, and I don't what to have to remember to write one each time I create an inside-out class.
  7. There are too many alternative inside-out object support modules that aren't compatible with each other.
  8. I'm leery of the 'magic' the inside-out object support modules do 'under the covers'. There may be bugs or they may lead to unexpected problems when interacting with other modules.
  9. I tried module Foo::Bar, and had problems with it so I gave up on trying to use inside-out objects.
  10. You can't serialize inside-out objects either in general, or using Data::Dumper or Storable.
  11. Inside-out objects are not thread-safe because they usually use refaddr as the key for storing object data.
Other monks were able to address some of these concerns, and I have summarized their responses, as well as adding some thoughs of my own.
Further, as the author of Object::InsideOut, I will speak to specifics concerning that module where appropriate.
Hash-based objects are the standard. Using a different object API may lead to maintainability issues.
The argument is basically that all Perl programmer's know how to use hash-based objects, and that if I use a support module like Object::InsideOut, then anyone else that tries to read/maintain my code will have to learn about inside-out objects, in general, as well as the specifics of the support module. This is obviously something to consider when looking at using inside-out objects, and needs to be weighed against inside-out objects' advantages.

As with any new paradigm, it will take time for inside-out objects to become generally accepted, however, I am confident that they will. Their inclusion in PBP will definitely speed up the process. Eventually, someone will write a tutorial on inside-out objects for inclusion with the main Perl distribution. Thus, as time goes by, the argument above will start to lose some of its weight.

Inside-out object classes aren't compatible with hash-based object classes.
They aren't compatible in the same way as other hash-based object classes, true, but that doesn't mean you can't work with them at all.

One simple approach to inheriting from hash-based classes is to use the hash-based object as is, and then use its refaddr as the key for storing data inside the derived class. Some inside-out object support modules use this approach. However, this approach doesn't support multiple inheritance, and the use of refaddr requires addition code for thread-safety (given that the hash-based class must be thread-safe as well).

Object::InsideOut has recently been enhanced to support subclassing of hash-based object classes (referred to as foreign inheritance in its docs), and it does support multiple inheritance. Further, Object::InsideOut is thread-safe.

Inside-out objects are just another kludge on top of Perl's already kludgy OO mechanisms.
Well, Perl never claims to be a pure OO language, and arguments as to its merits are rather pointless. It is what it is. Use it, or don't. My personal stand follows from the P in Perl standing for practical: Perl's OO interface gets the job done when it's needed. I find the ability to mix OO and procedural programming, as needed, to be one of Perl's greatest strengths.

As to inside-out objects being another kludge, I would argue against the use of that label. Inside-out objects is just another paradigm. They use standard Perl to do the same job but in a different manner, complete with its own strengths and weaknesses.

I haven't had any problems using hash-based objects. The encapsulation and compile-time checking advantages of inside-out objects aren't important enough to induce me to use them.
To be clear, encapsulation for inside-out objects prevents the overwriting of hash-keys that can occur with inheritance in hash-based object classes.

The compile-time checking comes about because the fields in inside-out objects are hashes or arrays, and not hash-keys. Misspelled hash-keys are not caught at compile-time, and may or may not be caught at runtime. Misspelled hash or array names are caught at compile-time.

Now for smaller systems, these advantages may be of less importance to a single programmer. However, for larger projects with multiple coders, these advantages should be given much more thought. In fact, inside-out objects resulted from considering how to overcome just these problems with hash-based objects. Obviously, they are very important to some.

The encapsulation provided by inside-out objects is unenforcable because the source code is available.
It is true that deliberate circumvention of any OO system is possible given the source code. If such totalitarian controls are a requirement of your system, then perhaps you need to consider using something other than Perl.

The point of encapsulation with inside-out objects is to prevent the collision of data (i.e., hash-keys) that can occur with hash-based object classes. It adds safety, but doesn't prevent deliberate circumvention.

Inside-out objects require a DESTROY method, and I don't what to have to remember to write one each time I create an inside-out class.
Various inside-out object support modules, including Object::InsideOut, handle this for you automatically, so this becomes a non-issue if you use one of them.
There are too many alternative inside-out object support modules that aren't compatible with each other.
This criticism can be applied to just about any functionality for which CPAN modules have been written: CPAN and CPANPLUS; ExtUtils::MakeMaker, Module::Build and Module::Install; and more.

As with anything, as time goes on, certain implementations will become more accepted than others depending on their features, robustness, support, and so on. Personally, I have been putting in a lot of effort in all these area to make Object::InsideOut as usable as possible to the Perl community.

I'm leery of the 'magic' the inside-out object support modules do 'under the covers'. There may be bugs or they may lead to unexpected problems when interacting with other modules.
With the source code available, you can see what is being done, if needed. However, as I see it the proof is in the pudding. If the support modules does what you want it to and thereby meets your needs without causing problems and incompatibilities, then what difference does it make how it does it.

As for bugs, a good test suite and good author support lessen the probability and potential impact of encountering problems in your own development. For example, there are currently no open bugs for Object::InsideOut, and any reported bugs have been corrected in less than one day.

Likewise, incompatibilites can be overcome with good author support. For example, when I first released Object::InsideOut, I was informed that having a CHECK block would make it incompatible with mod_perl. Within a day, I posted an new version that eliminated this incompatibility.

I tried module Foo::Bar, and had problems with it so I gave up on trying to use inside-out objects.
This sort of thing can happen with any module. Giving up is not the answer, however. If you weren't able to get support from the module's author, you could try another. Obviously, you were interested enough to look at inside-out objects in the first place. A bad module doesn't mean the underlying concept (i.e., inside-out objects) is bad.

As you might guess, I would recommend giving Object::InsideOut a try. It has a discussion forum on CPAN, and active author support.

You can't serialize inside-out objects either in general, or using Data::Dumper or Storable.
It is true that inside-out objects do not automatically support serialization. Once again, however, some support modules do provide serialization capabilities. For example, Object::InsideOut does provide object serialization and deserialization capabilites, and has recently been enhanced to support serialization using the Storable module.
Inside-out objects are not thread-safe because they usually use refaddr as the key for storing object data.
Making inside-out objects thread-safe is not a trivial process, but it can be done. Object::InsideOut is thread-safe, and even goes further by providing support for threads::shared.

In conclusion:
I agree that inside-out objects may not be for everyone, however, I hope that the discussion above (and what will follow) will help others in making an informed decision on the subject.


Remember: There's always one more bug.

Replies are listed 'Best First'.
Re: Anti-inside-out-object-ism
by xdg (Monsignor) on Dec 09, 2005 at 21:51 UTC

    Another common concern raised is about speed.

    There is overhead associated with DESTROY that doesn't exist (in quite the same way) for hash-based objects where garbage collection is left to Perl rather than done by hand. If lots of objects are being generated and destroyed, this may be an issue for some individuals.

    Also, depending on the implementation, inside-out accessors can be much slower than hash-based accessors, but the difference can be very small if the inside-out class caches the refaddr, as this node demonstrates. (The array-based implementation of Object::InsideOut is faster yet, I believe, but that isn't an apples-to-apples comparison.)

    As a side note, the tendency of inside-out classes to be implemented with attributes for syntactic sugar is another potential downside. (Incompatibility with other Attribute::Handlers modules, for example.) But that relates to implementation choices, not the inside-out paradigm itself.

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

      There is overhead associated with DESTROY that doesn't exist (in quite the same way) for hash-based objects where garbage collection is left to Perl rather than done by hand. If lots of objects are being generated and destroyed, this may be an issue for some individuals.

      Although when I've benchmarked inside-out vs hash based versions of objects in real world scenarios the overhead of the extra DESTROY just disappears in the noise.

      I suspect it's going to be a rare environment where one extra method call perl object makes a significant difference.

Re: Anti-inside-out-object-ism
by diotalevi (Canon) on Dec 09, 2005 at 21:13 UTC
    I'd like to hear about how I make an inside out object be thread safe (including whatever thread::shared) is. Do you have references for that?
      xdg provided the original insight on how to make inside-out objects thread-safe in Threads and fork and CLONE, oh my!.

      threads::shared provides the capability to share variables between threads such that changing the value in one thread makes that change visible in another thread. Object::InsideOut is unique among inside-out object support modules (and, to my knowledge, all other object support modules, as well) in providing support for threads::shared, thus giving you the capability to share objects between threads. As for how to do it, you'd have to look at the module's code to see how. It is not a trivial process.


      Remember: There's always one more bug.
        xdg provided the original insight on how to make inside-out objects thread-safe in Threads and fork and CLONE, oh my!.

        Though it bears repeating that this is only possible on Perl 5.8 or better which supports the special CLONE method.

        Whether using threads or threads::shared in Perl is a good idea or not is a whole separate issue. (c.f. Things you need to know before programming Perl ithreads and Re: Reliable asynchronous processing). However, it's important for people to realize that forking on Win32 actually uses threads (c.f. perlfork) so this behavior of inside-out objects needs to be continually flagged.

        None of these are "deal-killers" for inside-out objects, but they do require awareness and management of complexity. That said, I think jdhedden has done a great job with Object::InsideOut (as he did with Math::Random::MT::Auto) in creating something that might well serve as the gold-standard in the category.

        -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: perlmeditation [id://515650]
Approved by friedo
Front-paged by valdez
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others surveying the Monastery: (3)
As of 2024-11-01 19:23 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    chatterbot is...






    Results (4 votes). Check out past polls.