Refactoring en Español (3)

Palabras clave:
Tiempo aproximado: 3 min.
Seguimos con el ejemplo de refactor del ejemplo del “videoclub”.

En esta entrega vamos a hacer un cambio parecido al de la entrega anterior (donde transformamos el método Customer.amountFor a Rental.getCharge), pero en este caso moveremos crearemos el método Customer.getFrequentRenterPoints y luego lo moveremos a Rental.

Extracting Frequent Renter Points

Decíamos al final de la entrega anterior que Fowler proponía un último refactor, pero que lo posponíamos. Ahora sí lo hacemos porque veréis que, en mi modesta opinión, es más afín a los siguientes cambios.

1. En Customer.statement sustituimos las ocurrencias de thisAmount por each.getRental(). (En Eclipse, si hacemos doble-click sobre thisAmount veremos que se iluminan todos los puntos donde se usa la variable).
2. Eliminamos la declaración de thisAmount

El código queda como:
[code lang=”java” highlight=”11,12″]
while (rentals.hasMoreElements()) {
Rental each = (Rental) rentals.nextElement();
// add frequent renter points
frequentRenterPoints++;
// add bonus for a two day new release rental
if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE)
&& each.getDaysRented() > 1)
frequentRenterPoints++;
// show figures for this rental
result += "\t" + each.getMovie().getTitle() + "\t"
+ String.valueOf(each.getCharge()) + "\n";
totalAmount += each.getCharge();
}
[/code]

Hemos hecho este cambio para así eliminar el uso de thisAmount y ver más claro
el uso que se está haciendo de las demás variables locales. ¡No olvidemos pasar los tests!

Ahora nos fijamos en frequentRenterPoints.

Extraemos el método getFrequentRenterPoints (marcando desde el comentario “add frequent renter points” hasta el comentario “show figures for this rental” y haciendo Alt+Shift+M), pero nos quedará “un poco raro” porque estaremos incrementando la variable y luego asignando su valor en Customer.statement. Así que seguiremos refactorizando hasta tener en Customer.statement la siguiente linea:

[code lang=”java”]
frequentRenterPoints += getFrequentRenterPoints(each);
[/code]

Obsérvese que:
a) quitamos el parámetro frequentRenterPoints de la firma del método getFrequentRenterPoints que nos ha generado Eclipse. Hay que cambiarlo a mano, ahí ya no nos puede ayudar Eclipse. 🙂
b) acumulamos el valor fuera del método (de ahí el “+=”); hay que cambiar el código del método para mantener la integridad semántica. Customer.getFrequentRenterPoints devuelve los valores 1 o 2 (dependiendo de si le corresponde bonus o no a la película que se está alquilando).
c) dado que, no sólo creamos un nuevo método sino que además cambiamos la semántica de las líneas de código originales, es muy importante que pongamos atención al javadoc del método

[code lang=”java”]
/**
* Returns the renter points corresponding to each rental. A two day new
* release rental comes with a bonus.
*
* @param each
* @return
*/
private int getFrequentRenterPoints(Rental each) {
// add bonus for a two day new release rental
if ((each.getMovie().getPriceCode() == Movie.NEW_RELEASE)
&& each.getDaysRented() > 1) {
return 2;
}
return 1;
}
[/code]

TESTS

Después de este cambio, vemos que Customer.getFrequentRenterPoints no tiene nada
que ver con Customer, por lo que hacemos lo mismo que hicimos con Rental.getCharge
y nos llevamos este método a Rental.

Para ello usamos Alt+Shift+V (pero esta vez desmarcamos la opción de crear el método
delegado), con lo que directamente Eclipse nos cambia la linea anterior a:

[code lang=”java”]
frequentRenterPoints += each.getFrequentRenterPoints();
[/code]

El resultado final de Rental.getFrequentRenterPoints es:

[code lang=”java”]
/**
* Returns the renter points corresponding to the rental.
* A two day new release rental comes with a bonus.
*
* @param frequentRenterPoints
* @return
*/
int getFrequentRenterPoints() {
if ((getMovie().getPriceCode() == Movie.NEW_RELEASE)
&& getDaysRented() > 1) {
return 2;
} else {
return 1;
}
}
[/code]

Observad el matiz del cambio en el javadoc.

TESTS y listo.