Ejerciciós básicos de Refactorización

-
Ejercicio 1

El siguiente código, evidentemente, ha sido actualizado varias veces a lo largo de los años, pero los cambios no han mejorado su estructura. Refactorizar!



if (state == TEXAS) {
rate = TX_RATE;
amt = base * TX_RATE;
calc = 2*basis(amt) + extra(amt)*1.05;
}
else if ((state == OHIO) || (state == MAINE)) {
rate = (state == OHIO) ? OH_RATE : MN_RATE;
amt = base * rate;
calc = 2*basis(amt) + extra(amt)*1.05;
if (state == OHIO)
points = 2;
}
else {
rate = 1;
amt = base;
calc = 2*basis(amt) + extra(amt)*1.05;
}




Solución

Podríamos sugerir una reestructuración bastante suave aquí: asegúrese de que cada prueba se realiza sólo una vez, y hacer todos los cálculos comunes. Si la expresión 2 * base (...) * 1.05 aparece en otros lugares en el programa, se debe, probablemente hacer una función. En este caso no es necesario.

Hemos añadido un arreglo rate_lookup, inicializado para que las entradas distintos de Texas, Ohio y Maine tengan un valor de 1. Este enfoque hace que sea fácil de agregar los valores de otros estados a futuro.




rate = rate_lookup[state];
amt = base * rate;
calc = 2*basis(amt) + extra(amt)*1.05;
if (state == OHIO)
points = 2;



Ejercicio 2


Las siguientes clases Java necesitan soportar más "shapes". Refactorize la clase.



public class Shape {
public static final int SQUARE = 1;
public static final int CIRCLE = 2;
public static final int RIGHT_TRIANGLE = 3;

private int shapeType;
private double size;
public Shape(int shapeType, double size) {
this.shapeType = shapeType;
this.size = size;
}
// ... other methods ...
public double area() {
switch (shapeType) {
case SQUARE: return size*size;
case CIRCLE: return Math.PI*size*size/4.0;
case RIGHT_TRIANGLE: return size*size/2.0;
}
return 0;
}
}




Solución

Cuando usted ve a alguien usando los tipos enumerados (o sus equivalente en Java) para distinguir entre las variantes de un tipo, a menudo se puede mejorar el código por medio de subclases:



public class Shape {
private double size;
public Shape(double size) {
this.size = size;
}
public double getSize() { return size; }
}
public class Square extends Shape {
public Square(double size) {
super(size);
}
public double area() {
double size = getSize() ;
return size*size;
}
}
public class Circle extends Shape {
public Circle(double size) {
super(size);
}
public double area() {
double size = getSize();
return Math.PI*size*size/4.0;
}
}
// etc...





Ejercicio 3

Este código de Java es parte de un framework que se utilizará a través de su proyecto. Refactorizar para ser más general y más fácil de ampliar en el futuro.



public class Window {
public Window(int width, int height) { ... }
public void setSize(int width, int height) { ... }
public boolean overlaps(Window w) { ... }
public int getArea() { . . . }
}




Solución

Este caso es interesante. A primera vista, parece razonable que un "window" (ventana) deba tener una anchura y una altura. Sin embargo, tenga en cuenta el futuro. Imaginemos que queremos apoyar de manera arbitraria las formas de las ventanas. (que será difícil, si sabe que la clase window conoce todo acerca de los rectángulos y sus propiedades).

Sugerimos abstraer la forma de la ventanas de la Clase window.



public abstract class Shape {
// ...
public abstract boolean overlaps(Shape s);
public abstract int getArea();
}
public class Window {
private Shape shape;
public Window(Shape shape) {
this.shape = shape;
...
}
public void setShape(Shape shape) {
this.shape = shape;
...
}
public boolean overlaps(Window w) {
return shape.overlaps(w.shape);
}
public int getArea() {
return shape.getArea();
}
}





También se podría haber extendido este ejemplo mediante la introducción de una interface Java, que especifica los métodos de una clase de apoyo que debe ser compatible con las funciones de shape.

Fuente : ThePragmatic Programmer: From Journeyman to Master

Comentarios