Refactoring en Español (3)

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:

        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();
        }

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:

            frequentRenterPoints += getFrequentRenterPoints(each);

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

    /**
     * Returns the renter points corresponding to each rental. A two day new
     * release rental comes with a bonus.
     *
     *  each
     *  
     */
    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;
    }

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:

            frequentRenterPoints += each.getFrequentRenterPoints();

El resultado final de Rental.getFrequentRenterPoints es:

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

Observad el matiz del cambio en el javadoc.

TESTS y listo.

Tagged: