¿Cuál es el término para este tipo de refactorización?

33

Estoy seguro de que hay un término para la siguiente refactorización, pero no puedo recordarlo y mi Google-fu me falla.

El refactor mueve si las declaraciones a donde van a tener el mayor impacto, por ejemplo, cambiando esto

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

A esto

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

Respuestas:

56

Este es un movimiento de código invariante de bucle . Un buen compilador debería hacerlo solo.

... el código invariante de bucle consiste en declaraciones o expresiones (en un lenguaje de programación imperativo ) que se pueden mover fuera del cuerpo de un bucle sin afectar la semántica del programa. El movimiento de código invariante de bucle (también llamado elevación o promoción escalar ) es una optimización del compilador que realiza este movimiento automáticamente ...

Si consideramos el siguiente ejemplo de código, se pueden aplicar fácilmente dos optimizaciones.

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

El cálculo x = y + zy x * xse puede mover fuera del ciclo ya que dentro son invariantes , no cambian sobre las iteraciones del ciclo, por lo que el código optimizado será algo como esto:

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

Este código se puede optimizar aún más ...

thiton
fuente
55
un buen programador debe hacerlo por sí mismo, así, supongo
Stijn
8
Estoy de acuerdo @stijn: hay algunas cosas por las que es razonable dejar que el compilador se preocupe, ¡pero esta no es una de ellas!
Toby
@Toby: Si bien esto es cierto para el nuevo código (después de todo, el movimiento invariante del bucle hace que el bucle interno sea más fácil de entender), cualquier cosa que ya haya hecho el compilador no necesita hacerse a mano. Simplemente dejé que el viejo código como el ejemplo anterior se mantenga; La mejora de la calidad de LICM es pequeña y probablemente no valga la pena.
thiton
12
@thiton no estoy de acuerdo. Dejarlo como está significará que todos los futuros mantenedores tendrían que pasar por el mismo razonamiento. Pierde el tiempo; solo cámbialo.
Izkata
2
@zzzzBov sí, lo sé, pero mi punto es que cuando el patrón está oculto, probablemente ya no sea exactamente el patrón. O algo así. (lo siento, día largo)
stijn
10

Esto también se llama hoistingo scalar promotion. Mira aquí :

Alzar significa que ha extraído alguna operación de un bucle porque el bucle en sí no afecta el resultado de la operación. En su caso, está levantando la prueba condicional del ciclo while.

Reordenar significa cambiar la secuencia de instrucciones de una manera que no afecte el resultado. Por lo general, se trata de instrucciones adyacentes sin dependencias de datos, por ejemplo, no importa en qué orden realice las dos declaraciones siguientes:

int a = x;
int b = y;
Friki
fuente
0

No creo que exista tal refactorización.

Por lo tanto, sería difícil encontrarlo entre las "listas de refactorizaciones".

Clasificaría ese ejemplo como una optimización, no como una refactorización .

Refactorizar, para mí, es cambiar el código para mejorar su comprensión sin afectar su comportamiento.

La optimización, para mí, está cambiando el código para mejorar el rendimiento.

Dado que el código optimizado tiende a ser menos fácil de entender. Las dos prácticas tienden a funcionar una contra la otra.

JW01
fuente