Download Reestructuración de Códigos

Document related concepts
no text concepts found
Transcript
Refactoring, Reuso y Realidad
M.C. Juan Carlos Olivares Rojas
Mayo 2011
Agenda
• Generalización*
• Refactorizaciones mayores*
• Rechazo a la reestructuración
• Implicaciones concernientes al reuso
de software
• La realidad de la reestructuración
Competencia Específica
• conocerá el impacto de la
reestructuración en el
reuso de software, así
como la realidad actual de
la aplicación de la misma
en el ámbito de desarrollo
de software.
Criterios de Evaluación
• 100% Ensayo sobre refactoring en la
realidad.
Generalización
Categorías de Refactoring
• Refactorizar para generalizar
Categorías de Refactoring
• Reestructurar para generalizar
Introducir Aserción
• Malor olor: un código hace un asunción sobre
el estado del programa.
• Desodorante: hacer explícita la asunción a
través de un aserción.
• Por ejemplo en cierto tipo de validaciones como
la raíz cuadrada asumimos que el dato
introducido es positivo.
Introducir Aserción
• ¿Hay aserciones en java?
Introducir Aserción
• Si. El código anterior es en C#
• Cuando una aserción falla se produce una
excepción “unchecked”
• Indican errores de programación (que deben
ser corregidos, no capturados).
• De hecho, normalmente las aserciones se
desactivan en el código de producción.
Aserciones en Java
• Las aserciones sólo están disponibles a partir
de JDK1.4, si se desea hacer una aserción se
deberá de lanzar una excepción:
• if (! (estamos_como_queremos) )
throw new
Error("fallo en tal zona del programa");
• Pero este esquema maneja banderas lo cual se
acaba de ver que no es nada bueno.
Aserciones en Java
• En su lugar se puede manejar:
• assert estamos_como_queremos;
• El cual evaluará la expresión indicada para
obtener un valor de verdad.
• Las aserciones han caído en desuso con la
extensa proliferación de frameworks para
pruebas unitarias donde se hacen aserciones:
assertEquals() por ejemplo.
Aserciones en Java
• IMPORTANTE: las validaciones de datos no
son aserciones!!!
• Las validaciones de datos se deben de hacer.
Una aserción en teoría es para indicar una
porción de código que no debiera de
ejecutarse.
• Para indicar la versión de java al momento de
compilar se deberá habilitar la opción –source
seguido del numero de versión.
Aserciones en Java
• IMPORTANTE: el contenido colocado en assert
no debe de ser vital para la ejecución del
código.
• Suponga el siguiente código:
public int calcularSalario(int comisiones){
assert comisiones >=0;
return 1000+(comisiones*20);
}
Aserciones en Java
• Y el siguiente método para probarlo:
public static void main(String args[]){
int comisiones = 5;
int sueldo = calcularSalario(comisiones);
System.out.println(“Sueldo=”+ sueldo);
}
• Si se corre tanto para valores de 5 y -5 para
comisiones no sucede nada. ¿Por qué?
Aserciones en Java
• Se ocupa activar las directivas del manejo de
aserciones:
• -ea: activa aserciones
• -da: desactiva aserciones
• CONSEJO: en caso de duda siempre meter
aserciones.
Actividad
• Realizar el programa (modificar si ya lo tienen)
de la obtención de ecuaciones de segundo
grado por fórmula general, para que maneje
aserciones.
• Se deberá contar con un método main() y con
interface de usuario
• ¿cuántas aserciones manejaste?
Manejo de Errore con try-catch
• Cuando se está en fase de producción es muy
común sustituir las aserciones y pruebas
unitarias con bloques try-catch imprimiendo la
traza del error en pantalla o un archivo.
• Realizar está acción de esta forma no es buena
práctica
de
programación.
El
atrapar
excepciones es para darles solución aunque en
algunos casos como abrir o crear un archivo
sean excepciones mortales.
Manejo de Errore con try-catch
• Cuando se está en fase de producción es muy
común sustituir las aserciones y pruebas
unitarias con bloques try-catch imprimiendo la
traza del error en pantalla o un archivo.
• Realizar está acción de esta forma no es buena
práctica
de
programación.
El
atrapar
excepciones es para darles solución aunque en
algunos casos como abrir o crear un archivo
sean excepciones mortales.
Manejo de Errore con try-catch
• Otra mala práctica de programación es atrapar
Excepciones genéricas (objeto de la clase
Exception) si bien es cierto que nos permiten
ahorrar en muchas ocasiones tiempo hacen
que el software no sea predecible. Se pueden
utilizar considerando las demás excepciones.
• Siempre hay que saber que tipos de errores se
pueden presentar y darles un tratamiento.
Manejo de Errore con try-catch
• Parte de las malas prácticas del uso de trycatch en lenguajes con marcado de errores
implícito como Java es el hecho que al
forzarnos a atrapar el error solamente lo
hacemos para que corra el programa y no en si
por manejar el error. En algunas ocasiones no
siempre es obligatorio.
• Se recomienda lanzar errores en métodos que
implementen el modelo, mientras que en la
interfaz se deben atrapar.
Manejo de Errore con try-catch
• Por cada excepción que se lance debe de
haber una parte donde se atrape. Por tal motivo
es una mala práctica de programación poner
una excepción en el método main().
• Se recomienda crear nuestros propios
manejadores de errores extendiendo de la
clase Exception y colocando aquellos métodos
y atributos para procesar el error.
Actividades
• Modificar el programa anterior (raíces de una
ecuación cuadrática) para que maneje
excepciones
y
haga
las
validaciones
respectivas.
• Se contará con una interfaz con JOptionPane.
• Las entradas se validarán para que al
encontrarse un error se marque una excepción
creada por nosotros.
Actividades
• Para posteriormente procesarlas en la interfaz.
• Al introducir un valor incorrecto se deberá
quedar en donde está el error para volver a
introducir la entrada.
• Las clases Excepciones a Generar son:
NoPolinomioCuadrado
cuando
a=0
y
RaizImaginaria cuando el discriminante es <0.
Ref. en el manejo de Herencia
• La generalización es una herramienta muy
potente que nos permite evitar mucha
duplicación
de
código.
Utilizándola
correctamente podemos conseguir que nuestro
código sea muy fácil de extender. En estas
refactorización encontramos:
•
•
•
•
Subir Atributo,
Subir Metodo,
Subir CodigoConstructor
Bajar Atributo,
Ref. en el manejo de Herencia
•
•
•
•
•
•
•
Bajar Metodo,
Extraer Subclase
Extraer Superclase,
Extraer Interfaz,
Agrupar Jerarquia,
Sustituir Herencia Por Delegacion,
Sustituir Delegacion Por Herencia
• En el caso de los refactorins de subir y bajar
tanto campos como atributos ya se han
comentado con anterioridad.
Pull Up Constructor Body
• Problemática: se tiene constructores en las
subclases donde prácticamente es el mismo
código.
• Solución: crear un constrctor de la clase.
Llamarlo desde las subclases.
class Manager extends Employee...
public Manager (String name, String id, int
grade) {
_name = name;
_id = id;
public Manager (String name, String id, int
_grade = grade;
grade) {
}
super (name, id);
_grade = grade;
}
Pull Up Constructor Body
• Motivación: Los constructores son engañosos.
No son totalmente métodos, por lo que su uso
es restringido y delicado.
• ¿Por qué es necesario definir primero el
constructor de la superclase en la subclase?
• porque al crear una instancia de una clase, se
ejecuta primero el constructor de su
superclase, y después el de ella misma.
Extract Subclass
• Problemática: Una clase tiene características
que son usadas sólo en algunas instancias.
• Solución: Crear una subclase para este
subconjunto de características.
Trabajo
getTotalPrice
getUnitPrice
getEmployee
Trabajo
getTotalPrice
getUnitPrice
Labor
getUnitPrice
getEmployee
Extract Subclass
• Motivación: El principal motivo para utilizar esta
refactorización, es que una clase tenga
comportamiento que es usado por algunas
instancias de la clase y no se use para el resto.
• La principal alternativa para esta refactorización
es Extract Class. Esto significa seleccionar
entre delegación y herencia.
• Extract subclass es usualmente simple para
realizar, pero tiene sus limitaciones.
Extract Superclass
• Problema: se tienen dos clases con
características similares
• Solución: crear una superclase y mover las
características comunes a la superclase.
Department
getTotalAnnualCost()
getName()
getHeadCount()
Employee
getTotalAnnualCost()
getName()
getld()
Party
getTotalAnnualCost( )
getName( )
Department
Employee
getHeadCount( )
getld( )
Extract Superclass
• Motivación: el código duplicado es una de las
principales cosas malas en los sistemas.
• Una forma de código duplicado es tener dos
clases que hacen cosas similares de la misma
manera o de distinta manera. Los objetos
proporcionan mecanismos de ‘construcción’
para simplificar esta situación con herencia.
Extract Interface
• Problema: Varios clientes usan el mismo
subconjunto de una interface, o dos clases
tienen parte de sus interfaces en común
• Solución: Extraer el subconjunto dentro de una
interface
Extract Interface
•
Employee
getRate()
hasSpecialSkill()
getName()
getDepartment()
<<interface>>
Billable
getRate( )
hasSpecialSkill( )
Employee
getRate()
hasSpecialSkill()
getName()
getDepartment()
Extract Interface
• Motivación:
• Las clases son usadas por otras en diferentes
maneras, por lo que son implementadas de
forma diferente para cada clase.
• Cuando una clase necesita comportamientos
de más de una clase, se soporta con lo que se
llama Herencia múltiple. Java tiene herencia
simple, pero permite establecer e implementar
esta clase de requerimientos usando interfaces.
Interfaz vs Clase Abstracta
• Las clases abstractas como su nombre lo
indica son clases que no pueden instanciar
objetos. Por este motivo sólo se utilizan para
definir taxonomía de clases.
• Las interfaces definen las carácterísticas de
una clase pero no la implementan. Las
interfaces sirven para manejar “herencia
múltiple”.
Interfaz vs Clase Abstracta
• Un futbolista tiene ciertas carácterísticas que
no necesariamente definen su personalidad.
Una persona puede tener el comportamiento de
un futbolista. Por este motivo no heredan sino
que implementan una interfaz.
• Las clases abstractas pueden tener métodos
abstractos o no. Cuando un método es
abstracto debe ser redefinido en la subclase.
Interfaz vs Clase Abstracta
• Las interfaces todos sus métodos son
abstractos. Una interface no encapsula datos.
• ¿Cómo se implementaría en Java?
Colapse Hierarchy
• Problema: Una superclase y una subclase no
son muy diferentes
• Solución: mezclar las clases
Empleado
Empleado
Vendedor
Colapse Hierarchy
• Motivación: Refactorizar una jerarquía a
menudo involucra subir métodos y campos, así
como bajar la jerarquía en cuanto a niveles.
• Se tienen que encontrar las subclases que no
están añadiendo algún valor, y es necesario
mezclarlas con otra.
Colapse Hierarchy
• MECANISMO:
• Selecciona que clase será
superclase o alguna subclase.
eliminada:
la
• Utilizar subir campo o método, bajar campo o
método, para mover comportamientos y datos,
de la clase eliminada a la clase con la que será
mezclada.
Colapse Hierarchy
• Compilar y probar cada movimiento.
• Ajustar las referencias a la clase que será
eliminada para usar la clase mezclada. Esto
afectará declaraciones de variables, tipos de
parámetros y constructores.
• Eliminar la clase vacía.
• Compilar y probar
Dudas