Slash Boxes
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)

  (email not shown publicly)
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)

Monday December 01, 2008
05:23 AM

Rotten Ravioli Code

[ #37992 ]

In my last post, I was talking about the tendency of OO programmers to develop overly complex systems. Aristotle pointed out that I was talking about ravioli code. I've never heard the term before, but it seems perfectly appropriate, particularly given some code I'm trying to understand right now. Before I get there, let's have a look at one of the comments in the "ravioli code" discussion:

Although it often does, I don't think RavioliCode always means that something needs fixing. In OO programming, there seems to be a trade-off between "easy to change" code and "easy to understand at first glance" code. You can try to maximize ease-of-change, then do your best to make the code understandable; or you can try to maximize understandability. I do the former. --StanSilver

Ease of change instead of understandability? Pardon me for quibbling, but what we're looking for is the elusive "maintainability": that combination of ease of change and understandability that hits the sweet spot we all argue over. A blanket favoring of "ease of change" is a disaster. If something is really easy to change but hard to understand, is it not, by definition, easy to misunderstand? Thus, those easy changes might be dead wrong, a problem I've found in some code I'm working on right now. I don't think this is what StanSilver is arguing for, but if we're go for ease of change and then understandability, we all know what happens to developers who say "yeah, I'll get around to that".

$ ack 'XXX|TODO'  lib/ t/ aggtests/ docs/ --all | wc -l

So, turning to the code I'm working on right now, I've decided to try and understand it. Here's a (loose) inheritance heirarchy.

A         A
|         |
B    A    B
|    |    |
C    D    E
\   |   /

(use.perl is messing with that format a bit)

Given that I need to instantiate F, notice anything problematic there? And yes, B does override stuff in A, so you had better hope that:

  • You order your inheritance correctly
  • ... based upon your MRO (method resolution order)

And do C, D and E have any identically named methods? We're not calling "next::method" much internally, but even if we did, this level of complexity helps to illustrate why some languages simply outlaw multiple inheritance: it's too dangerous to abuse.

By the way, it's worse than that diagram implies. The hierarchy ignores that various subroutines are exported into some classes (subs, not methods) and we have three traits loaded into F. After working like mad to understand the various classes involved, I ran some tests with an instance of "F". I used the debugger to dump out the method and it identifies 144 methods on the F object. These methods are from nine packages. What it doesn't do is show you how the traits often "wrap" the methods to alter their behavior. It also doesn't show which of those methods are documented as being overridden. It also doesn't show which overriding methods should not have their parent called. It also doesn't show which overriding methods should have their parents called. It also doesn't show which methods just crept in there by accident just because the hierarchy is so complicated.

Now if you'll excuse me, I need to go find some aspirin.

The Fine Print: The following comments are owned by whoever posted them. We are not responsible for them in any way.
More | Login | Reply
Loading... please wait.
  • The choice that is being described I believe is the choice between code that is easy to modify, and code that is transparent to someone who is new to the code base. For code to be easy to modify it must also be easy for the modifier to understand. However it need not be easy for an uninitiated programmer to figure out.

    As an example, my first experience of functional techniques lead to 20 minutes of head scratching until I finally found the section of code that did the work, and figured out how it worked.