Stories
Slash Boxes
Comments
NOTE: use Perl; is on undef hiatus. You can read content, but you can't post it. More info will be forthcoming forthcomingly.

All the Perl that's Practical to Extract and Report

use Perl Log In

Log In

[ Create a new account ]

Ovid (2709)

Ovid
  (email not shown publicly)
http://publius-ovidius.livejournal.com/
AOL IM: ovidperl (Add Buddy, Send Message)

Stuff with the Perl Foundation. A couple of patches in the Perl core. A few CPAN modules. That about sums it up.

Journal of Ovid (2709)

Saturday November 29, 2008
04:58 PM

More Frustration With the State of OO

[ #37975 ]

From Encapsulation, Inheritance and the Platypus effect:

It's common practice to develop extensive in-house class libraries. However, when one examines the code in a typical class library, one finds a lot of excess generality and functionality which not only makes the code inefficient, but cluttered and hard to read, or even to debug.

The article itself is short, clear, and helps to make clear that OO code is often a dangerous beast. Please read it before continuing.

I find myself growing more disenchanted with OO as I go along because programmers are simply abusing it. One key thing that Schwern likes to remind us is that code should be skimmable. I really, really wish more programmers would understand this. I often go into projects and find that I cannot make heads or tails of their code not just because the work is complicated, but multiple levels of "abstraction" and "refactoring" have rendered code impenetrable.

Frankly, I'm not a stupid programmer, but I confess that there are many programmers who do a better job understanding complex systems than I do. Part of that is because we don't try hard enough to make our code understood. What I like to cleanly write the code the programmer's likely to look at first and then if there are gory bits, hide them lower down. The programmer who really needs to know will dig down, but at the higher level, well-named variables and functions, even if they take a bit longer to write out, are a win. Consider, for example, my Test::Kit module. This module let's you list several test classes in an import list and compose all of them together and export their test functions en masse to your namespace. This makes it easy to build custom testing modules. There are complicated bits, but here's the import method:

sub import {
    my $class = shift;

    my $callpack = caller(1);

    my $basic_functions = namespace::clean->get_functions($class);

    my ( $packages, $features ) = $class->_packages_and_features(@_);
    $class->_setup_import($features);

    foreach my $package ( keys %$packages ) {
        my $internal_package = "Test::Kit::_INTERNAL_::$package";
        eval "package $internal_package; use $package;";
        if ( my $error = $@ ) {
            Carp::croak("Cannot require $package:  $error");
        }

        $class->_register_new_functions(
            $callpack,
            $basic_functions,
            $packages->{$package},
            $package,
            $internal_package,
        );
    }
    $class->_validate_functions($callpack);
    $class->_export_to($callpack);

    {
        # Otherwise, "local $TODO" won't work for caller.
        no strict 'refs';
        our $TODO;
        *{"$callpack\::TODO"} = \$TODO;
    }
    return 1;
}

That's not perfect (_register_new_functions is particularly heinous), but at the high level, I made it easy to read because you need to understand the logic flow. And this is alpha code that I just threw together. You could contrast this with a class I was trying to understand the other day which had a bunch of Moose attributes declared, a couple of methods, inherited from three different classes and used two roles! You couldn't tell what the class did. The multiple inheritance (each of the parent classes in turn inherited from other things) and the two roles made it a mess to try and figure out where any functionality was. It's stuff like this which leads programmers to write articles like the one I linked to.

This style of coding is pervasive enough that I am beginning to think that OO encourages it. Take, for example, Mason and Template Toolkit. I've used both extensively, but Mason, while being lovely and powerful, makes it seductively easy to push application/business logic into the view layer (sorry Dave!). It makes this so easy that every shop I've worked at which makes extensive use of Mason has problems with this. I don't see those problems nearly as often with Template Toolkit.

So is OO, like Mason, a fantastic idea which nonetheless is so easy to abuse that it ultimately leads to more problems than it solves? I won't say this is true, but I suspect it. Unfortunately, so many have simply assumed the superiority of OO that trying to gain any traction here will be difficult, at best.

And for the record, I started whingeing about whether OO sucks back in 2002.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
 Full
 Abbreviated
 Hidden
More | Login | Reply
Loading... please wait.
  • At least, the two places I've worked at that used TT (Socialtext and LiveText) both had gobs and gobs of logic in the templates. And TT's crippled language made dealing with this much harder than dealing with the same thing in Mason, since at least with Perl you have a sane language to use.

    People keep saying TT helps with this problem, but I have yet to see a good example of using it cleanly.

    • Re: (Score:2, Insightful)

      I agree that there are people who abuse TT by putting application logic in templates. But given enough rope, there will always some people who end up hanging themselves, or at best, tripping themselves up.

      TT's language is deliberately "crippled" because it's a presentation language, not a programming language. And the fact that TT makes it so trivially easy to write and use a plugin means that no-one should ever be doing "programming" using TT.

      But they do :-(

      However, that fact that some people don'

      • I think the TT has the fault lines at all the wrong places. Templates have three classes of complexity: static text (obviously a large part of the output); simple interpolation and undemanding logic (loops, conditionals; very common as well); and then hairy complicated formatting stuff with lots of little conditionals and munging and all sorts of wiry bits poking out of the data (common, but only in small amounts). The TT language is far more powerful than necessary for the simple logic but not enough to ha

        • Display logic needs the same facilities for abstraction as business logic.

          Some days, it seems that only four people in the world understand this. (The third is Avi Bryant.)

      • I am convinced there's no such thing as a perfect separation of application and presentation logic.

        That said, we've done quite well with TT in Slash over the years.

  • Maybe it's time to start keeping code that does related stuff, you know, like grabbing from a database and prepping it for desplay, *together*! So when it needs to be tweaked, everything is close by not in 3 or more separate files?
  • I think you bring up an excellent point. I agree that OO can bring in complexity in the cases that you specify. But I would not write off OO in its entirety. I'm very interested in seeing what many other programmers think about this. Thanks -frank
  • You are talking about ravioli code [c2.com].

    • I think that node nicely illustrates what's going on here.

      Lots of insightful comments, as is usually the case with the c2 wiki.

  • A problem that I see is when OO is pushed to solve every problem.

  • One idea - OO makes it easier to cope with state - and this means people write more state-full apis where pure procedural languages would produce more stateless (functional) apis. And state is always more difficult to reason about.

    I don't want to single anything out - but what comes to mind is a hypothetical encoding API - that used to be of the form: my $encoded = encode( $from, $to, $what ); And then it became more OO with: my $encoding = Some::EncodingLib::new( $from, $to ); my $encoded = $encodi