I haven't used any of these, for a couple of reasons. Well, three I guess, the first being that I haven't found any real problems with using simple hash-based classes for everything.

The second is that Class::Std and some of the others do some things that I don't trust to work reliably and not interfere with some other tool. They use rely on DESTROY, have a super-complex constructor, use lots of subroutine attribute magic, etc. I suspect bugs and bad interactions with other modules will be found in these complex additions.

And finally, I don't use them because, despite the name, they are the exact opposite of standard. All the Perl literature teaches programmers how simple hash-based objects work, and any OO Perl programmer can be expected to know it and read that code. Class::Std turns the world upside down (or inside out if you prefer) and provides a whole new mini-language to learn. It means another level of stuff that people will have to learn before they have any chance of understanding my code, and thus more training, more difficulty getting help in public forums like Perlmonks, fewer people able to contribute patches, etc. To me, that isn't worth the payoff.

Encapsulation? I'm giving them the source! If they want to break it badly enough, they will be able to.

UPDATE: I removed an earlier statement that Class::Std puts a DESTROY method in the UNIVERSAL:: package. Although the Perl Best Practices book does show that in the section on inside-out objects, the Class::Std module doesn't actually do it.

Not having encapsulation means that it's really, really easy for someone to silently and mysteriously break your class by overwriting a hash key. I've had to deal with this and it's not fun. For smaller systems, it's less of a problem but bigger systems require more careful planning. Admittedly good test suites catch the errors, but they frequently don't tell you how to fix 'em.

The main problem with inside-out objects is that they're currently even more of a hack than Perl's current OO system. With clean OO, we wouldn't even be worrying about this.

I might add that Class::BuildMethods does not override UNIVERSAL::DESTROY and is very lightweight. It gives you encapsulation in a very easy to use manner and can be incorporated into existing classes. Further, the constructor is usually ridiculously easy to use. It's much easier than its counter-parts. The trade-off being that you only get one style of getter/setter and you can only store a single value (hashes must be passed as hashrefs, for example. By restricting the interface, the code is simpler and faster. You want three simple getter/setters?

use Class::BuildMethods qw/name rank serial/;

You can mix them with any others you want and add defaults or validation as needed.

It took me a while to grok it, longer to debug why my constructor wasn't working, then a bit more to peer into the guts and figure out why something I was used to doing (deriving auxilliary member variables from either a default value or its user-overridden replacement) wasn't going to work unless Damian changed how Class::Std works. I filed a feature request via RT, but the change might actually introduce subtle bugs into existing Class::Std derivatives, so I don't think it can be done.

The second is that Class::Std and some of the others do some things that I don't trust to work reliably and not interfere with some other tool.

Interesting. If Class::Std or "some of the others" interfere with some other tool, why do you blame Class::Std and some of the others, and not the other tool?

And finally, I don't use them because, despite the name, they are the exact opposite of standard. All the Perl literature teaches programmers how simple hash-based objects work, and any OO Perl programmer can be expected to know it and read that code.

First of all, "inside-out objects" as a name doesn't suggest anything about being standard or not. And if your argument makes sense, we'd still be using the indirect object notation, because that's how we used to teach programmers in the literature. Views change over time, and documentation isn't static.

Encapsulation? I'm giving them the source!

The point of encapsulation is that you don't need to read the source.

I guess you don't bother to use strict, or lexical variables, either, do you? Why would you, you have the source!

First of all, "inside-out objects" as a name doesn't suggest anything about being standard or not.

This is, unfortunately, a Damian-created issue, with a number of new modules released to CPAN with "::Std" as part of their names, coincident with the release of Perl Best Practices. "Class::Std" should not be read as "Class::Standard" as it's anything but. Pronouncing that suffix letter-by-letter gives a better sense of the caution and prophylaxis that should be considered before using it.

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

If Class::Std or "some of the others" interfere with some other tool, why do you blame Class::Std and some of the others, and not the other tool?

Have you looked at how Class::Std is implemented? It's pretty crazy. It includes some "worst practices" too, like use of the UNIVERSAL:: namespace.

"inside-out objects" as a name doesn't suggest anything about being standard

The name is Class::Std, i.e. "Class Standard."

we'd still be using the indirect object notation, because that's how we used to teach programmers in the literature. Views change over time, and documentation isn't static.

If Class::Std ever became a very common way to do things, to the point where the Perl man pages used it in their OO examples, I would drop this objection. I think the difference between Class::Std and normal OO perl is a lot bigger than these other examples you gave though.

we'd still be using the indirect object notation, because that's how we used to teach programmers in the literature. Views change over time, and documentation isn't static.

You're misunderstanding me. What I'm saying is that any attempt to enforce encapsulation is ultimately futile when the other person has the source and can simply change your code to expose things that they want. I will grant that it's much harder to do than it is with simple hash-based objects though.

UPDATE: Class::Std does not actually put things in UNIVERSAL::. This technique is suggested in the inside-out objects section of the PBP book, but not used in Class::Std.

What I'm saying is that any attempt to enforce encapsulation is ultimately futile when the other person has the source and can simply change your code to expose things that they want.

You are completely missing the point of inside-out objects. The point of inside-out object isn't to prevent accessing data. The point of inside-out objects is on the one hand to prevent accidental access of data (collisions), and on the other hand to give you compile time errors when making typos in the attribute names.

Inside-out objects is to OO programming what 'use strict', lexical variables, and name-spaces are to non-OO Perl programming. None of it prevents anyone from getting to anything one wants - but that doesn't mean 'use strict', lexical variables and name-spaces aren't very good ideas.

"inside-out objects" as a name doesn't suggest anything about being standard

The name is Class::Std, i.e. "Class Standard.

Let me recall what you wrote:

And finally, I don't use them because, despite the name, they are the exact opposite of standard.

That's plural. The thread is named Seeking inside-out object implementations. If your objection is about the name of a single module, then the use of plural is misleading. It would also mean that that objection doesn't hold for different implementations of inside-out objects.

Unless you want to claim that the name of inside-out objects is "Class::Std". In which case you are utterly wrong. "Class::Std" is a way of implementing inside-out objects, not 'the way'. Dismissing inside-out objects based on a single module is like dismissing databases because you don't like MySQL, or dismissing cars because you don't like Fords.