So I want a class inspector which will let me check for some common code smells in classes. As mentioned previously, I have a class with 255 methods spread across 27 packages. That's a bit unwieldy. My first pass, replicating what so many before me have done:
package Class::Sniff;
use Class::BuildMethods qw/ tree target /;
use Tree;
sub new {
my ( $class, $target_class ) = @_;
my $self = bless {} => $class;
$self->target($target_class);
$self->_initialize;
return $self;
}
sub _initialize {
my $self = shift;
my $target_class = $self->target;
$self->tree(Tree->new($target_class));
$self->_add_parents($self->tree);
}
sub _add_parents {
my ($self,@nodes) = @_;
for my $node (@nodes) {
my $class = $node->value;
no strict 'refs';
my @parent_classes = map { Tree->new($_) } @{"$class\::ISA"};
# Oops. Don't "return" here
next unless @parent_classes;
$node->add_child(@parent_classes);
$self->_add_parents(@parent_classes);
}
}
1;
And dumping out the inheritance hierarchy:
my $dump = Class::Sniff->new('PIPs::ResultSource::Clip');
for my $node ($dump->tree->traverse) {
print ' ' x $node->depth;
print $node->value, "\n";
}
__END__
PIPs::ResultSource::Clip
PIPs::ResultSourceBase::ClipEpisode
PIPs::ResultSourceBase::ContentObject
PIPs::ResultSourceBase::AuditedObject
PIPs::ResultSourceBase::Pips
DBIx::Class::UndefToEmptyString
DBIx::Class::UTF8Columns
PIPs::DBIx::Class::RecordChange
DBIx::Class::Core
DBIx::Class
Util::Class
PIPs::ResultSourceBase::HaveIdentifiers
PIPs::ResultSourceBase::Pips
DBIx::Class::UndefToEmptyString
DBIx::Class::UTF8Columns
PIPs::DBIx::Class::RecordChange
DBIx::Class::Core
DBIx::Class
Util::Class
PIPs::ResultSourceBase::HasParentBrand
Hmm, not 27 classes there. Either the debugger is wrong or we have packages exporting things in a few places.
So it's clear that we have some issues with inheritance, but much of this is is DBIx::Class is designed (great module, by the way). I am reinventing the wheel but by using a tree for tracking inheritance, I think I can gain some wins in code simplicity for more things I want to do. We'll see.
Update: Oops. jplindstrom saw the output was wrong. Turns out that return unless @parent_classes; should be next unless @parent_classes;. That reveals a grand total of 33 classes, not counting UNIVERSAL.