Refactoring:

Aprender cuándo y cómo refactorizar a partir de ejemplos

Adela Tort

@AdelaTort

Women Techmakers Tarragona 2015

Adela Tort

Java Senior Developer en Edreams

Colaboradora del Barcelona Java Users Group 

Seguidora del movimiento de la artesanía del software y aspirante a Software Craftman

@AdelaTort

https://www.linkedin.com/in/adelatort

adela.tort@gmail.com

Refactoring

  • ¿Qué es refactorizar?
  • ¿Por qué y cuándo se debe refactorizar? 
  • ¿Cómo refactorizar?
    • Ciclo de refactorización
    • Bad smells
    • Patrones de refactorización

¿Qué es refactorizar?

  • También conocido como 'limpiar el código'.

  • Cambios realizados en el software para hacerlo más fácil de modificar y comprender.

  • La refactorización es la parte del mantenimiento del código que no arregla errores ni añade funcionalidad.

¿Por qué y cuándo se debe refactorizar?

¿Por qué refactorizar? (I)

  • Mantener el código limpio 

  • Evitar problemas típicos que aparecen con el tiempo:
    • Cambios que provocan pérdida de estructura y dificultat de ver y preservar el diseño.
    • Código duplicado que hacen las mismas cosas.

  •  

¿Por qué refactorizar? (II)

  • Mejorar el mantenimiento y la legibilidad

  • Diseño evolutivo

¿Cuándo refactorizar?

  • Cuando añadas una nueva funcionalidad
    • Refactorizar el código existente hasta entenderlo y el diseño para facilitar añadir la funcionalidad

  • Cuando busques y soluciones bugs
    • Refactorizar para entender el código

  • Cuando hagas code review's
    • Refactorizar para mejorar la calidad del código revisado

¿Cómo refactorizar?

Ciclo de refactorización

Bad smells

  • Código duplicado
  • Métodos largos
  • Clase grande
  • Lista larga de parámetros
  • Identificadores excesivamente largos o cortos
  • Uso excesivo de métodos de otra clase
  • Detalles de implementación de otra clase
  • Complejidad ciclomática
  • Comentarios

Patrones de refactorización

Renombrar variables

public class ShoppingCart{
    private List<Product> products;

    public Double getTotalPrice(){
        Double p=0.0;
        for(Product prod: products){
            p=p+prod.getPrice();
        }
        return p;
    }
}
public class ShoppingCart{
    private List<Product> products;

    public Double getTotalPrice(){
        Double totalPrice=0.0;
        for(Product product: products){
            totalPrice=totalPrice+product.getPrice();
        }
        return totalPrice;
    }
}

Encapsular campos

public class Product {
    public String name;
}
public class Product {
    private String name;

    public void setName(String name){
        this.name = name;
    }

    public String getName(){
        return name;
    }
}

Extraer método

public Double calculatePrice(){
    Double totalPrice = 0.0;
    for(Product p : products){
        totalPrice = totalPrice + p;
    }
    if(totalPrice > 100) {
        totalPrice = totalPrice - 10;
    }
    return totalPrice; 
}
public Double calculatePrice(){
    Double totalPrice = calculateProductsPrice();
    return applyDiscounts(totalPrice); 
}

private Double calculateProductsPrice(){
    Double totalPrice = 0.0;
    for(Product p : products){
        totalPrice = totalPrice + p;
    }
    return totalPrice; 
}

private Double applyDiscounts(Double price){
    Double priceWithDiscounts=price;
    if(price> 100) {
        priceWithDiscounts=priceWithDiscounts- 10;
    }
    return priceWithDiscounts;
}

Descomponer condicional


 if (date.before (SUMMER_START) || date.after(SUMMER_END))
   charge = quantity * _winterRate + _winterServiceCharge;
 else charge = quantity * _summerRate;

 if (notSummer(date))
    charge = winterCharge(quantity);
 else charge = summerCharge (quantity);

Extraer clase

Extraer super clase

Reemplazar condicional con polimorfismo

public Float getArea() {
  switch (type) {
    case RECTANGLE:
      return getWidth()*getHeight();
    case CIRCLE:
      return getPi()*getRadius()*getRadius();
    case TRIANGLE:
      return (getBase()*getHeight())/2;
  }
  throw new RuntimeException ("Unexpected type");
}

Reemplazar código de error con excepción

public Integer getAmount(int quantity){
    if(quantity > numAvailable){
        return -1;
    }
    else{
        return quantity * price;
    }
}
public Integer getAmount(int quantity) throws UnavailableProductException {
    if(quantity > numAvailable){
        throw new UnavailableProductException();
    }
    else{
        return quantity * price;
    }
}

Resources

Preguntas

Primera gran conferencia de Java y JVM en España

Refactoring: Aprender cuándo y cómo refactorizar a partir de ejemplos

By atort

Refactoring: Aprender cuándo y cómo refactorizar a partir de ejemplos

  • 2,003