Was ist der Begriff für diese Art von Refactoring

33

Ich bin mir sicher, dass es einen Begriff für das folgende Refactoring gibt, aber ich kann mich nicht daran erinnern, und mein Google-Fu hat mich verfehlt!

Der Refaktor bewegt sich, wenn Anweisungen dahin gehen, wo sie den größten Einfluss haben, z. B. um dies zu ändern

$test = someFunctionThatReturnsABool();
for($x = 0; $x < 10000; $x++) {
    if ($test) { 
        echo $x; 
    }
}

Dazu

$test = someFunctionThatReturnsABool();
if ($test) {
    for($x = 0; $x < 10000; $x++) {
        echo $x; 
    }
}
Toby
quelle

Antworten:

56

Dies ist eine schleifeninvariante Codebewegung . Ein guter Compiler sollte es alleine machen.

... Schleifeninvarianter Code besteht aus Anweisungen oder Ausdrücken (in einer imperativen Programmiersprache ), die außerhalb des Schleifenkörpers verschoben werden können, ohne die Semantik des Programms zu beeinflussen. Loop-invariante Codebewegung (auch als Hebe- oder Skalar-Promotion bezeichnet ) ist eine Compiler-Optimierung, die diese Bewegung automatisch ausführt ...

Wenn wir das folgende Codebeispiel betrachten, können zwei Optimierungen problemlos angewendet werden.

for (int i = 0; i < n; i++) {
    x = y + z;
    a[i] = 6 * i + x * x;
}

Die Berechnung x = y + zund x * xkann außerhalb der Schleife verschoben werden, da sie innerhalb der Schleife invariant sind - sie ändern sich nicht über die Iterationen der Schleife -, sodass der optimierte Code ungefähr so ​​aussieht:

x = y + z;
t1 = x * x;
for (int i = 0; i < n; i++) {
    a[i] = 6 * i + t1;
}

Dieser Code kann weiter optimiert werden ...

Thiton
quelle
55
ein guter Programmierer soll es auf es tun ist selbst auch, ich denke
Stijn
8
Ich stimme @stijn zu - es gibt einige Dinge, über die sich der Compiler Gedanken machen sollte, aber dies ist keine davon!
Toby
@Toby: Während dies für neuen Code zutrifft (schließlich stellt die schleifeninvariante Bewegung eine verständlichere innere Schleife dar), muss alles, was bereits vom Compiler ausgeführt wird, nicht von Hand ausgeführt werden. Ich würde einfach alten Code wie den obigen stehen lassen. Die Qualitätsverbesserung von LICM ist gering und wahrscheinlich Ihre Zeit nicht wert.
Thiton
12
@thiton Ich stimme nicht zu. Wenn Sie es so lassen, wie es ist, müssen alle zukünftigen Betreuer die gleichen Überlegungen anstellen. Es verschwendet Zeit; ändere es einfach.
Izkata
2
@zzzzBov ja ich weiß, aber mein Punkt ist, dass wenn das Muster versteckt ist, es wahrscheinlich nicht mehr genau das Muster ist. Oder etwas ähnliches. (Entschuldigung, langer Tag)
stijn
10

Dies wird auch als hoistingoder bezeichnet scalar promotion. Sehen Sie hier :

Heben bedeutet, dass Sie eine Operation aus einer Schleife gezogen haben, da die Schleife selbst das Ergebnis der Operation nicht beeinflusst. In Ihrem Fall heben Sie den bedingten Test aus der while-Schleife heraus.

Nachbestellen bedeutet, die Reihenfolge der Anweisungen so zu ändern, dass das Ergebnis nicht beeinträchtigt wird. In der Regel handelt es sich hierbei um benachbarte Anweisungen ohne Datenabhängigkeit. Es spielt also keine Rolle, in welcher Reihenfolge Sie die folgenden beiden Anweisungen ausführen:

int a = x;
int b = y;
Aussenseiter
quelle
0

Ich glaube nicht, dass es ein solches Refactoring gibt.

Daher wäre es schwierig, es in den „Listen der Umgestaltungen“ zu finden.

Ich würde dieses Beispiel als Optimierung und nicht als Refactoring einstufen .

Refactoring bedeutet für mich, den Code zu ändern, um seine Verständlichkeit zu verbessern, ohne sein Verhalten zu beeinträchtigen.

Optimierung bedeutet für mich, den Code zu ändern, um die Leistung zu verbessern.

Da optimierter Code tendenziell weniger leicht zu verstehen ist. Die beiden Praktiken arbeiten in der Regel gegeneinander.

JW01
quelle