Está en la página 1de 23

1.

Introducci�n

Qu� es la refactorizaci�n

Un primer ejemplo
2.
Principios de refactorizaci�n

3.
Cuando refactorizar: c�digo sospechoso

4.
Pruebas unitarias y funcionales

5.
T�cnicas de refactorizaci�n


Refactorizaciones simples

Refactorizaciones comunes

Refactorizaci�n y herencia
6. Bibliograf�a
Curso 11-12 2


Proceso de mejora de la estructura interna de un

sistema software de forma que su comportamiento

externo no var�a.

Es una forma sistem�tica de introducir mejoras en el c�digo
que minimiza la posibilidad de introducir errores (bugs) en �l.


Consta b�sicamente de dos pasos

Introducir un cambio simple (refactorizaci�n)

Probar el sistema tras el cambio introducido

Consiste en realizar modificaciones como

A�adir un argumento a un m�todo

Mover un atributo de una clase a otra

Mover c�digo hacia arriba o hacia abajo en una jerarqu�a de herencia, etc.
Curso 11-12 3
� Tenemos una aplicaci�n de un video-club

1. Introducci�n

Qu� es la refactorizaci�n

Un primer ejemplo
2.
Principios de refactorizaci�n

3.
Cuando refactorizar: c�digo sospechoso

4.
Pruebas unitarias y funcionales

5.
T�cnicas de refactorizaci�n


Refactorizaciones simples

Refactorizaciones comunes

Refactorizaci�n y herencia
6. Bibliograf�a
Curso 11-12 2


Proceso de mejora de la estructura interna de un

sistema software de forma que su comportamiento

externo no var�a.

Es una forma sistem�tica de introducir mejoras en el c�digo
que minimiza la posibilidad de introducir errores (bugs) en �l.


Consta b�sicamente de dos pasos

Introducir un cambio simple (refactorizaci�n)

Probar el sistema tras el cambio introducido

Consiste en realizar modificaciones como

A�adir un argumento a un m�todo

Mover un atributo de una clase a otra

Mover c�digo hacia arriba o hacia abajo en una jerarqu�a de herencia, etc.
Curso 11-12 3
� Tenemos una aplicaci�n de un video-club

1. Introducci�n

Qu� es la refactorizaci�n

Un primer ejemplo
2.
Principios de refactorizaci�n

3.
Cuando refactorizar: c�digo sospechoso

4.
Pruebas unitarias y funcionales

5.
T�cnicas de refactorizaci�n


Refactorizaciones simples

Refactorizaciones comunes

Refactorizaci�n y herencia
6. Bibliograf�a
Curso 11-12 2


Proceso de mejora de la estructura interna de un

sistema software de forma que su comportamiento

externo no var�a.

Es una forma sistem�tica de introducir mejoras en el c�digo
que minimiza la posibilidad de introducir errores (bugs) en �l.


Consta b�sicamente de dos pasos

Introducir un cambio simple (refactorizaci�n)

Probar el sistema tras el cambio introducido

Consiste en realizar modificaciones como

A�adir un argumento a un m�todo

Mover un atributo de una clase a otra

Mover c�digo hacia arriba o hacia abajo en una jerarqu�a de herencia, etc.
Curso 11-12 3
� Tenemos una aplicaci�n de un video-club

1. Introducci�n

Qu� es la refactorizaci�n

Un primer ejemplo
2.
Principios de refactorizaci�n

3.
Cuando refactorizar: c�digo sospechoso
4.
Pruebas unitarias y funcionales

5.
T�cnicas de refactorizaci�n


Refactorizaciones simples

Refactorizaciones comunes

Refactorizaci�n y herencia
6. Bibliograf�a
Curso 11-12 2


Proceso de mejora de la estructura interna de un

sistema software de forma que su comportamiento

externo no var�a.

Es una forma sistem�tica de introducir mejoras en el c�digo
que minimiza la posibilidad de introducir errores (bugs) en �l.


Consta b�sicamente de dos pasos

Introducir un cambio simple (refactorizaci�n)

Probar el sistema tras el cambio introducido

Consiste en realizar modificaciones como

A�adir un argumento a un m�todo

Mover un atributo de una clase a otra

Mover c�digo hacia arriba o hacia abajo en una jerarqu�a de herencia, etc.
Curso 11-12 3
� Tenemos una aplicaci�n de un video-club

1. Introducci�n

Qu� es la refactorizaci�n

Un primer ejemplo
2.
Principios de refactorizaci�n

3.
Cuando refactorizar: c�digo sospechoso

4.
Pruebas unitarias y funcionales
5.
T�cnicas de refactorizaci�n


Refactorizaciones simples

Refactorizaciones comunes

Refactorizaci�n y herencia
6. Bibliograf�a
Curso 11-12 2


Proceso de mejora de la estructura interna de un

sistema software de forma que su comportamiento

externo no var�a.

Es una forma sistem�tica de introducir mejoras en el c�digo
que minimiza la posibilidad de introducir errores (bugs) en �l.


Consta b�sicamente de dos pasos

Introducir un cambio simple (refactorizaci�n)

Probar el sistema tras el cambio introducido

Consiste en realizar modificaciones como

A�adir un argumento a un m�todo

Mover un atributo de una clase a otra

Mover c�digo hacia arriba o hacia abajo en una jerarqu�a de herencia, etc.
Curso 11-12 3
� Tenemos una aplicaci�n de un video-club

1. Introducci�n

Qu� es la refactorizaci�n

Un primer ejemplo
2.
Principios de refactorizaci�n

3.
Cuando refactorizar: c�digo sospechoso

4.
Pruebas unitarias y funcionales

5.
T�cnicas de refactorizaci�n

Refactorizaciones simples

Refactorizaciones comunes

Refactorizaci�n y herencia
6. Bibliograf�a
Curso 11-12 2


Proceso de mejora de la estructura interna de un

sistema software de forma que su comportamiento

externo no var�a.

Es una forma sistem�tica de introducir mejoras en el c�digo
que minimiza la posibilidad de introducir errores (bugs) en �l.


Consta b�sicamente de dos pasos

Introducir un cambio simple (refactorizaci�n)

Probar el sistema tras el cambio introducido

Consiste en realizar modificaciones como

A�adir un argumento a un m�todo

Mover un atributo de una clase a otra

Mover c�digo hacia arriba o hacia abajo en una jerarqu�a de herencia, etc.
Curso 11-12 3
� Tenemos una aplicaci�n de un video-club

Calcula e imprime el cargo a realizar a un cliente, a partir de las pel�culas que
ha alquilado y el tiempo de alquiler.

Hay tres tipos de pel�culas: normales, infantiles y estrenos.

La aplicaci�n tambi�n bonifi ca con puntos a los clientes que m�s alquilan.

Curso 11-12 4

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;
Alquiler each = (Alquiler) rentals.nextElement();

//determine amounts for each line


switch (each.getPelicula().getCodigoPrecio()) {
case Pelicula.NORMAL:

thisAmount += 2;
if (each.getDiasAlquiler() > 2)
thisAmount += (each.getDiasAlquiler() - 2) * 1.5;
break;

case Pelicula.ESTRENO:
thisAmount += each.getDiasAlquiler() * 3;
break;

case Pelicula.INFANTIL:
thisAmount += 1.5;
if (each.getDiasAlquiler() > 3)

thisAmount += (each.getDiasAlquiler() - 3) * 1.5;


break;
}

. . .

Curso 11-12 5

. . .
// add frequent renter points
frequentRenterPoints++;
// add bonus for a two day new release rental
if ((each.getPelicula().getCodigoPrecio() == Pelicula.ESTRENO)
&& each.getDiasAlquiler() > 1)

frequentRenterPoints++;

// show figures for this rental


result += "\t" + each.getPelicula().getTitulo()

+ "\t" + String.valueOf(thisAmount) + "\n";

totalAmount += thisAmount;
} // END WHILE

// add footer lines


result += "Amount owed is " + String.valueOf(totalAmount) + "\n";
result += "You earned " + String.valueOf(frequentRenterPoints)

+ " frequent renter points";

return result;
}

Cliente.informe() hace demasiadas cosas. Muchas de ellas realmente deber�an


hacerlas otras clases.

Existe alta probabilidad de introducir errores en el c�digo al modificarlo.


Curso 11-12 6

Los usuarios solicitan nuevas funcionalidades: imprimir el informe en formato HTML,


introducir nuevas formas de clasificar las pel�culas, etc...

Imposible reutilizar el c�digo de Cliente.informe()

Soluci�n: copiar/pegar y crear nuevo m�todo Cliente.informeHTML()

Pero, �qu� suceder�a si las reglas de cargo a clientes cambian?

nuevos tipos de pelis, etc


Curso 11-12 7

Dos 'reglas de oro' de la refactorizaci�n:


1.
Cuando necesitamos a�adir una nueva funcionalidad a una aplicaci�n, si la
estructura de la aplicaci�n no es adecuada para introducir los cambios necesarios,
primero refactoriza el c�digo para que el cambio sea f�cil de introducir y luego
a�ade la nueva funcionalidad.

2.
Antes de aplicar t�cnicas de refactorizaci�n, debemos asegurarnos de que disponemos
de una bater�a de pruebas robusta y completa. Estas pruebas deben ser auto-
comprobantes (como las pruebas unitarias)

Refactorizar durante todo el ciclo de vida de una aplicaci�n ahorra tiempo e


incrementa la calidad del proyecto.
Objetivo �ltimo: Mantener un c�digo conciso y claro, f�cil de comprender, modificar
y extender (incluso por terceros). Un aspecto clave para ello es la total ausencia
de c�digo duplicado.
Curso 11-12 8 Descomponer y redistribuir el m�todo Cliente.informe()

Encapsular la sentencia switch que calcula el cargo aplicable a un item en un nuevo


m�todo.

De esta forma podremos reutilizar esta funcionalidad, independientemente del resto


de acciones de Cliente.informe()

No se trata de un cambio trivial:

�que variables locales o argumentos de Cliente.informe() se usan en ese trozo de


c�digo?

�Cu�les de ellas simplemente se leen y cuales son modificadas?

Curso 11-12 9

public String statement() {


...
while (rentals.hasMoreElements()) {
double thisAmount = 0;
Alquiler each = (Alquiler) rentals.nextElement();

thisAmount = calculaCargo(each);

. . .
}

private double calculaCargo(Alquiler alq) {


double cargo=0;

switch (alq.getPelicula().getCodigoPrecio()) {

case Pelicula.NORMAL:
cargo += 2;
if (alq.getDiasAlquiler() > 2)

cargo += (alq.getDiasAlquiler() - 2) * 1.5;


break;

case Pelicula.ESTRENO:
cargo += alq.getDiasAlquiler() * 3;
break;

case Pelicula.INFANTIL:
cargo += 1.5;
if (alq.getDiasAlquiler() > 3)

cargo += (alq.getDiasAlquiler() - 3) * 1.5;


break;
}

return cargo;

Curso 11-12 10

Motivos para refactorizar


-Mejorar el dise�o del software
-
Hacer que el c�digo se m�s f�cil de entender

-
Hacer que sea m�s sencillo encontrar fallos

-Permite programar m�s r�pidamente


Curso 11-12 11

�Cuando refactorizar?
Met�fora de los dos sombreros

Un programador tiene dos sombreros:

uno para modificar c�digo (refactorizar),

otro para a�adir nuevas funcionalidades

Cuando trabaja lleva puesto uno (y solo uno) de los dos sombreros.

Cuando a�ade c�digo nuevo, NO modifica el existente. Si est� arreglando el


existente, NO a�ade funcionalidades nuevas.

Arregla el c�digo con frecuencia. Haz refactoring sistem�ticamente.

-
Refactoriza al a�adir un m�todo/funci�n

-
Refactoriza cuando necesites arreglar un fallo

-
Refactoriza al revisar c�digo

- Refactoriza cuando 'algo huele mal' Curso 11-12 12

Problemas con la refactorizaci�n

Capa de persistencia:
Acoplamiento con bases de datos

Cambios de interfaz

Refactorizar implica a menudo cambios en la interfaz de las clases


Interfaces publicados (vs. p�blicos): aquellos utilizados por c�digo cliente al que
no tenemos acceso. Se hace necesario mantener la antigua interfaz junto a la nueva.
A menudo esto se consigue haciendo que los m�todos de la antigua interfaz deleguen
en los de la nueva.

En Java, podemos usar la anotaci�n @deprecated

Moraleja: no publiques interfaces de forma prematura.


Curso 11-12 13

Cuando no refactorizar

Cuando el c�digo original es tan 'malo' (por dise�o,o m�ltiples fallos) que merece
m�s la pena reescribirlo desde el principio.

�Cuando se est�n a punto de cumplir los plazos!


Curso 11-12 14 A menudo encontramos c�digo sospechoso: algo nos dice que ese c�digo
podr�a ser mejor. A menudo a esto se le llama c�digo con mal olor (bad code smells,
en ingl�s).

Algunas ejemplos:
C�digo duplicado: l�neas de c�digo exactamente iguales o muy parecidas en varios
sitios. Se debe unificar en un s�lo sitio. Es el 'mal olor' m�s com�n y se debe
evitar a toda costa.
M�todos muy largos: Cuanto m�s largo es el c�digo, m�s dif�cil de entender y
mantener. Un m�todo muy largo normalmente est� realizando tareas que deber�an ser
responsabilidad de otros. Se deben identificar �stas y descomponer el m�todo en
otros m�s peque�os.
Curso 11-12 15

Clases muy grandes. Clases con demasiados m�todos, demasiados atributos o incluso
demsiadas instancias. La clase est� asumiendo, por lo general, demasiadas
responsabilidades. Se debe identificar si realmente todas esas cosas tienen algo
que ver entre s� y si no es as�, hacer clases m�s peque�as, de forma que cada una
trate con un cojunto peque�o de responsabilidades bien delimitadas (por ejemplo,
ocuparse de la conexi�n con una base de datos, o manejar cierto tipo de informaci�n
espec�fica, como fechas, DNI, etc.)
Curso 11-12 16

M�todos con demasiados par�metros. Los m�todos de una clase suelen


disponer de la mayor parte de la informaci�n que necesitan en su propia clase

o clases base. Tener demasiados par�metros puede estar indicando un problema de


encapsulaci�n de datos o la necesidad de crear una clase de objetos a partir de
varios de esos par�metros y pasar ese objeto como argumento en vez de todos los
par�metros. Especialmente si esos par�metros suelen tener que ver unos con otros y
suelen ir juntos siempre.
Sentencias 'switch': Normalmente un switch se tiene que repetir en el c�digo en
varios sitios, aunque en cada sitio sea para hacer cosas distintas. Amenudo la
soluci�n es usar polimorfismo para evitar tener que repetir el 'switch' en varios
sitios, o incluso evitarlo completamente.
Curso 11-12 17
En la pr�ctica, la mayor parte del tiempo de desarrollo se dedica a depurar
c�digo.

De ese tiempo, la mayor parte se invierte en encontrar los fallos. El tiempo


dedicado a arreglarlo es normalmente �nfimo, en comparaci�n.

Los test o pruebas unitarios son una forma de probar el correcto funcionamiento de
un m�dulo de c�digo. Esto sirve para asegurar que cada uno de los m�dulos funcione
correctamente por separado.
La idea es escribir casos de prueba para cada funci�n no trivial o m�todo en el
m�dulo o paquete, de forma que cada caso sea independiente del resto.
Las pruebas funcionales tratan a un componente software como una caja negra.
Verifican una aplicaci�n comprobando que su funcionalidad se ajusta a los
requerimientos o a los documentos de dise�o. Se trata a la aplicaci�n o componente
software como un todo.
Curso 11-12 19 Para que una prueba unitaria sea buena se deben cumplir los
siguientes requisitos:

Automatizable: no deber�a requerirse una intervenci�n manual. Esto es especialmente


�til para integraci�n continua.

Completas: deben cubrir la mayor cantidad de c�digo.

Repetibles o Reutilizables: no se deben crear pruebas que s�lo puedan ser


ejecutadas una sola vez. Tambi�n es �til para integraci�n continua.

Independientes: la ejecuci�n de una prueba no debe afectar a la ejecuci�n de otra.

Profesionales: las pruebas deben ser consideradas igual que el c�digo, con la misma
profesionalidad, documentaci�n, etc.
Curso 11-12 20

Los conjuntos o 'suites' de pruebas unitarias son un potente detector de


fallos que reduce dr�sticamente el tiempo necesario para encontrarlos.
Son una precondici�n necesaria para utilizar la refactorizaci�n.
Se asocia una suite de pruebas a cada clase.
Se deben ejecutar tras cada peque�o cambio o refactorizaci�n en el c�digo.
T�picamente cada m�todo es probado utilizando aserciones, que verifican
que el resultado obtenido y el esperado son iguales.
Especialmente relevante es probar

Las condiciones o valores l�mite con los que un m�todo debe ejecutarse.

Las condiciones bajo las cuales un m�todo genera excepciones.

Curso 11-12 21

�Cu�ndo escribir pruebas unitarias?


Tradicionalmente, se piensa que esto se hace tras haber inclu�do el nuevo c�digo a
probar.
Sin embargo, resulta mucho m�s �til escribirlos ANTES de escribir el c�digo a
probar. A menudo, esto sirve para tener m�s claro el comportamiento de un m�todo.
Curso 11-12 22 En Java, la herramienta JUnit (c�digo abierto) es la m�s usada para
pruebas unitarias:

http://junit.sourceforge.net/
En C++, existen varias librer�as similares a Junit en Java:
Cxxtest : http://cxxtest.tigris.org/ (GNU LGPL)
CppUnit : https://launchpad.net/cppunit2 (GNU LGPL)

En C#,
Nunit : http://www.nunit.org/ (licencia tipo BSD)
CsUnit : http://www.csunit.org/ (licencia zLib)

Curso 11-12 23
T�cnicas de refactorizaci�n Refactorizaciones simples A�adir un par�metro Quitar un
par�metro Cambiar el nombre de un m�todo Curso 11-12 24

A�adir un par�metro
Motivo: Un m�todo necesita m�s informaci�n al ser invocado
Soluci�n: A�adir como par�metro un objeto que proporcione dicha
informaci�n
Ejemplo

Cliente.getContacto() . Cliente.getContacto(Fecha f)

Observaciones
Evitar listas de argumentos demasiado largas.

Curso 11-12 25

Quitar un par�metro
Motivo: Un par�metro ya no es usado en el cuerpo de un m�todo
Soluci�n: Eliminarlo

Ejemplo
Cliente.getContacto(Fecha f) . Cliente.getContacto()

Observaciones
Si el m�todo est� sobrescrito, puede que otras implementaciones del m�todo s� lo
usen. En ese caso no quitarlo. Considerar sobrecargar el m�todo sin ese par�metro.
Curso 11-12 26

Cambiar el nombre de un m�todo


Motivo: El nombre de un m�todo no indica su prop�sito
Soluci�n: Cambiarlo
Ejemplo
Cliente.getLimCrdFact() .

Cliente.getLimiteCreditoFactura()

Observaciones

Comprobar si el m�todo est� implementado en clases base o derivadas.


Si es parte de una interface publicada, crear un nuevo m�todo con el nuevo nombre y
el cuerpo del m�todo. Anotar la versi�n anterior como #deprecated y hacer que
invoque a la nueva.

Modificar todas las llamadas a este m�todo con el nuevo nombre.

Curso 11-12 27

Refactorizaciones comunes

Mover un atributo


Mover un m�todo


Extraer una clase


Extraer un m�todo


Cambiar condicionales por polimorfi smo


Cambiar c�digo de error por excepciones

Curso 11-12 28

Mover un atributo
Motivo: Un atributo es (o debe ser) usado por otra clase m�s que en la clase donde
se defi ne. Soluci�n: Crear el atributo en la clase destino
Observaciones

Si el atributo es p�blico, encapsularlo primero.

Reemplazar las referencias directas al atributo por llamadas al getter/setter


correspondiente.

Curso 11-12 29

Mover un atributo
Ejemplo
class Cuenta {
private TipoCuenta tipo;
private double tipoInteres;

double calculaInteres(double saldo, int dias) {


return tipoInteres * saldo * dias /365;
}
class TipoCuenta {
private double tipoInteres;

void setInteres(double d) {�}


double getInteres() {�}

double calculaInteres(double saldo, int dias) {


return tipo.getInteres() * saldo * dias /365;
}

Curso 11-12 30

Cambiar el nombre de un m�todo


Motivo: El nombre de un m�todo no indica su prop�sito
Soluci�n: Cambiar el nombre (y delegar el m�todo antiguo si procede)

Ejemplo

Cliente.getLimCrdFact() .
Cliente.getLimiteCreditoFactura()

Observaciones

Comprobar si el m�todo est� implementado en clases base o derivadas.

Si es parte de una interface publicada, crear un nuevo m�todo con el nuevo nombre y
el cuerpo del m�todo. Anotar la versi�n anterior como #deprecated y hacer que
invoque a la nueva.

Modificar todas las llamadas a este m�todo con el nuevo nombre.

Curso 11-12 31

Mover un m�todo
Motivo: Un m�todo es usado m�s en otro lugar que en la clase actual Soluci�n: Crear
un nuevo m�todo all� donde m�s se use.
Ejemplo
Cliente.getLimiteCreditoFactura()
Cuenta.getLimiteCreditoFactura(Cliente c)
// arg. opcional, s�lo en caso de necesitar info. de
Cliente

Observaciones

Es una de las refactorizaciones m�s comunes

Hacer que el antiguo m�todo invoque al nuevo o bien eliminarlo.


Comprobar si el m�todo est� definido en la jerarqu�a de clases actual. En

ese caso puede no ser posible moverlo. Curso 11-12 32

Extraer una clase


Motivo: Una clase hace el trabajo que en realidad deber�an hacer
entre dos.
Soluci�n: Crear una nueva clase y mover los m�todos y atributos
relevantes de la clase original a la nueva.

Observaciones

La nueva clase debe asumir un conjunto de responsabilidades bien definido.

Implica crear una relaci�n entre la nueva clase y la antigua.

Implica 'Mover atributo' y 'Mover m�todo'

Se debe considerar si la nueva clase ha de ser p�blica o no.

Curso 11-12 33

Extraer una clase


Ejemplo

Curso 11-12 34

Extraer un m�todo
Motivo: Existe un fragmento de c�digo (quiz�s duplicado) que se puede agrupar en
una unidad l�gica.
Soluci�n: Convertir el fragmento en un m�todo cuyo nombre indique su prop�sito e
invocarlo desde donde estaba el fragmento.
Ejemplo: (ejemplo de la introducci�n de la UD)
Observaciones

Se realiza a menudo cuando existen m�todos muy largos.

Las variables locales que s�lo se leen en el fragmento se convertir�n en


argumentos/var. locales del nuevo m�todo
Si algunas variables locales son modificadas en el fragmento, son
candidatas a ser valor de retorno del m�todo

Considerar si se debe publicar el nuevo m�todo.

Curso 11-12 35

Cambiar condicionales por polimorfi smo


Motivo: Una estructura condicional elige entre diferentes
comportamientos en funci�n del tipo de un objeto.
Soluci�n: Convertir la estructura condicional en un m�todo ('Extraer m�todo').
Convertir cada opci�n condicional en una versi�n del m�todo sobrescrito en la clase
derivada correspondiente. Hacer el m�todo en la clase base abstracto.
Observaciones

Con condicionales el c�digo cliente necesita conocer las clases derivadas

Con polimorfismo el c�digo cliente s�lo necesita conocer a la clase base

Esto permite a�adir nuevos tipos sin modificar el c�digo cliente

Curso 11-12 36

Cambiar condicionales por polimorfi smo

Ejemplo:

double getSalario() {

switch(tipoEmpleado()) {
case INGENIERO: return salarioBase + productividad; break;
case VENDEDOR: return salarioBase + ventas*comision; break;
case DIRECTOR: return salarioBase + bonificacion+ dietas; break;
default : throw new RuntimeException(�Tipo de empleado incorrecto�);

}
}

Curso 11-12 37

Cambiar condicionales por polimorfi smo


Ejemplo:
class Empleado {

abstract double getSalario(); �


}
class Ingeniero {

@Override double getSalario() { return salarioBase + productividad; }


...}
class Vendedor {

@Override double getSalario() { return salarioBase + ventas*comision; }


...}
class Director {

@Override double getSalario() {return salarioBase+bonificacion+dietas;}


...}

Curso 11-12 38

Cambiar c�digo de error por excepciones


Motivo: Um m�todo devuelve un valor especial para indicar un error
Soluci�n: Lanzar una excepci�n en lugar de devolver ese valor.
Observaciones

Decidir si se debe lanzar una excepci�n verificada o no verificada.

El c�digo cliente debe manejar la excepci�n.

�Ojo! cambiar la cla�sula 'throws' de un m�todo p�blico (excepciones verificadas)


en Java equivale a cambiar la interfaz de la clase donde se define.
Curso 11-12 39

Cambiar c�digo de error por excepciones


Ejemplo
int sacarDinero(int cantidad) {
if (cantidad > saldo) return -1;
else { saldo -= cantidad; return 0; }

int sacarDinero(int cantidad) throws ExcepcionSaldoInsuficiente {


if (cantidad > saldo) throw new ExcepcionSaldoInsuficiente();
else { saldo -= cantidad; return 0; }

Curso 11-12 40


Refactorizaci�n y herencia

Generalizar un m�todo

Especializar un m�todo

Colapsar una jerarqu�a

Extraer una clase derivada

Extraer una clase base (o interfaz)

Convertir herencia en composici�n
Curso 11-12 41

Generalizar un m�todo
Motivo: Existen dos o m�s m�todos con id�ntico comportamiento
(c�digo duplicado) en las clases derivadas.

Soluci�n: Unifi carlos en un �nico m�todo en la clase base


Observaciones

Prestar atenci�n a diferencias en el comportamiento (cuerpo de los m�todos)

El c�digo cliente debe manejar la excepci�n.

Caso particular: un m�todo en clase derivada sobrescribe uno de la clase base pero
hace esencialmente lo mismo.

Si el m�todo invoca a m�todos declarados en las clases derivadas:

Primero generalizar los m�todos invocados si es posible, o

Declarar dichos m�todos como abstractos en la clase base

Curso 11-12 42

Curso 11-12 43

Especializar un m�todo
Motivo: Un comportamiento de la clase base s�lo es relevante para algunas clases
derivadas.
Soluci�n: Mover el m�todo que lo implementa a las clases derivadas.
Ejemplo
Empleado.getCuotaVentas() . Vendedor.getCuotaVentas()

Observaciones

Usado en 'Extraer clase derivada'


Puede implicar cambiar la visibilidad de ciertos atributos a protegida (o
declarar getter/setter p�blicos(protegidos) en la base.

Si supone un cambio de interfaz, revisar el c�digo cliente. Otra posibilidad es


dejar el m�todo como abstracto en la base

Curso 11-12 44

Colapsar una jerarqu�a


Motivo: Apenas hay diferencias entre una clase base y una de sus
derivadas.
Soluci�n: Juntarlas en una sola clase.
Ejemplo:

Observaciones

Decidir qu� clase eliminar (base o derivada)

El c�digo cliente de la clase eliminada (si es p�blica) deber� ser modificado.

Curso 11-12 45

Extraer una subclase


Motivo: Algunas caracter�sticas de una clase son usadas s�lo por un grupo de
instancias.
Soluci�n: Crear una clase derivada para ese conjunto de
caracter�sticas.
Observaciones

Es a menudo consecuencia de usar un dise�o top-down

La presencia de atributos como 'tipoCliente' se�ala la necesidad de este tipo de


refactorizaci�n.

El c�digo cliente debe ser revisado, en particular, la construcci�n de objetos de


clase base.

Relacionado con 'especializar m�todo', 'reemplazar condicional con


polimorfismo'
Curso 11-12 46

Extraer una subclase


Ejemplo:
La pol�tica del hospital dice que s�lo los m�dicos titulares pueden tener una carga
m�xima de pacientes. Los interinos pueden atender un n�mero indefinido de
pacientes.
Curso 11-12 47
Extraer una subclase
Ejemplo:

Curso 11-12 48

Extraer una superclase


Motivo: Hay dos (o m�s) clases con caracter�sticas similares.
Soluci�n: Crear una clase base para ellas y mover el comportamiento com�n a la
base.
Observaciones

A menudo consecuencia de usar un dise�o bottom-up.

Casi siempre implica eliminar c�digo duplicado.

La nueva clase base suele ser abstracta o incluso un interfaz.

Hay que prestar especial atenci�n a qu� m�todos deben subir a la base ('generalizar
m�todo')

Las referencias en el c�digo cliente pueden tener que ser actualizadas de


referencia a derivada a referencia a base.

Curso 11-12 49
Extraer una superclase
Ejemplo:

Curso 11-12 50

Extraer una superclase


Ejemplo:

Curso 11-12 51

Convertir herencia en composici�n


Motivo: El principio de sustituci�n no se cumple: una clase derivada usa s�lo parte
de la interfaz de la base o no desea heredar tambi�n los atributos.
Soluci�n: Crear un campo para la clase base en la derivada, ajustar los m�todos
involucrados para delegar en la clase base y eliminar la herencia.
Observaciones

Los m�todos de la clase base usados en la derivada se implementan en la derivada y


se convierten en una invocaci�n al m�todo base (delegaci�n)
Curso 11-12 52

Convertir herencia en composici�n


Ejemplo:

Curso 11-12 53

Otras refactorizaciones
Existen otras muchas refactorizaciones que no se presentan aqu�:

Reemplazar valores por objetos

Reemplazar paso por valor por paso por referencia

Reemplazar un array por un objeto

Cambiar una asociaci�n unidireccional en una bidireccional o viceversa

Eliminar setters

Convertir un dise�o procedural en orientado a objetos

Extraer una jerarqu�a

Separar la capa de dominio de la capa de presentaci�n

etc, etc,...
Curso 11-12 54

Conclusiones

Refactorizar es una forma sistem�tica y segura de realizar cambios en una


aplicaci�n con el fi n de hacerla m�s f�cil de comprender, modifi car y extender.
Algunas de las refactorizaciones vistas aqu� se pueden hacer de forma autom�tica en
algunos entornos de desarrollo (p. ej., Eclipse para Java).

Lo importante es saber qu� y cuando refactorizar.

La refactorizaci�n ha sido identifi cado como una de las m�s


importantes innovaciones en el campo del software:

http://www.dwheeler.com/innovation/innovation.html
Curso 11-12 55

En esta unidad docente no se ha hecho especial hincapi� en los pasos a seguir para
realizar las refactorizaciones de forma controlada. Una lectura imprescindible para
conocer estos detalles es el libro de Martin Fowler:
Martin Fowler. Refactoring. Improving the Design of Existing Code Addison Wesley,
2007
http://martinfowler.com/refactoring/
Curso 11-12

También podría gustarte