2009-10-28 5 views
7

Ich habe eine Perl-Codebasis, und es gibt viele redundante Funktionen und sie sind über viele Dateien verteilt.Wie kann ich redundanten Code in Perl identifizieren und entfernen?

Gibt es eine bequeme Möglichkeit, diese redundanten Funktionen in der Codebasis zu identifizieren? Gibt es ein einfaches Tool, das meine Codebasis dafür verifizieren kann?

+1

Ich bin mir nicht sicher, was Sie meinen, wenn Sie "redundant" sagen. Sprechen Sie über mehrere Subs, die alle den gleichen Job machen? Oder über Subs, die nie aufgerufen werden? Oder beides? – innaM

Antwort

10

Mit dem Modul B::Xref können Sie Querverweisberichte erstellen.

+0

Ich war auf der Suche nach so etwas ... – someguy

3

Es mag nicht bequem sein, aber das beste Werkzeug dafür ist Ihr Gehirn. Gehen Sie den ganzen Code durch und verstehen Sie seine Zusammenhänge. Versuchen Sie, die üblichen Muster zu sehen. Dann, Refaktor!

Ich habe Ihre Frage mit "refactoring" markiert. Auf dieser Seite finden Sie möglicherweise interessante Informationen zu diesem Thema.

+5

Ich mag den Lagerraum-Refaktor. 1. Überprüfen Sie den Code in Git. 2. Stellen Sie sicher, dass Sie viele Tests haben. 3. Benennen Sie das Modul vollständig in etwas Ungewöhnliches um. 4. Erstellen Sie einen leeren. 5. Kopieren Sie die Funktionen zurück und refactorieren Sie sie so lange, bis die Tests erneut ausgeführt werden. 6. Entfernen Sie nach einem Monat, in dem Funktionen aus dem alten Modul nicht kopiert werden müssen. –

+0

@Ether: Sie haben Recht über Refactoring ... aber zuerst muss ich die Funktionen finden .. :) – someguy

0

Wenn Sie unter Linux arbeiten, können Sie grep verwenden, um die Liste aller Funktionen in Ihrer Codebasis aufzulisten. Sie werden wahrscheinlich tun müssen, was Ether vorschlägt und den Code wirklich durchgehen, um es zu verstehen, wenn Sie es nicht bereits getan haben.

Hier ist ein über vereinfachtes Beispiel:

grep -r "sub " codebase/* > function_list 

Sie nach Duplikaten zu so aussehen können. Diese Idee ist möglicherweise weniger effektiv, wenn Sie die OOP-Funktionalität von Perl verwenden.

Es könnte auch erwähnenswert sein NaturalDocs, ein Werkzeug zur Code-Dokumentation. Dies wird Ihnen helfen, vorwärts zu gehen.

+10

Wenn Sie mit Perl arbeiten, betrachten Sie 'ack', eine reine Perl-Version von' grep' das nutzt Perls mächtigere Regex-Unterstützung. –

8

Ich habe in der Vergangenheit selbst auf dieses Problem gestoßen. Ich habe ein kleines Programm zusammengestellt, das PPI benutzt, um Subroutinen zu finden. Es normalisiert den Code ein wenig (Leerzeichen normalisiert, Kommentare entfernt) und meldet alle Duplikate. Funktioniert einigermaßen gut. PPI macht das ganze schwere Heben.

Sie könnten die Normalisierung etwas schlauer machen, indem Sie alle Variablennamen in jeder Routine auf $ a, $ b, $ c normalisieren und vielleicht etwas ähnliches für Strings tun. Hängt davon ab, wie aggressiv du sein willst.

#!perl 

use strict; 
use warnings; 

use PPI; 

my %Seen; 

for my $file (@ARGV) { 
    my $doc = PPI::Document->new($file); 
    $doc->prune("PPI::Token::Comment");   # strip comments 

    my $subs = $doc->find('PPI::Statement::Sub'); 
    for my $sub (@$subs) { 
     my $code = $sub->block; 
     $code =~ s/\s+/ /;      # normalize whitespace 
     next if $code =~ /^{\s*}$/;    # ignore empty routines 

     if($Seen{$code}) { 
      printf "%s in $file is a duplicate of $Seen{$code}\n", $sub->name; 
     } 
     else { 
      $Seen{$code} = sprintf "%s in $file", $sub->name; 
     } 
    } 
} 
+0

Nizza! Aber warum müssen Sie leere Routinen ignorieren? – innaM

+1

Der Zweck besteht nicht nur darin, redundanten Code zu finden, sondern ihn zu entfernen. Es war schnell offensichtlich, dass das Melden leerer Routinen nur Unordnung war. Mit 'sub foo {} 'ist nichts falsch. Wenn Sie an die Alternative '* foo = \ & DO_NOTHING' denken, die ungefähr so ​​albern ist wie' my $ foo = $ EMPTY_STRING', sollte alles einen Sinn ergeben. – Schwern

Verwandte Themen