Reestructuración de Códigos

Download Report

Transcript Reestructuración de Códigos

“Bad Smells” en código
M.C. Juan Carlos Olivares Rojas
Febrero 2011
Agenda
• Código Duplicado
• Métodos grandes
• Clases grandes
• Lista de Parámetros excesiva
• Características de la “envidia”
Agenda
• Sentencias Switch
• Jerarquías de Herencia Paralelas
• Campos Temporales
• Encadenamientos de mensajes
Agenda
• Clases alternativas con diferentes
interfaces
• Librerías de clases incompletas
Competencia Específica
• aprenderá e identificará
los malos hábitos de
codificación
(bad
smells), conociendo así
los
errores
que
generalmente
se
cometen al desarrollar
código.
Criterios de Evaluación
• 70% Examen práctico
• 30% Desarrollo de portafolio
evidencias
(trabajos,
tareas
prácticas)
de
y
Código Duplicado
• Los refactoring funcionan como
desodorante permitiendo que
sea mejor la programación.
Bad Smells
• Un “bad smell” es una mala
práctica de programación que
debe de ser eliminada para que
el código sea más legible y por
ende más mantenible.
• Si algo huele mal…
• La codificación deficiente trae
consigo
una
serie
de
características que la evidencian
rápidamente.
Badsmell
• Muy probablemente este mal.
• Los “malos olores” son visto
como signos de debilidad del
código.
Badsmell
• En general, para cada “mal olor”
existe una serie de refactorings
propuesto para solucionarlos.
Malos Olores
BAD SMELL
REFACTORING PROPUESTO
CODIGO DUPLICADO
EXTRAER EL MÉTODO
SUBIR VARIABLES
SUSTITUIR EL ALGORITMO
MÉTODOS LARGOS
EXTRAER EL MÉTODO
INTRODUCIR OBJETOS COMO PARÁMETROS
REEMPLAZAR EL MÉTODO CON UN OBJETO
MÉTODO
CLASES GRANDES
EXTRAER CLASES
EXTRAER SUBCLASES
CARACTERÍSTICA DE LA “ENVIDIA”
MOVER MÉTODO
CLASES “PEREZOSAS”
COLAPSAR JERARQUÍAS
• ¿cómo
detectamos
duplicado?
código
Código Duplicado
• Es el principal indicador de un
malor olor.
• Misma
expresión
en
subclases hermanas.
dos
• Códigos que sean similares,
pero no iguales.
Código Duplicado
• Misma
expresión
en
dos
métodos de la misma clase.
• Duplicidad de código en dos
clases independientes.
• La gran mayoría de los “Bad
Smells”
se
da
por
la
“codificación excesiva”
Código Duplicado
• Métodos que hagan lo mismo
con diferente algoritmo.
• La decisión de reestructurar
código
depende
de
los
desarrolladores.
Código Duplicado
• La codificación excesiva se da
por muchas razones: malos
hábitos
de
programación,
presión del tiempo de desarrollo,
etc.
• Generalmente no se hace
diseño y cuando llega a hacerse
se hace muy superficial sólo por
cumplir el requerimiento.
Mal Diseño
• Aunque no está enfocado
directamente con la codificación,
es el principal mal olor en la
implementación del software.
Mal Diseño
• En un diagrama de clases en
UML es posible verificar algunos
indicadores de malos olores y
poder reestructurarlos antes de
codificarlos.
• Se
pueden
utilizar
otros
diagramas de UML como los de
secuencia, actividades, estados,
etc.
Mal Diseño
• Existirán indicadores que no son
muy visibles en el modelado
como los métodos largos o el
código duplicado.
Práctica 3
• TDD (Test-Driven Development) es
una metodología de diseño la cual
consiste en codificar en principio
las pruebas unitarias del código.
• Se diseñan todos los posibles
casos de prueba y se verifican sus
resultados.
Práctica 3
• Se codifican las pruebas unitarias y
hasta que no se pasen al 100% el
programa no puede terminar.
• Nótese que al inicio las pruebas no
pueden correrse hasta que se
ejecute el código.
Práctica 3
• Una herramienta popular es
PMD que puede analizar código
escrito en Java
Código Duplicado
• Los malos olores también
pueden ser determinados a
través
de
herramientas
automatizadas,
generalmente
conocidos como analizadores de
códigos.
• Sólo serían muchos menores los
cambios
• La solución para el buen
desarrollo de software son los
patrones de diseño.
Patrones de Diseño
• ¿Si se codifica bien desde el
principio no se tendría que
reestructurar el software?
Patrones de Diseño
• Es
una
solución
bien
documentada que los expertos
aplican para solucionar nuevos
problemas porque han sido
utilizadas con éxito en el
pasado.
• Los patrones de diseño están
basados en esquemas que
funcionan. ¿Cómo es una casa
estilo americano?
Patrones de Diseño
• Los patrones suponen una
evolución en abstracción y
reutilización del software.
• La utilización de patrones puede
resolver este problema. Caso de
ejemplo: Singleton
Patrones de Diseño
• Realizar un programa que
permita que un momento dado
uno y solo un objeto pueda estar
en ejecución (no se permiten
dos o más ejemplares).
Singleton
• Problema:
se
admite
exactamente una instancia de
una clase. Los objetos necesitan
un único punto de acceso global.
• Solución: Defina un método
estático de la clase que
devuelva el Singleton
Singleton
Singleton
public class Singleton {
private static Singleton INSTANCE = null;
private Singleton() {}
private
synchronized
static
void
createInstance() {
if (INSTANCE == null){
INSTANCE = new Singleton();
}
}
Patrón de Diseño de un Menú
Actividad
• Realizar el análisis del programa Criba cn la
herramienta PMD a nivel máximo y tratar de
minimizar la mayor cantidad de errores posibles
Actividad
• Modificar el patrón singleton para que permita
que un objeto se pueda crear un número
específico de veces (por ejemplo de 3 a 5)
• ¿Cómo quedaría dicho patrón?
• Tarea: traer un programa con orientación a
objetos de más de 200 LOC. Mañana por email antes de las 13:00 horas.
Métodos Grandes
• El tener métodos grandes trae
consigo muchas consecuencias
como el hecho de que es menos
reusable y más dificil de leer.
• Se recomienda que los métodos no
sean mayores a 24 líneas
Métodos grandes
• El número de líneas puede ser
variable pero se recomienda que
se pueda leer en una sola pantalla.
• Es deseable que los métodos no
sea tan cortos para evitar el seguir
el flujo del programa
Métodos grandes
• Extract Method es el refactoring
más popular para malos olores
como código duplicado y métodos
grandes (casi el 99% de la solución
es este refactoring)
Extract Method
• El nuevo método que se ha
extraído
contiene
el
código
seleccionado
y
el
código
seleccionado
del
miembro
existente, se reemplaza por una
llamada al nuevo método.
Extract Method
Extract Method
Clases Grandes
Clases Grandes
• En la gran mayoría de las ocasiones,
una clase grande es sinónimo de
código duplicado o que la clase está
realizando más acciones de las
debidas.
• ¿cómo sabemos que una clase es
grande?
Clases Grandes
• Las clases no son grandes por el
tamaño de su código ni por su número
de elementos.
• Se debe verificar que la clase realice
solo las acciones necesarias. Por
ejemplo que no mezcle E/S con la
lógica de la aplicación.
Antipatrones de Diseño
• Antipatrón es un patrón de diseño que
invariablemente conduce a una mala
solución para un problema.
• Al
documentarse
tanto
los
antipatrones como los patrones de
diseño, sirven de base para no
escoger malos caminos, partiendo de
documentación disponible en lugar de
simplemente la intuición.
Antipatrón BLOB
• Mejor
conocido
como
“objeto
todopoderoso”. Se presenta cuando
una clase es muy grande tanto en
atributos y/o en métodos.
Antipatrón BLOB
• Entre más grande son las clases es
más difíciles de mantener, reusar y
probar. Su gran tamaño puede
perjudicar el tiempo de carga.
Generalmente son el resultado de un
mal diseño o de sistemas legados.
Antipatrón BLOB
Antipatrón BLOB
Antipatrón BLOB
Antipatrón BLOB
• Algunos autores consideran al
Singleton (Simplicidad) un ejemplo de
un antipatrón ¿por que?
Antipatrón BLOB
• Dificulta las pruebas de código ya que
promueve un alto acoplamiento.
• La clase controla su propia creación
cuando esta no debe de ser su
responsabilidad.
Antipatrón BLOB
• Se recomienda utilizar el patrón de
diseño Factory para crear objetos.
• En general su naturaleza estática y
pública no son del todo bien vistas.
Lista de Parámetros excesiva
• El manejo de parámetros de forma
excesiva es una mala práctica de
programación ya que implica el
paso de muchos parámetros
difíciles de recordar.
• No hay una métrica exacta para el
número de parámetros
Lista de Parámetros excesiva
• Nuestra
recomendación
será
manejar hasta 4 parámetros como
máximo.
• Si se supera del límite establecido
se deberá reestructurar.
Lista de Parámetros excesiva
• Se pueden elegir otras métricas
como que el ancho del código no
rebase 80 caracteres o bien una
sola pantalla de texto.
• Se debe hacer uso de las
bondades del lenguaje como el
polimorfismo
y
el
uso
de
parámetros predeterminados.
Lista de Parámetros excesiva
• En
general
se
debe
reestructurar
el
número
parámetros por la utilización
estructuras como arreglos
objetos.
de
de
de
y/o
• Se recomienda utilizar refactroings
como: Replace parameters with
method e Introduce parametrs with
object
Lista de Parámetros excesiva
Características de la Envidia
• La envidia viola el principio de
diseño de la cohesión y eleva el
acoplamiento.
Envidia
• Cuando una entidad como una
clase o método están más
interesados
en
el
comportamiento de otra entidad
se le denomina envidia.
• La envidia se presenta sobre
todo con los datos (atributos).
Envidia
• La
solución
generalmente
implica utilizar move method
cuando todo el método es
envidioso.
• Si una sola parte de un método
o clase es envidiosa se debe
utilizar extract method.
Envidia
• Si se presenta envidia con
muchas entidades se deberá
escoger aquella que sea la más
fuerte para colocar en ella el
método.
• Actividad: del código de la criba
se deberá reestructurar de la
siguiente forma:
Actividad
• Nótese
que
el
método
generarCriba es muy grande por
lo que deberá simplificarse
utilizando Extract Method de la
siguiente forma:
Actividad
• Encuentre las funcionalidades y
extraiga
3
métodos:
inicializarCandidatos(max),
eliminarMultiplos(),
obtenerCandidatosNoEliminados
();
• Haga los ajustes necesarios y
verifique que otras partes del
código se pueden reestructurar.
Sentencias Switch
Sentencias Switch
• La
estructura
switch
causa
generalmente duplicidad en el código.
• En general en POO debemos utilizar
polimorfismo para hacer más legibles
e intuitivos los códigos.
Sentencias Switch
• Generalmente
se
aplica
los
refactoring Extract Method y Move
Method aunque en otros casos
aplican refactoring más elaborados
como: Replace Type Code with
Subclasses, Replace Type Code with
State/Strategy, Replace conditional
with Polimorphism, entre otros.
Jerarquía de Herencias Paralelas
• Es un caso especial de Shotgun
Surgery.
• La “cirugía de escopeta” se da
cuando al modificar una clase se
tienen que modificar otras clases
en forma de cadena
Jerarquía de Herencia Múltiples
• Este mal olor se caracteriza por
que cada vez que se crea una
sublcase de una clase x, se debe
crear otra subclase de otra clase,
que generalmente tiene el mismo
prefijo que la otra jerarquía.
Jerarquía de Herencias Paralelas
• Para solucionar este mal olor se
debe utilizar refactroings como
Move Method o Move fields para
quitar las referencias de la otra
subclase creada.
Jerarquía de Herencias Paralelas
Reingeniería de Software
• La refactorización es parte importante
del proceso de reingeniería.
• La reingeniería es una actividad de
reconstrucción, preferible de realizar
antes de que se “derrumbe” la obra.
Técnicas de Reingeniería
• Análisis de Inventario
• Reestructuración de Documentos
• INGENIERÍA INVERSA
• Reestructuración de Códigos
• Reestructuración de Datos
• Ingeniería directa
Ingeniería Inversa
• Se aplica para obtener un modelo
detallado de análisis, ingeniería de
requerimientos, diseño y en algunos
casos implementación teniendo una
solución.
• Es una actividad penada por la ley
Ingeniería Inversa
• Los archivos ejecutables pueden ser
desemsamblados
obteniendo
su
código fuente en ensamblador.
• Los archivos ejecutables con código
portable (Java, .NET) pueden ser
desemsamblados para obtener su
código fuente.
Ingeniería Inversa
• Existen herramientas como los
decompiladores que a partir de un
código objeto pueden obtener código
fuente.
• Todas las aplicaciones nativas se
descomponen en instrucciones en
ensamblador.
Ingeniería Inversa
• Sólo se puede obtener el código
exacto si se conoce la técnica de
generación de código objeto.
• En el caso de java existe un
decompilador básico llamado javap o
bien herramientas más avanzadas
como cavaj, MacJAD o Java
Decompiltaor, etc.
Ingeniería Inversa
• ¿Cómo se puede proteger nuestros
códigos?
Ofuscación
• La ofuscación es una técnica
avanzada de refactorización que
permite a un código mantenerle
obscuro (es decir no muy legible) con
diversos propósitos de optimización.
• ¿No viola esto el principio de claridad
en la implantación?
Ofuscación
• La ofuscación se realiza en muchas
casos para hacer un código ilegible,
también en muchos casos se puede
reducir el tamaño del código fuente y
del código binario realizado.
Ofuscación
Actividad
• Realizar la ofuscación del código Example de
Martin Fowler
• Refactoring de identificadores (métodos,
clases, atributos) con nombres muy grandes y
poco descriptivos.
• Agregando
comentarios
javadoc
sin
coherencia.
• Agregando funcionalidades no utilizadas así
como código no útil.
Téc, de Ofuscación
• La ofuscación al igual que el
refactoring se puede hacer
sobre las estructuras de datos.
• Por ejemplo en arreglos:
Tec. de Ofuscación
• Arreglos
Tec. de Ofuscación
• También
clases:
se
puede
ofuscar
Tec. de Ofuscacion
• Clases
Tec de Ofuscación
• Variables
Tec. de Ofuscación
• Variables
Tec. de Ofuscaciòn
• Sobre el flujo del programa
Tec. de Ofuscación
• Sobre el flujo del programa
• Sobre el flujo del programa
Tec. Ofuscación
• Paralelización
Tec. de Ofuscación
• Paralelización
Tec. de Ofuscación
• Paralelización
Tec. de Ofuscación
• Ciclos
Tec. de Ofuscación
• Ciclos
Téc. De Ofuscación
• Lo más adecuado es realizar la
ofuscación sobre el código
objeto generado sin alterar el
original.
• Existen
ofuscadores
como
proguard, yguard que son libres
o comerciales como Dasho o
KlassMaster
Actividad
• Comparar su proyecto ofuscado con el original
a través de diff y patch
• Determina el grado de legibilidad de la
aplicación calculado a través de la siguiente
fórmula:
• Líneas negras / líneas blancas * 100
Lab
• De la página principal del sitio Web de su
profesor:
http://antares.itmorelia.edu.mx/~jcolivar/
• Realizar ofuscación de códigos para obtener el
archivo más pequeño posible. Por ejemplo si la
página es de 10KB y se reduce en 8KB es
buena la ofuscación. Trate de eliminar líneas
en blanco. La página NO debe de cambiar. Se
premiará al que logre el menor tamaño posible
con 1 PUNTO EXTRA. En caso de empate se
anula.
Campos Temporales
• Generalmente están allí debido
a la utilización de algoritmos
complicados.
Campos Temporales
• Se presentan cuando existen
variables o atributos de la clase
subutilizadas.
Campos Temporales
• Se pueden utilizar refactorings
como extract class o Introduce
Null Objects
Encadenamiento de Mensajes
• Este mal olor es muy notorio y se
caracteriza por tener líneas de
código en las que un objeto pide
por otro y a su vez este por otro, y
así sucesivamente logrando lo que
se conoce como cadenas de
mensajes
Encadenamiento de Mensajes
• Aparentemente se reduce el
manejo de objetos temporales pero
en realidad se está realizando
mucho acoplamiento.
• Cualquier cambio en las relaciones
internas provoca el cambio en las
subsecuentes.
Cadenas de Mensajes
• Se pueden presentar el problema
de “middle man” al tener muchos
intermediarios.
• La solución es en muchos casos
aplicar Hide Delegate, Extract and
Move Method.
Cadena de Mensajes
Clases Alternativas con Distintos
Mensajes
Clases Alternativas
• Se presenta cuando se tienen
métodos similares en diferentes
clases.
• Generalmente se debe de
renombrar el método, y en otros
casos renombrarlo.
Librerías de Clases Incompletas
Librerías de Clases Incompletas
• Las bibliotecas de clases aunque
promueven el reuso de software, sino
están bien elaboradas ocasionan
muchos problemas.
• El problema radica en que la gran
mayoría de las ocasiones, no se
cuenta con el código de la biblioteca.
Librería de Clases Incompletas
• Al no poseer el código fuente, se
vuelve
complicado
realizar
modificaciones.
• Se puede optar por los refactorings de
Introducir Método Foraneo o Introducir
Extesión Local
Actividad
• Desarrollar una biblioteca en Java que
permita realizar operaciones básicas
con vectores en dos y tres
dimensiones.
• Para ello, se deberán construir
“Beans” de la implementación.
Actividad
• Una vez construida la biblioteca
deberá ser utilizada en un proyecto
donde la funcionalidad sea utilizada
por el usuario final.
• Se deberá documentar la biblioteca
con comentarios JavaDoc.
Actividad
• Las operaciones a realizar son:
•
•
•
•
•
Suma
Resta
Igualdad
Multiplicación por un Escalar
Producto punto
Suma
Resta
Producto Punto
Producto Vectorial
Producto de un vector por un Escalar
Se multiplica el escalar por cada componente del vector
kA donde k es un escalar y A un vector se tiene:
kA= kA1x + kA2y + kA3z….
• Existen diversas clasificaciones de
malos olores. Una de las más
populares es la Mika Mäntyla, el
cual divide los malos olores en
cinco categorías:
Otros Malos Olores
• Los que aumentan el tamaño del
código como:
• Método largo, clase larga
• Obsesión por tipos primitivos: aquí
no se utilizan ADT cuando el tipo
de dato lo requiere. Ejemplo: tipo
de dato teléfono
1. Infladores
• Lista de parámetros larga
• Grupos de datos (dataclump): se
presenta cuando se utilizan
muchos datos aislados que podrían
simplificarse utilizando un objeto o
estructura para ello.
1. Infladores
• Sentencias switch
• Campo temporal
• Clases alternas con distintas
interfaces
• Rechazo del legado: cuando una
clase se reusa a utilizar su
herencia.
2. Abusadores de POO
• Cambio divergente: cuando se
implementan
en
las
clases
funcionalidades
diferentes
al
contexto de la clase
• Cirugía de escopeta
• Jerarquía de herencias paralelas
3. Impedidores de cambio
• Clases holgazanas
• Clases de datos: cuando una clase
sólo almacena datos pero no tiene
métodos para acceder a ellos
• Código duplicado
4. Los prescindibles
• Código muerto: código legado que
ya no se utiliza en la versión actual
del código.
• Generalización
especulativa:
sucede cuando un código intenta
solucionar problemas más allá de
sus alcances originales.
4. Los prescindibles
• Alertan sobre alto acoplamiento de
componentes.
• Característica de la envidia
• Cadenas de mensajes
• Intermediarios
5. Los emparejadores
• Intimidad
inapropiada:
ocurre
cuando dos clases se conocen
demasiado y se usan con
demasiada confianza, el problema
se presenta cuando esa relación
en
términos
de
POO
es
inapropiada.
5. Los emparejadores
Hisoria de Usuario
• Necesito de un software que
permita
llevar
acabo
el
seguimiento de mis pacientes.
• La secretaria debe poder
agendar una cita y tener los
datos de contacto del paciente
(teléfono, domicilio, etc.)
Historia de Usuario
• Por mi parte, debo de poder
realizar una cita clínica y poder
imprimir una receta médica.
• Las citas clínicas se van
almacenando en un expediente
electrónico para posteriormente
visualizarlo
• Interacción 1: funcionalidad de
agendar citas
Laboratorio 5
• Interacción 2: funcionalidad de
captura de historia clínica y
expedición de recetas
• Interacción 3: funcionalidad de
consultar expedientes clínicos.
• Programar la interacción que les
corresponda.
Lab 5
• Aspectos
de
diseño
de
interfaces de usuarios salen en
segundo plano.
• Los malos olores dependen del
autor aunque son consistentes.
Conclusiones
• Por ejemplo Jeff Bay en su
artículo
Object
Calisthenics
sugiere 9 reglas a seguir para
construir software de calidad:
• 1.Usa solo un nivel
indentación por método
de
• 3.Usa Wrappers para los tipos
primitivos y las cadenas
• 4.Solo usa un punto por línea
Conclusiones
• 2.No uses el “else” dentro de
una condicional
• 5.No abrevies
las
entidades
• 7.No utilices una clase que
tenga más de 2 variables de
instancia.
Conclusiones
• 6.Mantén
pequeñas
• 9.No use propiedades,
getters ni setters
ni
Conclusiones
• 8.Una clase que contenga una
colección no debe contener
otras variables de instancia
• ¿qué se tendría que hacer en el
programa si la biblioteca utilizada
realiza cálculos erróneos (por
ejemplo
manejar
números
complejos) y no se dispone del
código fuente para modificarlo?
• Identificar mal olor
Actividad
• Librerías de Clases Incompletas
• Solución: introducir método foráneo
o introducir extensión local.
• Se puede utilizar el patrón de
diseño adapatador
Actividad
Dudas