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

Slides:



Advertisements
Presentaciones similares
EL PROCESO DE DESARROLLO DEL SOFTWARE
Advertisements

MODELOS ORIENTADOS A OBJETOS
Guía metodológica para la gestión de proyectos de software en PyMEs que no son fábricas de software por medio de Metodologías ágiles.
INTRODUCCIÓN A JAVA.
Pruebas Orientadas a Objeto
Pruebas de Unidad y Refactorización
Herencia simple y multiple
Arquitectura CLARO-TECNOTREE
INSTITUTO TECNOLOGICO DE MINATITLAN
DSOO - María Eugenia Valencia
POO Santiago, Mayo 2004 TRABAJO DE INVESTIGACIÓN POO Programación Orientada a Objetos CENAFOM Carolina Bravo V. Jaime Jofré B.
Tipo de Dato Abstracto Tipos de datos:
Etapas y actividades en el desarrollo OO basado en UML
UNIVERSIDAD LATINA (UNILA) ENCAPSULACION Y HERENCIA
Programación 1 Introducción
Aplicación del paradigma orientado a objetos
DIAGRAMAS DE CLASES Completando los diagramas de interacción, es posible identificar la especificación de las clases que participarán en la solución indicando.
Diseño y programación de
MODELANDO EL DOMINIO Capítulo 2 del libro guía Gloria Lucía Giraldo G. UNIVERSIDAD NACIONAL DE COLOMIBIA DISEÑO Y CONSTRUCCIÓN DE PRODUCTOS DE SOFTWARE.
4.- Orientación a Objetos Justo N. Hidalgo Sanz DEPARTAMENTO DE INGENIERÍA INFORMÁTICA.
PROGRAMACIÓN ORIENTADA A OBJETOS
Clases y objetos La unidad fundamental de programación OO son las clases. Conjunto de métodos y semántica Qué se va a hacer POO Clase: que define la implementación.
Conceptos Objeto Clase Atributo / Método Encapsulamiento Mensaje
Contexto: Aplicación gráfica.  Siempre que se piensa en separar la funcionalidad de una aplicación de su interacción con el usuario, bien sea una aplicación.
TRADUCTOR DE UN PROGRAMA
Test Driven Development
Ciclos de vida ágiles.  Es una metodología ágil que plantea: ◦ Iteraciones cortas ◦ Entregables periódicos ◦ Colaboración con el cliente full time ◦
DEPARTAMENTO DE INGENIERÍA INFORMÁTICA
Diseño del Software Diseño de datos Diseño arquitectónico
(c) P. Gomez-Gil, INAOE DISEÑO DE COMPONENTES DE SOFTWARE * NOTAS DEL CURSO Ingeniería de Software I DRA. MARIA DEL PILAR GÓMEZ GIL INAOEP.
TIPOS DE DATOS ABSTRACTOS
ANDRES FELIPE BORRERO SALAZAR COD ALEXANDRA CARREÑO SALAS COD LUCIO ANIBAL CRIOLLO COD ALEJANDRO RUIZ IDROBO COD
DISEÑO DE SOFTWARE 1ª. Parte
Fundamentos de Ingeniería de Software Facultad de Ingenieria Universidad Distrital Francisco José de Caldas ESPECIFICACIÓN Y MANEJO DE LOS REQUERIMIENTOS.
PROGRAMACIÓN ESTRUCTURADA. PROGRAMACÍÓN IMPERATIVA El programa detalla los pasos necesarios para realizar una tarea. Existe un estado global de programa.
Material de apoyo Unidad 4 Estructura de datos
Algoritmos y Programación III 8. Diseño, patrones, arquitecturas Carlos Fontela, 2004.
Tecnológico de Estudios Superiores Huixquilucan Fundamentos de Sistemas Ingeniería en Sistemas Computacionales Lic.: Lydia Villavicencio Gómez “Paradigmas.
INTRODUCCIÓN A JAVA. Índice ¿Qué es Java? La plataforma Java 2 La Máquina Virtual de Java Características principales ¿Qué ventajas tengo como desarrollador?
Ingeniería en Sistemas de Información
Universidad Central de Venezuela Facultad de Ciencias Postgrado en Ciencias de la Computación Sistemas Distribuidos Albany Márquez.
SCJP SUN CERTIFIED PROGRAMMER FOR JAVA 6
Ingeniería de software
Almudena Moya Muñoz Julio 2006 Una vuelta de tuerca a los principios de diseño ágiles.
CICLO DE VIDA Y NORMAALIZACION DE UN SISTEMA DE BASE DE DATOS
Programación orientada a objetos Capítulo 6 Diseño de clases.
Herencia. Introducción La idea básica es poder crear clases basadas en clases ya existentes. Cuando heredamos de una clase existente, estamos re-usando.
INTRODUCCIÓN A LA INGENIERÍA DEL SOFTWARE
Programación Orientada a Objetos (P.O.O.)
TEMA 9: DIAGRAMA DE CLASE EN UML
Programación Orientada a Objeto
Ing. Noretsys Rodríguez. Definición de Conceptos  Falla: Ocurre cuando un programa no se comporta de manera adecuada. Es una propiedad estadística de.
Metodología de la programación
Algoritmos y Programación III
Programación orientada a objetos
Roles de Open UP.
Patrones de diseño equipo n.1
Tipo de relación entre clases Es uno de los aspectos que distinguen el paradigma de orientación a objetos frente a otros paradigmas. Mecanismo que,
DISEÑO DE COMPONENTES Y DESARROLLO BASADO EN COMPONENTES
Proceso de desarrollo de Software
La Programación Orientado a Objetos
Marco de Trabajo para Indexación, Clasificación y Recopilación Automática de Documentos Digitales Javier Caicedo Espinoza Gonzalo Parra Chico.
Fundamentos de Computación
Modelo de procesos de software
Bachillerato Ingeniería en Informática Fundamentos de Computación.
Fundamentos de Ingeniería de Software
Objetivos de la prueba Los objetivos principales de realizar una prueba son: Detectar un error. Tener un buen caso de prueba, es decir que tenga más probabilidad.
Programación orientada a objetos La programación orientada a objetos o POO (OOP según sus siglas en inglés) es un paradigma de programación que usa objetos.
Modelado UML Diagrama de Clases
LE, EI, Profesor Ramón Castro Liceaga UNIVERSIDAD LATINA (UNILA) IV. IMPLANTACION DE ALGORITMOS.
Transcripción de la presentación:

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

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.”

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.

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.

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.

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: */ “privatizar” lo más posible Pocos parámetros

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();

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

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

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

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

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

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.

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?

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”

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”

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

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

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

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

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

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

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…

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

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

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

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

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

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

¿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

Caso I: extraer ancestro Sin problemas para los clientes: se siguen usando las clases descendientes

Caso II: extraer descendientes Hay que modificar clientes, haciendo una refactorización en pasos para más seguridad

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

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

Qué sigue Concurrencia Aplicaciones distribuidas Integración de aplicaciones

Muchas Gracias. Carlos Fontela, 2006