2008-11-26 17 views
5

El método de refactorización Reemplazar temperatura con consulta se recomienda bastante ahora pero parece ser muy ineficiente con muy poca ganancia.Reemplazar temperatura con consulta

El método desde el sitio del Martin Fowler da el siguiente ejemplo:

Extracto de la expresión en un método. Reemplaza todas las referencias a la temperatura con la expresión. El nuevo método se puede usar en otros métodos.

double basePrice = _quantity * _itemPrice; 
    if (basePrice > 1000) 
     return basePrice * 0.95; 
    else 
     return basePrice * 0.98; 

convierte

if (basePrice() > 1000) 
     return basePrice() * 0.95; 
    else 
     return basePrice() * 0.98; 


double basePrice() { 
    return _quantity * _itemPrice; 
} 

Por qué es una buena idea? seguramente significa que el cálculo se repite innecesariamente y usted tiene la ventaja de llamar a una función. Sé que los ciclos de CPU son baratos, pero arrojarlos así parece descuidado.

¿Echo de menos algo?

+0

¿qué idioma/plataforma estás usando? – Javier

Respuesta

2

Está destinado a ser más revelador de la intención del código. En algunos casos puede ser abusado pero no probable. por ejemplo, puede actualizar las consultas para los descuentos del 5% y del 2% con consultas, pero en el nombre de los métodos que podría describir en el nombre del motivo del descuento. recuerde, puede ser obvio hoy, pero en 6 meses podría no ser así, como digo, no es una cuestión si lo olvido, pero cuando lo olvido.

if (basePrice() > 1000) 
    return bigTicketDiscount() 
    else 
    return regularDiscount() 

double bigTicketDiscount(){ 
    return basePrice() * 0.95; 
} 

double regularDiscount(){ 
    return basePrice() * 0.98 
} 
+2

El problema es que si lee la página de Fowler sobre el asunto (enlace en mi respuesta), verá que el código citado en la pregunta (que implica que está abusando del concepto) proviene directamente de Fowler. Tu sugerencia parece estar cambiando el enfoque de lo que Fowler parece estar diciendo. –

+0

mi punto sobre el abuso fue que es posible si comienzas a hacerlo en el extremo no es bueno y podría ver su abuso. Creo que su intención es simplificar el código que es complejo y oscurecedor: después de todo, es una técnica y si no funciona para usted, no lo haga. – MikeJ

0

Realmente me parece que al hacer esto estás ayudando a hacer un único propósito para tu método original; Ya no es responsable de calcular el precio base y el precio de descuento (o lo que sea que esté calculando). Este es un ejemplo de sacrificar algunos ciclos de CPU para hacer que el código sea más fácil de mantener. Los ciclos de CPU "desperdiciados" probablemente no sean algo que notará para uno y también es posible que el compilador pueda optimizarlo (tal vez al notar que el método es relativamente simple y en lugar de llamar al método, inserta el código real (más como un macro). De todos modos, este tipo de optimizaciones se dejan mejor a las máquinas, dejando a las personas con código más limpio para trabajar.

+0

El ejemplo de James Curran es lo suficientemente limpio para el gusto, ¿no?Creo que hacerlo así dará el mayor "valor para los ciclos de CPU": para la CPU, solo 1 salto de pila es más costoso, pero aún así tienes tu legibilidad. – bungrudi

4

Al haber leído webpage on it de Fowler, no veo ninguna ventaja de hacerlo de esa manera. aislar una expresión que puede ser utilizado a menudo en un solo lugar, pero que sería mejor manejado por:

double basePrice = basePrice(); 
    if (basePrice > 1000) 
      return basePrice * 0.95; 
    else 
      return basePrice * 0.98; 

Fowler no ofrece ninguna explicación de por qué su código revisado es Bett er que el original, aparte de leer su libro.

+0

Su forma parece tener más sentido, pero creo que Fowler simplemente está tratando de ilustrar, aunque extremadamente, lo que parece cuando abstrae el cálculo del precio base por su propio método. – CodyBugstein

2

Creo que la mayor parte de la utilidad de esta refactorización no proviene de su aplicación por sí misma, sino como un paso hacia un método de extracción que es extremadamente común y útil. En los casos en que la variable local se interpone en el modo de Extraer el Método o lo complica con parámetros adicionales, 'reemplazar temperatura con ayuda de consulta' hace que el Método de Extracción sea más fácil. También en esos casos, el método de consulta que se genera se reutiliza por dos métodos diferentes que son el resultado del método de extracción.

2

Hay algo más sobre Reemplazar temporal con la consulta en el libro Refactoring y es:

Usted puede estar preocupado por el rendimiento en este caso. Al igual que con otros problemas de rendimiento, déjelo deslizar por el momento. Nueve veces de cada diez, no importará. Cuando sí importa, reparará el problema durante la optimización.Con su código mejor factorizado, a menudo encontrará más poderosas optimizaciones , que se habría perdido sin refactorizar. Si empeora, es muy fácil volver a poner la temperatura.

2

Es una refactorización que es importante ya que se trata de una refactorización hacia una sola responsabilidad, ¡es una resolución de DRY fail!

El principal problema con las temperaturas (especialmente en el código ingenuo que utiliza métodos largos, ¡cientos de líneas de longitud!) Es que son mutables, de estado local. El riesgo obvio (según lo discutido por Fowler?) Es que alguien podría hacer un cambio a mitad de un largo método y romper algo al final. (Han visto incurrir en este costo)

No hay pruebas, este método tiene innumerables dependencias, ¡qué desorden! :)

Eliminar la temperatura se trata de la refactorización hacia la responsabilidad única.

Ejemplo: hoy encontré un error y se trata de pasar la variable temporal incorrecta a un servicio. Si elimino las temperaturas (hay varias, todas las cadenas), ese error (supervisión) simplemente no puede suceder.

La razón por la que mi método tiene una variable temporal es que está haciendo un trabajo que no debería ... y esta lógica se repite en clases similares ... ¿es consistente? ¡NO!

Al eliminar la temperatura, también voy a refactorizar el código en una clase con la responsabilidad adecuada, que se puede cubrir en un 110% mediante unas simples pruebas.

Sin gran accesorio para probar algo trivial

Si llamo algo caro, voy a devolver el resultado como un valor de objeto/agregado. El 'código temporal' debería ser internalizado por el agregado, probablemente.

Por lo tanto, quitar la temperatura lo empuja a la responsabilidad centralizada (singular) -> SOLIDO!

0

Estoy volviendo a leer la refabricación en este momento y una razón es la siguiente cita desde el final de Extract Method p.116.

Antecedentes: Describe que es difícil Extract Method si el código para extraer utiliza variables locales.

Las variables temporales a menudo son tan abundantes que hacen que la extracción sea muy incómoda. En estos casos, trato de reducir las temperaturas utilizando Replace Temp with Query (120). ...

De modo que una refactorización puede depender de que primero se haga otra refactorización que no es obvia. Otro ejemplo es Inline Method antes de reemplazar Method with Method Object.