Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

37
Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006

Transcript of Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Page 1: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Algoritmos y Programación III

9. Diseño micro y refactorización

Carlos Fontela, 2006

Page 2: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Temario

Diseño micro o de clases Cohesión y acoplamiento Diseño de interfaces Jerarquías Condiciones anormales

Refactorización ¿Para qué? ¿Cuándo? Condiciones previas Problemas típicos que necesitan

refactorización

Page 3: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Bases del diseño de clases

Una buena arquitectura. Buenas prácticas de diseño y

programación. Patrones de diseño.

Eckel: “Un diseño termina cuando no se pueden

extraer más cosas del mismo.” “Las tareas más habituales se deben poder

hacer de una forma bien sencilla.”

Page 4: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Clases

Cada clase con un propósito simple y claro: una clase por abstracción y una

abstracción por clase.

Separar las dependencias de una plataforma en una clase aparte.

Page 5: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Patologías en diseño de clases

Clases con nombres verbales: No se supone que una clase hace algo, sino

que provee un conjunto de servicios. Clases sin métodos. Clases que no introducen nuevos métodos

ni los redefinen. Sólo heredan.

Clases que se refieren a varias abstracciones: Se deberían dividir en varias.

Page 6: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cohesión y acoplamiento

Cohesión: Cada módulo haga una sola cosa simple.

Acoplamiento: Independencia entre módulos.

Asegurar bajo acoplamiento y alta cohesión en: Métodos Clases Paquetes

Algunos patrones ayudan.

Page 7: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Interfaces de clases (I)

Es lo que ve el cliente Más clara Más consistente Más simple Más intuitiva

No quitar funcionalidad En Java: /** @deprecated */ “privatizar” lo más posible

Pocos parámetros

Page 8: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Interfaces de clases (II)

Implementar operaciones canónicas Comparable Serialización, toString() Clonación No necesariamente en la misma clase

No incluir opciones en métodos que realizan acciones: Hacerlo en el constructor O en forma sucesiva:

documento.establecerHoja(A4);

documento.establecerColor(rojo);

documento.imprimir();

Page 9: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Interfaces de clases (III)

No hay problema si podemos modificar todo el código que depende de ellas

Por eso, es mejor mantener el principio del mínimo privilegio Todo lo más privado que se pueda Publicar las interfaces sólo si es

necesario

Page 10: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Atributos

Atributos deberían mostrar sólo estado y los métodos sólo comportamiento

No abusar de la herencia para expresar estado: El color de una figura es un atributo No crear clases para varones y mujeres

Estado condicionado por los invariantes de clase: Se expresan como restricciones entre atributos Conviene separar atributos vinculados en una clase

aparte que controle el cumplimiento de los invariantes Cuestiones de eficiencia nos pueden llevar a que

no mantengamos siempre los invariantes de la clase

Page 11: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Métodos

Ojo con métodos con grandes switch en los que se hace una cosa u otra en base al valor de un atributo:  if (unaFigura.getClass() == Elipse.class)

(Elipse)unaFigura.dibujar();

else if (unaFigura.getClass() == Poligono.class)

(Poligono)unaFigura.dibujar(); 

Habría que analizar el uso de herencia y polimorfismo

O sobrecarga

Page 12: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Jerarquías (I)

Poner la mayor parte de los atributos y métodos lo más arriba que se pueda: para evitar luego definiciones duplicadas

Si una porción de código se repite en muchas clases hermanas, habría que generar un método y ponerlo en la clase base

Evitar generalizar todo lo que parezca generalizable de entrada Primero debemos resolver el problema que tenemos

entre manos de la manera lo más simple posible

Page 13: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Jerarquías (II)

Una nueva clase descendiente debe añadir o redefinir un método (modificar la interfaz) Si no, no es necesaria Riesgo de complicar la jerarquía sin un fin práctico. Las jerarquías deben ayudar a dominar la complejidad, no a

complicarla

Es más sencillo describir una jerarquía de lo general a lo particular

Pero esto no siempre se aplica a la construcción: Jerarquía construida por demanda

Generalizaciones que surgen al descubrir atributos o métodos en común en clases ya construidas

Sí para clases adquiridas

Page 14: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Excepciones a la herencia (I) Aves como animales voladores.

• ¿Pingüinos, gallinas, etc.? Idiomas de Europa como indoeuropeos.

• ¿magiar, finés y turco?

El uso de herencia con excepciones es una práctica cuestionable. Utilizar subclases para expresar las

excepciones. Pero las clasificaciones con subclases no

permiten excepciones por diferentes categorías.• No voy a poder clasificar a las aves también como

americanas y europeas sin caer en herencia repetida.

Page 15: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Excepciones a la herencia (II)

Pocas soluciones en el terreno práctico Herencia múltiple, en los lenguajes que la

manejan

Interfaces cuando las excepciones se dan a

nivel de métodos

Caso de discusión: ¿La circunferencia es una elipse con un radio

menos? ¿Cómo lo manejamos?

Page 16: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Condiciones anormales (I)

Una excepción indica un error de

ejecución

Mala idea elevar una excepción si no hay error

Por ejemplo, si en una búsqueda no se

encontró el valor buscado

Máxima: “Cuando todo falle, lance una

excepción”

Page 17: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Condiciones anormales (II)

“Un parámetro de error consume menos recursos”

No nos guiemos por microeficiencias: privilegiar la robustez y la seguridad

Las excepciones nos obligan a hacer algo con ellas: chequeo de condiciones lógicas puede evitarse,

dando la impresión de que no ha habido un error cuando en verdad lo hay

Máxima del diseño robusto: “Nunca se debe dar la impresión de que no pasó nada cuando algo ha fallado”

Page 18: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Condiciones anormales (III)

Una implementación de clase debería venir con

las excepciones que puede disparar Ponerlas en el mismo paquete

Cuando se produce una excepción luego de

capturar recursos, a veces debemos liberarlos El recolector de basura se va a ocupar de la memoria

El resto los debe liberar el programador

En el bloque finally

Buena práctica: liberar en orden inverso a la adquisición

Page 19: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Diseño por contrato

Invento de Meyer

Hay un contrato entre implementador y cliente basado en: Invariantes de clase

Precondiciones de métodos

Postcondiciones de métodos

Facilidad para pasar de diseño a implementación

Se centra más en qué hacen las clases que en cómo se hace

Implementado directamente en Eiffel

Page 20: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Refactorización

“Refactoring” Mejorar el diseño de código ya escrito ¿Cómo?

Modificar estructura interna Sin modificar funcionalidad externa Un poco como las optimizaciones

Ejemplo muy simple… y trillado Eliminar código duplicado

Page 21: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Para qué

Mejorar código, haciéndolo más comprensible Para modificaciones Para depuraciones Para optimizaciones

Mantener alta la calidad del diseño Si no, se degrada

A la larga, aumenta la productividad

Page 22: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuándo

Antes de modificar código existente Siempre después de incorporar

funcionalidad Antes de optimizar Durante depuraciones Durante revisiones de código Siempre, si se hace TDD o XP

Page 23: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Condiciones previas

Riesgo alto Máxima: “Si funciona, no lo arregle”

Un paso por vez Pruebas automatizadas

Escribirlas antes de refactorizar Y correrlas luego de cada pequeño

cambio

Page 24: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Problemas y refactorización

“Bad smells in code” (malos olores), los llama Fowler

Son indicadores de que algo está mal, y se solucionan con refactorizaciones

Hay catálogos por todos lados También en “Piensa en Java”, de Eckel

Veamos…

Page 25: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuestiones y soluciones (I)

Código duplicado Extraer un método Extraer y llevar arriba en la jerarquía Extraer una clase, cuando no hay

jerarquía en común

Método largo Extraer métodos

• Nos podemos ayudar con los comentarios

• Y con partes condicionales y ciclos

Page 26: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuestiones y soluciones (II)

Clase grande, con muchas responsabilidades Extraer clases Extraer subclases

Lista de parámetros larga Crear clases para los parámetros Eliminar el parámetro y agregar una

llamada a método

Page 27: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuestiones y soluciones (III)

Cambios divergentes Separar las clases cuya necesidad de

cambio tenga frecuencias distintas o provenga de necesidades diferentes

“Shotgun surgery” Es lo opuesto a lo anterior, cuando cada

cambio me obliga a tocar muchas clases Mover atributos o métodos para crear

una única clase

Page 28: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuestiones y soluciones (IV)

“Envidia de características” Cuando una clase se la pasa llamando a

métodos de otras clases Poner los métodos en las clases que los

usan

Clases sin comportamiento Pueden provenir de refactorizaciones

anteriores Pueden existir, pero no es bueno

Page 29: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuestiones y soluciones (V)

Ifs y switchs abundantes Herencia y polimorfismo Patrones Estado (State) y Estrategia

(Strategy) Otras soluciones de catálogo

Jerarquías paralelas Juntar clases

Page 30: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Cuestiones y soluciones (VI)

“Herencia especulativa” Colapsar la jerarquía

Clases que son alternativas pero tienen interfaces diferentes Renombrar métodos y otras más

complicadas

Hay más Ver Fowler, con sus soluciones

Page 31: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

¿Flexibilidad?

La flexibilidad oscurece el código Y agrega complejidad En general, se flexibiliza uno u otro

aspecto, según lo que se espera que cambie Es el enfoque de los Patrones de diseño

Page 32: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Caso I: extraer ancestro

Sin problemas para los clientes: se siguen usando las clases descendientes

Page 33: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Caso II: extraer descendientes

Hay que modificar clientes, haciendo una refactorización en pasos para más seguridad

Page 34: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Bibliografía

Refactoring Martin Fowler Básicamente, un catálogo de

refactorizaciones típicas

Refactoring to Patterns Joshua Kerievsky Patrones de diseño como un objetivo de

la refactorización

Page 35: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Resumen

Las clases deben tener estado y comportamiento

Mantener el principio de mínimo privilegio Nunca se debe dar la impresión de que no

pasó nada cuando algo ha fallado Refactorizar para mejorar la calidad del

código, no la funcionalidad Combinar refactorización y pruebas

unitarias y de integración constantes

Page 36: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Qué sigue

Concurrencia Aplicaciones distribuidas Integración de aplicaciones

Page 37: Algoritmos y Programación III 9. Diseño micro y refactorización Carlos Fontela, 2006.

Muchas Gracias.

Carlos Fontela, 2006