Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW
 
PerlMonks  

Perl 5 OOP solutions

by tomazos (Deacon)
on Apr 14, 2006 at 02:11 UTC ( #543270=perlquestion: print w/replies, xml ) Need Help??

tomazos has asked for the wisdom of the Perl Monks concerning the following question:

A recent article I was reading about Perl 6 said the following...

The de facto OO technique in Perl 5 is blessing a hash and accessing the hash's members directly as attributes. This is quick and easy, but it has encapsulation, substitutability, and namespace clashing problems. Those problems all have solutions: witness several competing CPAN modules that solve them.

My question is which are the CPAN modules that try to solve those problems? And what approach do they take to solving them?

Thanks.

-Andrew.

Replies are listed 'Best First'.
Re: Perl 5 OOP solutions
by dragonchild (Archbishop) on Apr 14, 2006 at 02:33 UTC
    The latest one to enter the space is Moose. It's written by stvn who's designing the P6 OO. We're using that one at work and we like it, a lot. Catalyst and DBIx::Class are also starting to use it, so it's getting a lot of exposure.

    Old standbys are Class::MakeMethods, Class::Std, and Class::MethodMaker, though there are dozens of decent solutions.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      The thing about Moose is that it isn't really addressing the issue that the OP cited -- that the "default" approach to objects in Perl 5 is blessing a hash and storing attributes in the hash -- as it doesn't address the encapsulation and substitutability issues (what has come to called "foreign inheritance" by inside-out authors).

      Moose is built with Class::MOP, which provides some nice sugar, but doesn't really change the underlying behavior. From the description of Class::MOP:

      This module is an attempt to create a meta object protocol for the Perl 5 object system. It makes no attempt to change the behavior or characteristics of the Perl 5 object system, only to create a protocol for its manipulation and introspection.

      What it does well is to allow for various types of introspection. (See stvn's response to my question about this in another thread.) This is very helpful for object-relational mapping like DBIx::Class and (I'd imagine) request-dispatch mapping frameworks like Catalyst. The fact that Moose is proving useful to these applications doesn't mean that it's well suited for all types of problems. (It doesn't mean that it isn't, either.)

      And while it might be possible to build inside-out objects using Class::MOP, the InsideOutClass example bundled with it has substantial missing pieces and is currently YABIOOI (yet another broken inside-out object implementation). When I have enough tuits, I might tackle a proper inside-out implementation using Class::MOP.

      I have great respect for stvn, and I'm glad to see some of the insights from the Perl 6 object system migrating back to Perl 5, but I don't think that Class::MOP or Moose really address the underlying issues that the OP was asking about -- though they do bring some useful systematization to Perl OO techniques and make it easier to address the problems that exist today.

      For that matter, it should be noted that inside-out objects aren't a panacea, either. They solve a couple of problems, but at the cost of a substantial increase in complexity.

      It's all the more reason to look forward to Perl 6.

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

        You are absolutely correct that Moose and Class::MOP both do not attempt to change the underlying fundementals of Perl 5 00, it attempts to augment them in such a way that all the (sometimes dangerous) flexibility is retained and all the tedious repitition is removed. To address the quote the OP gave:

        This is quick and easy, but it has encapsulation, substitutability, and namespace clashing problems.
        The need for strong encapsulation is (IMO) overblown. In many of the application domains where perl thrives, it is not really needed, and if you do find you really need it, you probably shouldn't be coding in Perl anyway. Of course encapsulation has a social component to it as well, a "keep out the dumb programmer next to me" feature. But honestly, I think that issue is better addressed by social policy than by language features.

        As for substitutability, a well designed class will not have this problem. In fact I can break substitutability in just about any language, although languages with strict type systems are harder than dynamic languages like Perl/Python/Ruby/etc. A well designed class hierarchy will not break substitutability, a language compiler/runtime which double checks that for you is nice at times and restrictive at others.

        The "namespace clashing" is a little ambiguous, it sounds to me like a C++ism and really just another word for encapsulation. In that case, my above comment applies.

        So all that said, you can see why i did not try to address these items with Moose and Class::MOP, I don't see them as dire problems. The dire problems I see with Perl 5 OO is the tediousness manual nature of it. Too often I find myself writing the same code over and over. Things like constructors, slot creation and initialization, accessor methods, the list goes on and on. Solutions like Class::Accessor, Class::MethodMaker, etc. only address certain issues and either don't handle the others, or worse, handle them poorly. I do not think this is a failing of these modules (or their authors), but a failing of Perl's OO facilities in general. In short, it's extreme flexibility makes enforcing consistency difficult, and without some consistency these problems cannot be solved. The primary goal of Class::MOP is to create a meta-level infrastructure which can serve as that layer of consistency, while trying to not enforce that consistency on the user (non-meta) level.

        Now, some people might not see that tedium I mention as being nearly as important as things like encapsulation. I disagree, reducing tedious and repetitive coding means reduced errors. And not logic errors, but stupid errors, silly ones that you can spend hours trying to hunt down cause you wouldn't think to look in that tedious repetitive code you have written 1000 times. And all that tedium usually means duplication, which is where simple typing errors and misspellings can easily creep in. If you only ever write the name of your attribute once (in it's attribute definition) and the meta-level handles things like slot initialization, accessor generation, etc., simple spelling errors then become much less common.

        But enough babbling, let me address some of your comments:

        And while it might be possible to build inside-out objects using Class::MOP, the InsideOutClass example bundled with it has substantial missing pieces and is currently YABIOOI (yet another broken inside-out object implementation). When I have enough tuits, I might tackle a proper inside-out implementation using Class::MOP.
        I am sure It is quite broken, but it is mearly a proof of concept for alternate instance storage schemes, and not meant ever to be used seriously. The missing piece are left as an exercise to the reader *cough* hint hint *cough* ;)
        I'm glad to see some of the insights from the Perl 6 object system migrating back to Perl 5, but I don't think that Class::MOP or Moose really address the underlying issues that the OP was asking about -- though they do bring some useful systematization to Perl OO techniques and make it easier to address the problems that exist today.
        Actually, my point above is that a "useful systematization to Perl OO techniques" actually can go a long way to solve the underlying issues the OP is talking about. Of course YMMV and TIMTOWTDI.
        For that matter, it should be noted that inside-out objects aren't a panacea, either. They solve a couple of problems, but at the cost of a substantial increase in complexity.
        I actually think that a meta-level infrastructure like Class::MOP might be just what inside-out objects need to help reduce that complexity. By moving the complexity up the meta-chain, you move it out of the view of the casual user, and still keep it accessible to those who need it.

        -stvn
        Actually, it does provide for everything the OP asked for. You just have to drink a little more Koolaid. Class::MOP doesn't provide much outside of sugar. But, Moose does. Using 'extends', you can safely subclass. It doesn't guarantee much (yet) in the way subclassing non-Moose stuff, but we're only on 0.03_02 - lots more to go. :-)

        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?

      I thought Moose was an experiment from the Perl 6 people. Gah.

      ⠤⠤ ⠙⠊⠕⠞⠁⠇⠑⠧⠊

        It started out that way. But, after sri (Catalyst) and mst (DBIx::Class) started playing with it, they liked it and wanted stvn to productionize it. :-)

        My criteria for good software:
        1. Does it work?
        2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      Wow. Moose really rocks. I mean I really wasn't impressed by all the inside-out craze, but this one is really promising :)
Re: Perl 5 OOP solutions
by xdg (Monsignor) on Apr 14, 2006 at 03:05 UTC
Re: Perl 5 OOP solutions
by nacredata (Sexton) on Apr 14, 2006 at 06:12 UTC
    I was introduced to this topic by the excellent book "Perl Best Practices". No other programming book has ever explained such complex material so naturally to me, I really do recommend it. I haven't played around to know if the author's solution of inside-out objects using Class::Std works well for me, but at least I feel I better understand the problems.
Re: Perl 5 OOP solutions
by dws (Chancellor) on Apr 15, 2006 at 00:58 UTC

    When someone makes claims that something is a "problem", particularly when they start waving the magic word "solution", it's sometimes insightful to replace "problem" with "possible issue" and then ask:

    • What evidence has been provided that this is a real issue?
    • What is the nature of the issue? Who does it affect, how, and when? Is it likely to affect me?
    • How is the issue mitigated?
    • Is the cost of the mitigation worth the effort?

    In the specific case the visibility of member variables (hash elements) of stock Perl objects, yes, they are visible. Is this a problem? It comes down to a matter of trust. If you trust yourself and your team to not abuse the feature, I'll argue, (based on experience with two substantial perl-based applications, one in the 600KLOC range) that visibility isn't an issue worth the cost of the various workarounds.

    If you don't trust your team, then visibility is an issue, but isn't your biggest issue.

    YMMV.

      In the specific case the visibility of member variables (hash elements) of stock Perl objects, yes, they are visible. Is this a problem? It comes down to a matter of trust. If you trust yourself and your team to not abuse the feature, I'll argue, (based on experience with two substantial perl-based applications, one in the 600KLOC range) that visibility isn't an issue worth the cost of the various workarounds.

      For me the issue isn't trust. The problems I've had are not due to deliberate fiddling with member variables - they're to do with accidental ones. People having subclasses break when new superclasses are released by different teams because instance variables or private methods clash, etc.

      So yes, for me, it has occasionally been quite a significant issue - and solutions like Class::InsideOut look like a nice low cost way to avoid it in the future.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://543270]
Approved by ikegami
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others scrutinizing the Monastery: (6)
As of 2023-12-06 17:48 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?











    Results (31 votes). Check out past polls.

    Notices?