Graphing the hierarchy (you won't believe this)

Ovid on 2009-01-30T16:04:48

After sorting the bug in my Class::Sniff post, I had 33 classes to juggle (and this for a database table with effectively only 6 fields to store!). So I decided to turn the output into a png. I can't have them here, so you can view the horror on my LiveJournal.

Feel free to comment either here or there.

Oh, and if you're wondering how I made that nifty graph, remember how I said that using a tree is a huge gain for code simplicity? Yup. Transform it into a graph and print:

my $dump  = Class::Sniff->new($root);
my $graph = Graph::Easy->new;
for my $node ($dump->tree->traverse) {
    my $class = $node->value;
    next if $class eq $root;
    $graph->add_edge_once($node->parent->value, $class);
}

my $graphviz = $graph->as_graphviz;
open my $DOT, '|dot -Tpng -o clip.png' or die "Cannot open pipe to dot: $!";
print $DOT $graphviz;
close $DOT;


Class::C3 is your friend...

melo on 2009-01-30T19:16:48

There is a script in the Class::C3 distribution that does this and much more.

My tweaked version of it is here:

http://github.com/melo/scripts/blob/master/bin/x-perl-c3-visualize

The original is here:

http://cpansearch.perl.org/src/FLORA/Class-C3-0.20/util/visualize_c3.pl

Best regards,

Re:Class::C3 is your friend...

Ovid on 2009-01-30T19:31:27

Sorry, I don't think I was clear about my intent. There are a number of alternatives for doing this, but the name of this project, Class::Sniff, suggests my purpose: searching out code smells in OO code. To this end, merely collecting the hierarchy is the first bit. I also have to look for inappropriate inheritance, multiple inheritance, which methods are overridden where, etc. As a result, I'll eventually need to collect a lot more state about everything and provide analysis tools.

DBIC is C3

Stevan on 2009-01-30T20:33:40

Well, I agree, that inheritance tree does look nasty. However all that MI in DBIC is managed with Class::C3 which checks the sanity of your MI at compile time using the C3 method resolution. Basically mst wanted roles before there was a stable implementation of them so he used MI instead. Being insane but not stupid Matt decided to use Class::C3 to manage his MI. So while it may look really ugly and nasty, it is pretty well through out and not nearly as fragile as traditional Perl MI is (*cough* NEXT.pm *cough*, *cough*, ***gag***, !ack!).

- Stevan

Re:DBIC is C3

Ovid on 2009-01-30T21:33:10

While I agree that Class::C3 is better, I still disagree with multiple inheritance. See my latest write-up about this. I should also note that Matt's done fantastic work with DBIx::Class and this is not directed at him specifically. He's a careful programmer and I appreciate that. That still doesn't avoid that fact that MI is a minefield.

Complexity

jrockway on 2009-01-30T21:31:56

I think you are misinterpreting your diagram. When I see all those modules, I think: "Aha, look at all those subtle complexities I don't have to understand." If DBIC wasn't there, you'd be doing that all yourself.

Unicode is complicated. SQL databases are extremely complicated. Object/relational mapping is complicated. DBIC takes on complexity to hide it from the rest of your app.

Think about what a mess your app would be if you had a home-grown ORM -- you'd have all these complexities, but you'd have to handle them yourself. At least that nightmare is shared among the collective open source community, instead of just you.

I will agree that the mixin-based design is a bit of a relic from the past. If DBIC used roles (via Moose), then all the DBIC stuff would be appear to be one or two classes. But the complexity is the same either way -- meaning that your diagram doesn't really say much.

(If I were to psychoanalyze, I would probably come to the conclusion that you don't like your work app very much, and are taking out your frustration on things that don't deserve it. ;) ;)

Re:Complexity

Ovid on 2009-01-30T21:39:41

I'm quite happy with my job and my work app. It's great. There are just frustrating corners from time to time :)

And with roles, the complexity wouldn't be the same because roles at least provide some compile-time sanity about method conflicts and requirements, something which MI cannot do.

Re:Complexity

Stevan on 2009-01-31T04:06:57

And with roles, the complexity wouldn't be the same because roles at least provide some compile-time sanity about method conflicts and requirements, something which MI cannot do.

Actually C3 does detect some particularly horrid ambiguities that can crop up in MI and via the next::method package it is possible to have a consistent traversal path through your MI hierarchy that is assured to stay consistent no matter what angle you look at it from.

Also, experience has taught me that role requirements and conflicts are not always a happy thing, it can create some really thorny issue as well. With any non-trivial Role or MI usage you are always dealing with the waterbed in the end (push something down and it just pops back up in the other side).

- Stevan