2014-04-28 3 views
8

Ich bin neu in Perl und bin gerade damit beschäftigt, ein großes und ziemlich unordentliches Perl-Projekt aufzuräumen und zu warten. Ich benutze Perl-Kritiker, um mir zu helfen, Probleme im Code zu erkennen (und mir auch Best Practices beizubringen).Wie erkennt man nicht erreichbaren Code in Perl-Bedingung, die immer als falsch auswertet?

Der vorhandene Code enthält Stellen, an denen der Coder nicht erreichbaren Code erstellt hat. So fügten sie ‚& & 0‘ als faule Art der Kommentierung einige der Code verzweigt:

if ($req->param('donut') && 0) { 
    unreachable code... 
} else { 
    always branches to here... 
} 

ich gehofft hatte, dass Perl oder Kritiker würde mich über nicht erreichbare Code in solchen Fällen warnen (wo ein conditional hat einen konstanten Wert, der zu false auswertet), tut es aber nicht.

Gibt es ein Werkzeug oder ein Stück Skript, das ich verwenden könnte, das solche Dinge zuverlässig erkennen kann?

Offensichtlich konnte ich für ‚& & 0‘ in der Quelle suchen, aber es gibt eine Reihe von Möglichkeiten, wie die Codierer nicht erreichbar Code erstellt haben, könnten neben anfügen von ‚& & 0‘ zu einer if-Anweisung.

Antwort

9

B::Deparse verwenden, können Sie nicht erreichbar Code in einigen Situationen erkennen:

perl -MO=Deparse -e 'if (0 && $x) {print 1} else {print 2}' 
do { 
    print 2 
}; 
-e syntax OK 

Es ist nicht so einfach, wenn die 0 nicht die erste Bedingung ist, aber:

perl -MO=Deparse -e 'if ($x && 0) {print 1} else {print 2}' 
if ($x and 0) { 
    print 1; 
} 
else { 
    print 2; 
} 
-e syntax OK 

Warum ist es anders? Nun, wenn 0 zuletzt kommt, müssen alle Bedingungen überprüft werden. Sie können Nebenwirkungen haben, die noch passieren werden. Außerdem erzwingt && einen skalaren Kontext, sodass das Verhalten des aufgerufenen Codes bei der Auswertung der Bedingung geändert werden kann.

Dies erklärt nicht, warum der Block selbst nicht kompiliert wird, sorry. Ich vermutete, es wäre einfach zu kompliziert.

+0

+1 für die Information über B :: Deparse.Obwohl mir die Nebenwirkung des ersten Teils des Konditionals klar war (was bedeutet, dass der Bedingungsausdruck selbst nicht kompiliert werden kann), war mir nicht bewusst, dass der Kontext, der durch den zweiten Teil des Konditionals eingeführt wurde, geändert wurde . –

5

Laut chorobas Antwort kann B :: Deparse Ihnen Fälle zeigen, in denen der Code so offensichtlich unerreichbar ist, dass der Perl-Compiler ihn optimiert. Aber im allgemeinen Fall ist es unmöglich zu erkennen. Der folgende Code enthält einen effektiv nicht erreichbaren Block.

use 5.006; 

if ($] < 5) { ... } 

Da $] eine Variable, die die aktuell ausgeführte Version von Perl gibt, die garantiert mindestens 5.006 durch die use Linie. Aber Sie würden ein paar ziemlich clevere Techniken brauchen, um das herauszufinden, indem Sie eine statische Analyse des Quellcodes verwenden. (Nebenbei, obwohl eine ungewöhnliche Sache zu tun ist, ist es möglich, den Wert von $] zur Laufzeit zu ändern - siehe Acme::Futuristic::Perl - in diesem Fall wird der Code erreichbar sein.)

Wenn Sie eine anständige Testsuite haben Für Ihren Code könnte Devel::Cover nützlich sein. Sie setzen die Umgebungsvariable PERL5OPT auf -MDevel::Cover, dann führen Sie Ihre Testsuite aus (beachten Sie, dass es etwas langsamer als gewöhnlich läuft), dann führen Sie den Befehl cover aus, der einen hübschen HTML-Bericht erzeugt. Dieser Bericht wird hervorheben, welche Subs nicht ausgeführt wurden, welche Zweige nie benutzt wurden, usw.

Verwandte Themen