Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Re Factoring
Re Factoring
Refactoring
Tabla de contenidos Introduccin: un ejemplo de refactoring Principios en refactoring
Definiciones y orgenes Por qu y cuando refactorizar? Problemas con las refactorizaciones
Miscelneo:
Herramientas Metodologas giles Definicin de nuevas refactorizaciones (Big Low) Conclusiones Fowler, Refactoring: Improving the Design of Existing Code, AddisonWesley, 1999
1
Bibliografa
Refactorizacin - Refactoring
Introduccin
Definicin
Refactoring son una serie de pequeas transformaciones, cada uno de las cuales cambia la estructura interna del programa sin cambiar su comportamiento externo.
Refactoring
Se parte de cdigo existente y con el diseo subyacente en l Limpia el cdigo para minimizar el coste de los cambios Mejora el diseo del cdigo una vez que este ha sido escrito
Refactorizacin - Refactoring
Customer statement()
Refactorizacin - Refactoring
Class Movie
public class Movie { public static final int public static final int public static final int private String _title; private int _priceCode; public Movie(String title, int priceCode) { _title = title; _priceCode = priceCode;
}
Refactorizacin - Refactoring
Class Rental
public class Rental { private Movie _movie; private int _daysRented; public Rental(Movie movie, int daysRented) { _movie = movie; _daysRented = daysRented; } public int getDaysRented() { return _daysRented; } public Movie getMovie() { return _movie; } }
Refactorizacin - Refactoring
Class Customer
public class Customer { private String _name; private Vector _rentals = new Vector(); public Customer (String name) { _name = name; }; public void addRental(Rental arg) { _rentals.addElement(arg); } public String getName () { return _name; }; public String statement() 1
Refactorizacin - Refactoring
Customer.statement()
public String statement() { 1 double totalAmount = 0; int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "\n"; while (rentals.hasMoreElements()) { double thisAmount = 0; Rental each = (Rental) rentals.nextElement(); //determine amounts for each line switch (each.getMovie().getPriceCode()) { case Movie.REGULAR: thisAmount += 2; if (each.getDaysRented() > 2) thisAmount += (each.getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: thisAmount += each.getDaysRented() * 3; break; case Movie.CHILDRENS: thisAmount += 1.5; if (each.getDaysRented() > 3) thisAmount += (each.getDaysRented() - 3) * 1.5; break; }
Refactorizacin - Refactoring
Customer.statement()
2
// 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(thisAmount) + "\n"; totalAmount += thisAmount; } //add footer lines result += "Amount owed is " + String.valueOf(totalAmount) + "\n"; result += "You earned " + String.valueOf(frequentRenterPoints) + " frequent renter points"; return result; }
Refactorizacin - Refactoring
Customer.statement()
aCustomer aRental aMovie
Rental Record for Dinsdale Pirhana Monty Python and the Holy Grail Ran 2 Star Trek 27 6 Star Wars 3.2 3 Wallace and Gromit 6 Amount owed is 20.5 You earned 6 frequent renter points
3.5
Refactorizacin - Refactoring
Comentarios
El programa funciona perfectamente Se observan problemas de diseo
Mtodo excesivamente largo en la clase Client.statement() Dificultan futuros cambios
Cuando haya que aadir una nueva caracterstica al programa y el cdigo no mantiene la estructura adecuada para aadir la nueva caracterstica, primero se refactoriza el programa y luego se aade la nueva caracterstica.
10
Refactorizacin - Refactoring
Testear
Construir un conjunto slido de test
Crear unos clientes Dar a los clientes unos alquileres de varias clases de pelculas Generar manualmente cadena resultantes del alquiler Comparar las cadenas resultantes con las generadas manualmente
Localiza los posibles fallos (bugs) cuando se refactoriza Usar un simple framework para construir los Test
http://www.junit.org
11
Refactorizacin - Refactoring
Extract Method
Se dispone de un fragmento de cdigo que puede ser agrupado junto. Crear un nuevo mtodo con ese cdigo, cuyo nombre explique el propsito del mtodo.
void printOwing() { printBanner(); //print details System.out.println ("name: System.out.println ("amount }
void printOwing() { printBanner(); printDetails(getOutstanding()); } void printDetails (double outstanding) { System.out.println ("name: " + _name); System.out.println ("amount " + outstanding); }
12
Refactorizacin - Refactoring
Extract Method
Crear un mtodo con el nombre que describa la intencin del cdigo Copiar en el nuevo mtodo el cdigo extrado Determinar si las variables utilizadas en el cdigo extrado son:
Parmetros Valores de retorno Variables locales
Compilar Sustituir el fragmento de cdigo con llamadas al nuevo mtodo Compilar y testear
13
Refactorizacin - Refactoring
14
Refactorizacin - Refactoring
15
Refactorizacin - Refactoring
16
Refactorizacin - Refactoring
Fallo de Testeo
public String statement() {
double totalAmount = 0;
int frequentRenterPoints = 0; Enumeration rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "\n"; while (rentals.hasMoreElements()) { double thisAmount = 0; Rental each = (Rental) rentals.nextElement(); //determine amounts for each line
thisAmount=amountFor(each)
double thisAmount = 0;
switch (each.getMovie().getPriceCode()) { case Movie.REGULAR:
...
return this amount; }
La refactorizacin cambia los programas en pequeos pasos. Si se comete un error es ms fcil encontrar el fallo.
17
Refactorizacin - Refactoring
Un buen cdigo debera comunicar claramente que hace, el nombre de las variables es clave para conseguirlo.
18
Refactorizacin - Refactoring
Move Method
Un mtodo esta usando ms caractersticas de otra clase que de la clase en la que est definido. Crear un nuevo mtodo con un cuerpo similar en la clase que ms lo usa. Transformar el nuevo mtodo en una delegacin o eliminarlo completamente.
Class 1 aMethod()
Class 1
Class 2
Class 2 aMethod()
19
Refactorizacin - Refactoring
Move Method
Declarar el mtodo en la clase destino Copiar y ajustar el cdigo Colocar una referencia del objeto destino en el objeto fuente Transformar el mtodo original en un mtodo delegado
amountOf(Rental each) {return each.charge()}
20
Refactorizacin - Refactoring
double getCharge() {
double result = 0; switch (getMovie().getPriceCode()) { case Movie.REGULAR: result += 2; if (getDaysRented() > 2) result += (getDaysRented() - 2) * 1.5; break; case Movie.NEW_RELEASE: result += getDaysRented() * 3; break; case Movie.CHILDRENS: result += 1.5; if (getDaysRented() > 3) result += (getDaysRented() - 3) * 1.5; break; } return result; Rental
Movie
priceCode: int
Customer statement()
21
Refactorizacin - Refactoring
double thisAmount = 0;
Rental each = (Rental) rentals.nextElement(); //determine amounts for each line
thisAmount=each.getCharge();
Si el mtodo movido es privado no tiene sentido mantener el delegado por que no van a existir clientes del mismo.
22
Refactorizacin - Refactoring
thisAmount = each.getCharge();
// add frequent renter point 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
23
Refactorizacin - Refactoring
24
Refactorizacin - Refactoring
if (basePrice() > 1000) return basePrice() * 0.95; else return basePrice() * 0.98; ... double basePrice() { return _quantity * _itemPrice; }
25
Refactorizacin - Refactoring
Reemplazar todas las referencias de la variable temporal por el nuevo mtodo Eliminar la declaracin y la sentencia de asignacin de la variable temporal Compilar y testear
26
Refactorizacin - Refactoring
27
Refactorizacin - Refactoring
return result; }
28
Refactorizacin - Refactoring
Customer statement()
aCustomer
aRental
aMovie
29
Refactorizacin - Refactoring
return result; } 30
Refactorizacin - Refactoring
private double getTotalCharge() { double result = 0; Enumeration rentals = _rentals.elements(); while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); result += each.getCharge(); } return result; } private int getTotalFrequentRenterPoints(){ int result = 0; Enumeration rentals = _rentals.elements(); while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); result += each.getFrequentRenterPoints(); } return result; }
31
Refactorizacin - Refactoring
//Remove declarations
Enumeration rentals = _rentals.elements(); String result = "Rental Record for " + getName() + "\n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); //show figures for this rental result += "\t" + each.getMovie().getTitle()+ "\t" + String.valueOf(each.getCharge()) + "\n"; } //add footer lines
result += "Amount owed is " + String.valueOf(getTotalCharge()) + "\n"; result += "You earned " + String.valueOf(getTotalFrequentRenterPoints()) + " frequent renter points";
return result; }
32
Refactorizacin - Refactoring
aCustomer
aRental
aMovie
getPriceCode
33
Refactorizacin - Refactoring
Aadir funcionalidad
Customer.htmlStatement()
//Customer public String htmlStatement() { Enumeration rentals = _rentals.elements(); String result = "<H1>Rentals for <EM>" + getName() + "</EM></H1><P>\n"; while (rentals.hasMoreElements()) { Rental each = (Rental) rentals.nextElement(); //show figures for each rental result += each.getMovie().getTitle()+ ": " + String.valueOf(each.getCharge()) + "<BR>\n"; } //add footer lines result += "<P>You owe <EM>" + String.valueOf(getTotalCharge())+ "</EM><P>\n"; result += "On this rental you earned <EM>" + String.valueOf(getTotalFrequentRenterPoints()) + "</EM> frequent renter points<P>"; return result; }
34
Refactorizacin - Refactoring
Refactorizacin - Refactoring
return result;
}
36
Refactorizacin - Refactoring
Movie getCharge
Price
getCharge
return price.getCharge
37
Refactorizacin - Refactoring
Employee
Employee Type
Engineer
Salesman
38
Refactorizacin - Refactoring
Refactorizacin - Refactoring
40
Refactorizacin - Refactoring
//Class Movie public int getPriceCode() { return _priceCode; } public setPriceCode (int arg){ _priceCode = arg; } private int _priceCode;
Refactorizacin - Refactoring
case NORWEIGIAN_BLUE: return (_isNailed) ? 0 : getBaseSpeed(_voltage); } throw new RuntimeException ("Should be unreachable"); }
Bird getSpeed
European getSpeed
African getSpeed
42
Refactorizacin - Refactoring
43
Refactorizacin - Refactoring
44
Refactorizacin - Refactoring
45
Refactorizacin - Refactoring
Resumen
En el ejemplo se mejoro el diseo de un programa para aadir funcionalidad
Ms fcil aadir nuevos servicios a los clientes Ms fcil aadir nuevos tipos de pelculas
Refactorizacin - Refactoring
Tabla de contenidos
Introduccin: un ejemplo de refactoring
Principios en refactoring
Definiciones y orgenes Por qu y cuando refactorizar? Problemas con las refactorizaciones
Miscelneo:
Herramientas Metodologas giles Definicin de nuevas refactorizaciones (Big Low) Conclusiones Fowler, Refactoring: Improving the Design of Existing Code, AddisonWesley, 1999
47
Bibliografa
Refactorizacin - Refactoring
Como nombre
Cambio en la estructura interna de un programa para facilitar su comprensin y abaratar sus modificaciones, sin modificar el comportamiento externo
Como verbo
Actividad de reestructurar el software aplicando una serie de refactoring/transformaciones sin cambiar el comportamiento externo del software.
Origenes
Ward Cunningham y Kent Beck (Smalltalk) Ralph Johnson y Bill Opdyke (Definicin formal d) ftp://st.cs.uiuc.edu/pub/papers/refactoring/opdyke-thesis.ps.Z John Brant y Don Roberts (Refactoring Browser)
48
Refactorizacin - Refactoring
Cuando refactorizar?
Aadir nueva funcionalidad
Refactorizar el cdigo existente hasta que se entienda Refactorizar el diseo para facilitar la incorporacin de la nueva funcionalidad
Refactorizacin - Refactoring
Aadir funcionalidad No modifica el cdigo existente Aade nueva funcionalidad sistema Aade nuevos test Obtener los resultados de test
Refactorizar
al
Modifica el cdigo existente No aade nuevas caractersticas No aade test (pero podra modificar alguno)
Cambio de interfaz
Realizar intercambios de sombreros, pero llevar puesto slo uno cada vez
50
Refactorizacin - Refactoring
Por qu refactorizar?
Para mejorar el diseo del software
Combate la perdida de la estructura de cdigo (diseo) en cambios acumulativos Facilita futuros cambios en el programa
Refactorizacin - Refactoring
Refactorizacin - Refactoring
Tabla de contenidos
Introduccin: un ejemplo de refactoring Principios en refactoring
Definiciones y orgenes Por qu y cuando refactorizar? Problemas con las refactorizaciones
Miscelneo:
Herramientas Metodologas giles
Definicin de nuevas refactorizaciones (Big Low)
Conclusiones
Bibliografa
Fowler, Refactoring: Improving the Design of Existing Code, AddisonWesley, 1999
53
Refactorizacin - Refactoring
Herramientas de Refactoring
Basadas en transformaciones demostrables
Repositorio para consultar informacin
Entidades del programa: clases, mtodos, instrucciones, Encontrar todos los mtodos que leen o escriben una var. de instancia
Construir parses de programas Probar matemticamente que la refactorizacin no cambia la semntica Incorporar las refactorizaciones en entornos integrados de desarrollo
Refactorizacin - Refactoring
Herramientas de Refactoring
55
Refactorizacin - Refactoring
Ejecutar un conjunto de Test (suite) con un nico comando Testear con cada compilacin Direcciones de inters
56
Refactorizacin - Refactoring
Decisiones de diseo
Diseo planeado
Considera necesidades actuales y posibles necesidades futuras Se disea para minimizar los cambios con futuras necesidades Aade un parche en el cdigo si aparece alguna necesidad imprevista
Diseo evolutivo
Considerar necesidades actuales y posibles necesidades futuras Evaluar el coste de la actual flexibilidad versus coste de refactorizar ms tarde Refactorizar cuando el cambio aparece
XP
Metodologa desarrollada por Kent Beck Diseada para soportar los cambios Prcticas claves
Desarrollo iterativo Cdigo Self Testing Refactoring Programacin por parejas
57
Refactorizacin - Refactoring
Tcnicas de equipo
Animar a la cultura de la refactorizacin
Nadie hace bien algo la primera vez Nadie puede escribir cdigo limpio sin revisiones Refactorizar es un paso al progreso
58
Refactorizacin - Refactoring
Realizar los cambios de nuevo, comprobar y redefinir las anotaciones Despus de dos o tres veces de ejecutar la refactorizacin se dispondr de una nueva refactorizacin
59
Refactorizacin - Refactoring
Conclusiones
El principal beneficio de los objetos es su facilidad para ser cambiados. (Encapsulamiento) Las refactorizaciones permiten mejorar el diseo una vez que este ha sido escrito. El tema de Refactoring esta inmaduro:
Falta de documentacin escrita Falta y mejora de herramientas
60