Class-Sniff

 view release on metacpan or  search on metacpan

lib/Class/Sniff.pm  view on Meta::CPAN

 sub inc {
    my ( $self, $value ) = @_;
    return $value + 1;
 }

 sub increment {
    my ( $proto, $number ) = @_;
    return $number + 1;
 }

However, this will not match the above methods:

 sub increment {
    my ( $proto, $number ) = @_;
    return 1 + $number;
 }

=head3 Code Smell:  duplicate methods

This is frequently a sign of "cut and paste" code.  The duplication should be
removed.  You may feel OK with this if the duplicated methods are exported
"helper" subroutines such as "Carp::croak".

=cut
sub duplicate_methods {
    my $self = shift;
    my @duplicates;
    foreach my $methods ( values %{ $self->{duplicates} } ) {
        if ( @$methods > 1 ) {
            push @duplicates => $methods;
        }
    }
    return @duplicates;
}

=head2 C<long_methods> (highly experimental)

 my $num_long_methods = $sniff->long_methods;
 my %long_methods     = $sniff->long_methods;

Returns methods longer than C<method_length>.
This value defaults to 50 (lines) and
can be overridden in the constructor (but not later).

=over 4

=item * How to count the length of a method.

 my $start_line = B::svref_2object($coderef)->START->line;
 my $end_line   = B::svref_2object($coderef)->GV->LINE;
 my $method_length = $end_line - $start_line;

The C<$start_line> returns the line number of the I<first expression> in the
subroutine, not the C<sub foo { ...> declaration.  The subroutine's
declaration actually ends at the ending curly brace, so the following method
would be considered 3 lines long, even though you might count it differently:

 sub new {
     # this is our constructor
     my ( $class, $arg_for ) = @_;
     my $self = bless {} => $class;
     return $self;
 }

=cut

sub long_methods { %{ $_[0]->{long_methods} } }

=item * Exported methods

These are simply ignored because the C<B> modules think they start and end in
different packages.

=item * Where does it really start?

If you've taken a reference to a method I<prior> to the declaration of the
reference being seen, Perl might report a negative length or simply blow up.
We trap that for you and you'll never see those.

=back

Let me know how it works out :)

=head3 Code Smell:  long methods

Note that long methods may not be a code smell at all.  The research in the
topic suggests that methods longer than many experienced programmers are
comfortable with are, nonetheless, easy to write, understand, and maintain.
Take this with a grain of salt.  See the book "Code Complete 2" by Microsoft
Press for more information on the research.  That being said ...

Long methods might be doing too much and should be broken down into smaller
methods.  They're harder to follow, harder to debug, and if they're doing more
than one thing, you might find that you need that functionality elsewhere, but
now it's tightly coupled to the long method's behavior.  As always, use your
judgment.

=head2 C<parents>

 # defaults to 'target_class'
 my $num_parents = $sniff->parents;
 my @parents     = $sniff->parents;

 my $num_parents = $sniff->parents('Some::Class');
 my @parents     = $sniff->parents('Some::Class');

In scalar context, lists the number of parents a class has.

In list context, lists the parents a class has.

=head3 Code Smell:  multiple parens (multiple inheritance)

If a class has more than one parent, you may have unreachable or conflicting
methods.

=cut

sub parents {
    my ( $self, $class ) = @_;
    $class ||= $self->target_class;
    unless ( exists $self->{classes}{$class} ) {



( run in 1.956 second using v1.01-cache-2.11-cpan-f56aa216473 )