resumen pds.pdf
Document Details
Uploaded by RelaxedConceptualArt
UADE
Tags
Full Transcript
Proceso de desarrollo de software Tecnicas de desarrollo de software 1. Métodos de Desarrollo de Software Método en Cascada (Waterfall) Descripción: Método secuencial y lineal, donde una fase debe completarse...
Proceso de desarrollo de software Tecnicas de desarrollo de software 1. Métodos de Desarrollo de Software Método en Cascada (Waterfall) Descripción: Método secuencial y lineal, donde una fase debe completarse antes de comenzar la siguiente. Fases principales: Requerimientos, diseño, implementación, verificación y mantenimiento. Ventajas: Fácil de gestionar, ideal para proyectos pequeños con requisitos claros. Desventajas: Poco flexible para cambios, no recomendado para proyectos complejos o inciertos. Método Iterativo-Incremental Descripción: Desarrollo en ciclos llamados iteraciones, donde se agregan o mejoran funcionalidades. Ventajas: Flexibilidad y ajustes continuos con la participación activa del cliente. Desventajas: Requiere mucha interacción con el cliente y grandes cambios no son recomendables durante el proceso. Método en Espiral Descripción: Combina elementos de modelos cascada e iterativo, con énfasis en la gestión de riesgos. Ventajas: Permite cambios durante el desarrollo, adecuado para proyectos grandes. Proceso de desarrollo de software 1 Desventajas: Requiere experiencia en gestión de riesgos y puede generar documentación extensa. Método en V Descripción: Similar al modelo en cascada, pero se centra en la verificación y validación en cada fase. Ventajas: Reduce riesgos al realizar pruebas tempranas. Desventajas: Estructura rígida, poco flexible para cambios en los requisitos. Método de Prototipado Descripción: Desarrollo gradual del producto a través de prototipos que se refinan con retroalimentación del cliente. Tipos: Descartable, evolutivo, e incremental. Ventajas: Útil para requisitos inciertos o cambiantes. Desventajas: Puede ser costoso si los prototipos son descartados y requiere tiempo. Método Ágil Descripción: Fomenta el desarrollo rápido y colaborativo con iteraciones frecuentes y la participación constante del cliente. Ventajas: Adaptable a cambios, con entrega continua de funcionalidades. Desventajas: Puede ser difícil cumplir plazos si hay cambios frecuentes. Scrum Descripción: Divide el trabajo en sprints de 2 a 4 semanas, con reuniones de revisión y retrospectivas. Ventajas: Mejora continua con retroalimentación rápida del cliente. Desventajas: Puede aumentar el tiempo y los costos debido a la interacción continua del cliente. Funcionamiento: Sprints comienzan con planificación, reuniones diarias (scrums) de 15 minutos, y revisión del progreso. El Scrum Master garantiza la Proceso de desarrollo de software 2 eficiencia de las reuniones. Kanban Descripción: Enfocado en visualizar y mejorar el flujo de trabajo con tres prácticas clave: visualización, gestión y mejora. Ventajas: Ayuda a gestionar recursos y mejorar procesos. Desventajas: Puede haber problemas cuando hay fluctuaciones en la demanda o falta de recursos. RAD (Rapid Application Development) Descripción: Metodología que busca desarrollar aplicaciones rápidamente mediante prototipos y retroalimentación continua. Ventajas: Reduce riesgos y permite ajustar el desarrollo. Desventajas: Falta de énfasis en requisitos no funcionales y menos escalable para proyectos grandes. Programación Extrema (XP) Descripción: Centrada en mejorar la calidad del software y en la adaptabilidad rápida a cambios. Elementos clave: Programación en pares, desarrollo dirigido por pruebas (TDD). Ventajas: Alta adaptabilidad y reducción de defectos mediante revisiones continuas. Desventajas: Menos documentación formal y repetición frecuente puede ser tediosa. 2. Seguridad de la Información Modelo CIA (Confidencialidad, Integridad, Disponibilidad) Confidencialidad: Solo las personas autorizadas pueden acceder a la información. Proceso de desarrollo de software 3 Integridad: La información no puede ser alterada sin ser detectada. Disponibilidad: La información está accesible para los usuarios legítimos cuando la necesitan. Conceptos adicionales: Autenticación: Verifica que el usuario es quien dice ser. No repudio: Evita que un usuario niegue haber realizado una acción o transacción. 3. DevOps y DevSecOps DevOps Descripción: Busca la integración continua entre los equipos de desarrollo y operación para entregar software continuamente. Función clave: Mejora la comunicación y la colaboración entre las fases de desarrollo y operación. DevSecOps Descripción: Extiende DevOps integrando la seguridad desde el inicio en el ciclo de desarrollo, en lugar de dejarla para el final. Ventajas: Reduce vulnerabilidades al integrar pruebas de seguridad en cada fase del ciclo. 4. Ciclo de Vida del Desarrollo de Software Las fases del ciclo de vida del software incluyen: 1. Planificación: Identificación de requisitos y planificación del desarrollo. 2. Análisis: Estudio de los requisitos para entender las necesidades del sistema. 3. Diseño: Creación de modelos y arquitecturas del sistema. 4. Implementación: Desarrollo del código. Proceso de desarrollo de software 4 5. Mantenimiento: Gestión del software post-implementación, con actualizaciones y mejoras. 5. UML (Unified Modelling Language) Descripción: UML es un lenguaje estándar para visualizar, especificar, construir y documentar sistemas de software. Características clave: Es independiente del proceso de desarrollo utilizado y permite representar tanto la parte conceptual como física del sistema. Vistas principales en UML: Vista de diseño: Estructura y diseño del sistema. Vista de proceso: Comportamiento de los procesos en el sistema. Vista de implementación: Cómo se implementarán los componentes del sistema. Vista de despliegue: Cómo se instalará y configurará el sistema. Casos de uso: Describe los comportamientos y funcionalidades principales del sistema. 6. Programación Orientada a Objetos y Diagramas de Clases 1. Paradigma de la Programación Orientada a Objetos (POO) El paradigma de la orientación a objetos se basa en: Objetos: Representan entidades del mundo real. Estado: Definido por los valores de sus atributos. Comportamiento: Definido por sus métodos. Proceso de desarrollo de software 5 Un sistema orientado a objetos funciona a través de la interacción entre estos objetos. 2. Características Fundamentales de la POO Encapsulamiento Los detalles internos del objeto están ocultos. Solo los métodos públicos están expuestos para modificar el estado del objeto. Herencia Definición: Permite la reutilización de código y refinamiento. Una subclase hereda atributos y métodos de una superclase. Ejemplo: Perro y Gato heredan de la clase Animal. Polimorfismo Un objeto puede tomar diferentes comportamientos. Polimorfismo ad-hoc: Sobrecarga de métodos. Polimorfismo paramétrico: Los métodos operan con diferentes tipos de datos. Polimorfismo de subtipo: Las clases derivadas pueden redefinir el comportamiento de la clase base. Abstracción Simplifica la representación de un objeto ocultando detalles innecesarios y mostrando solo lo relevante. 3. Modelos en Programación Orientada a Objetos Definición: Un modelo es una representación simplificada de la realidad. Se utiliza para: 1. Visualizar el sistema. 2. Especificar la estructura y comportamiento del sistema. Proceso de desarrollo de software 6 3. Documentar decisiones durante el desarrollo. Modelos Orientados a Objetos: Se centran en la interacción entre los objetos y son más fáciles de mantener cuando los requisitos cambian. 4. Diagramas de Clases en UML Clases Definición: Una clase es un modelo de los elementos que interactúan en un sistema. Los objetos son instancias de una clase. Atributos: Propiedades del objeto. Métodos: Definen el comportamiento del objeto. Elementos de una Clase 1. Nombre: Debe ser único dentro del paquete. 2. Atributos: Especifican el tipo y rango de valores que la propiedad puede tener en las instancias de la clase. 3. Métodos: Implementaciones de los servicios que la clase ofrece. 5. Relaciones entre Clases Las clases rara vez están aisladas y suelen interactuar con otras a través de varias relaciones: Dependencia Definición: Una clase usa otra. Si la clase utilizada cambia, la clase dependiente podría necesitar cambios. Ejemplo: NumTel depende de la enumeración TipoTel para el atributo tipo. Generalización (Herencia) Definición: Relación entre una superclase y una subclase. La subclase hereda atributos y métodos de la superclase. Ejemplo: Perro y Gato heredan de la clase Animal. Proceso de desarrollo de software 7 Asociación Definición: Relación estructural que indica que objetos de una clase están conectados con objetos de otra clase. Pueden tener nombre, roles, y multiplicidad. Ejemplo: Persona tiene una asociación múltiple con Teléfono, lo que indica que una persona puede tener varios teléfonos. Agregación Definición: Relación "todo/parte", donde las partes pueden existir independientemente del todo. Ejemplo: Persona tiene una relación de agregación con Pet, lo que significa que una persona puede adoptar múltiples mascotas. Composición Definición: Relación más fuerte que la agregación, en la que las partes no pueden existir sin el todo. Ejemplo: Persona tiene una relación de composición con Dirección, indicando que no puede haber una dirección sin una persona. 6. Visibilidad de Clases y Métodos 1. Pública (+): Cualquier clase puede acceder a los métodos y atributos. 2. Privada (-): Solo la clase contenedora puede acceder a los métodos y atributos. 3. Protegida (#): Las clases que heredan de la clase contenedora también pueden acceder a los métodos y atributos. 7. Clases Abstractas y Clases Estáticas Clases Abstractas Definición: No pueden ser instanciadas directamente. Deben ser heredadas y pueden tener métodos abstractos que las subclases deben implementar. Proceso de desarrollo de software 8 Clases Estáticas Definición: No pueden ser instanciadas. Se utilizan para definir métodos y propiedades que no dependen de instancias de la clase. 8. Interfaces Definición: Un conjunto de métodos que una clase debe implementar, sin especificar cómo debe hacerlo. Una clase puede implementar múltiples interfaces. Ejemplo: Perro y Gato implementan la interfaz Pet. 7. GRASP (Patrones de Asignación de Responsabilidades en Software) 1. Introducción a GRASP GRASP es una colección de patrones de diseño orientados a la asignación de responsabilidades en el desarrollo de software orientado a objetos. El acrónimo significa General Responsibility Assignment Software Patterns, y su propósito es ayudar a los diseñadores a tomar decisiones sobre cómo distribuir responsabilidades entre las clases de un sistema. 2. Responsabilidades en GRASP En GRASP, las responsabilidades se dividen en dos tipos principales: 1. Responsabilidades de conocimiento: Relacionadas con lo que un objeto sabe. 2. Responsabilidades de acción: Relacionadas con lo que un objeto puede hacer. Patrones de Diseño Patrón 1: Experto Proceso de desarrollo de software 9 Problema que resuelve: ¿Qué principio utilizamos para asignar responsabilidades a los objetos? Solución: Asignar una responsabilidad a la clase que tiene la información necesaria para cumplirla. Ejemplo: Venta es responsable de calcular el total porque tiene los datos necesarios. Observaciones finales del patrón Experto: 1. Se usa con frecuencia para asignar responsabilidades relacionadas con la información que ya posee el objeto. 2. Favorece un bajo acoplamiento y facilita la interacción entre clases mediante mensajes. 3. No siempre es la mejor solución en situaciones complejas. Patrón 2: Creador Problema: ¿Quién debe crear instancias de una clase? Solución: La clase que contiene, agrega o utiliza la clase A es responsable de crear instancias de A. Ejemplo: Venta crea instancias de ItemVenta. Observaciones finales del patrón Creador: 1. Ideal para asignar responsabilidades de creación de objetos. 2. Favorece el bajo acoplamiento al conectar el creador con el objeto creado. 3. En algunos casos puede agregar complejidad. Patrón 3: Bajo Acoplamiento Problema: ¿Cómo minimizar dependencias entre clases para facilitar el mantenimiento del sistema? Solución: Asignar responsabilidades de manera que el acoplamiento entre clases sea bajo. Ejemplo: La clase Venta gestiona los pagos para reducir dependencias. Proceso de desarrollo de software 10 Acoplamiento en Lenguajes Orientados a Objetos El acoplamiento se presenta en varias formas: 1. Tipo X tiene un atributo que se refiere a una instancia del Tipo Y. 2. Tipo X tiene un método que hace referencia a una instancia del Tipo Y. 3. Tipo X pertenece a una subclase de la clase del Tipo Y. 4. Tipo X usa servicios del objeto Tipo Y. 5. Tipo Y es una interfaz, y Tipo X la implementa. Observaciones finales del patrón Bajo Acoplamiento: 1. El bajo acoplamiento es un principio fundamental en el diseño de sistemas de software. 2. Debe considerarse junto con otros principios como Alta cohesión y Experto. 3. Promueve la independencia de las clases, reduciendo el impacto de los cambios. 4. No existen medidas estrictas para determinar cuándo el acoplamiento es demasiado alto, pero debe mantenerse bajo para facilitar la flexibilidad. Patrón 4: Alta Cohesión Problema: ¿Cómo mantener la complejidad bajo control? Solución: Mantener a las clases enfocadas en un conjunto reducido de responsabilidades relacionadas. Ejemplo: Registro no debe gestionar la creación de pagos. Problemas de la Baja Cohesión Los elementos con baja cohesión presentan varios problemas: 1. Son difíciles de reutilizar. 2. Son difíciles de mantener. 3. Son difíciles de entender. Proceso de desarrollo de software 11 4. Son delicados y sensibles a cambios. Patrón 5: Controlador Problema: ¿Quién gestiona los eventos externos que ingresan al sistema? Solución: Una clase que representa el sistema o subsistema, o que gestiona casos de uso específicos. Ejemplo: Sistema puede gestionar la entrada de ventas. Observaciones finales del patrón Controlador: 1. Los sistemas reciben eventos externos, típicamente a través de una GUI operada por una persona o a través de mensajes. 2. Es necesario elegir una clase que gestione estos eventos. El patrón Controlador proporciona una guía para elegir correctamente. 3. Se recomienda utilizar una sola clase controladora para todos los eventos de un mismo caso de uso, permitiendo mantener la información del estado del caso de uso. 4. Se pueden usar diferentes controladores para distintos casos de uso. 5. No se deben dar demasiadas responsabilidades a un controlador ni a ninguna otra clase. 6. El controlador delega en otros objetos el trabajo que debe realizarse. ¿Qué son los Code Smells? Un code smell (o código con mal olor) no necesariamente indica la presencia de bugs, sino un diseño deficiente que puede dificultar la mantenibilidad y escalabilidad del software. Esta idea fue popularizada en el libro Refactoring de Martin Fowler. Los code smells son comunes en el desarrollo ágil. Enfoques para abordar Code Smells: Purista: Evitar los code smells siempre. Pragmático: Analizar caso por caso para determinar si es necesario intervenir. Proceso de desarrollo de software 12 Principales Code Smells 1. Bloaters Los bloaters son clases o fragmentos de código que han crecido desmesuradamente, lo que dificulta su comprensión y mantenimiento. No aparecen de golpe, sino que van creciendo lentamente. Ejemplos de Bloaters: Métodos largos: Los métodos con más de 10 líneas suelen ser sospechosos. Es mejor dividirlos en métodos más pequeños y específicos. Clases grandes: Las clases con demasiados atributos o métodos pierden cohesión y se vuelven difíciles de manejar. Abuso de primitivos: Usar tipos de datos primitivos en lugar de objetos especializados puede generar problemas de flexibilidad. Exceso de parámetros: Demasiados parámetros en un método complican su uso y mantenimiento. Cúmulos de datos: Agrupar muchos datos relacionados sin encapsularlos en una clase puede crear confusión. 2. Orientación a objetos mal entendida Este tipo de smell ocurre cuando no se aplican correctamente los principios de la programación orientada a objetos. Ejemplos: Instrucciones switch: El uso excesivo de instrucciones switch puede reemplazarse por polimorfismo. Herencia rechazada: Cuando una subclase no utiliza todos los métodos heredados, lo que indica una mala relación entre superclase y subclase. Clases alternativas con diferentes interfaces: Clases que hacen lo mismo pero con diferentes nombres de métodos. Es preferible unificar o crear una superclase. Proceso de desarrollo de software 13 3. Bloqueadores de cambios Los bloqueadores de cambios dificultan el mantenimiento del software, ya que un cambio en una parte del código puede requerir modificaciones en muchas otras partes. Ejemplos: Cambios divergentes: Cuando una clase requiere cambios en muchos métodos no relacionados. Esto indica falta de cohesión. Bombardeo de cambios: Cuando un cambio en un método afecta a muchas clases. Esto suele ocurrir cuando las responsabilidades están mal distribuidas. Jerarquías paralelas de herencia: Aparece cuando cada vez que queremos crear una subclase de una clase, es necesario crear otra subclase en otro lugar. Esto es un problema de acoplamiento. La solución consiste en eliminar la jerarquía paralela haciendo que las instancias de una jerarquía se refieran a las de la otra, moviendo atributos y métodos para deshacer la duplicidad. 4. Descartables Se refiere a elementos que no aportan valor al código y deben eliminarse para simplificar y mejorar el rendimiento. Ejemplos: Comentarios innecesarios: Si el código está bien estructurado, no deberían ser necesarios demasiados comentarios. Código duplicado: Se deben extraer métodos comunes para evitar duplicación. Clases perezosas: Clases que no hacen lo suficiente o que han quedado obsoletas. Clases de datos: Se refiere a clases que solo tienen atributos y métodos para acceder a estos (getters y setters), sin ninguna funcionalidad adicional. Estas clases no operan sobre los datos que contienen, por lo que es importante encapsular datos o agregar nuevos métodos para que la clase adquiera valor. Proceso de desarrollo de software 14 Código muerto: Variables, parámetros, métodos o clases que ya no se usan, generalmente por obsolescencia. Es importante identificar y eliminar el código que ya no tiene utilidad, lo que se puede hacer con la ayuda de un IDE. Generalidad especulativa: Clases o parámetros creados "por si acaso" anticipando funcionalidades que nunca se implementan. Este tipo de código también debe ser eliminado, ya que añade complejidad sin aportar ningún valor. 5. Acopladores Este tipo de code smell refleja un acoplamiento excesivo entre clases, lo que genera dependencia entre ellas. Ejemplos: Envidia de atributos: Cuando un método accede con más frecuencia a datos de otro objeto que a los suyos propios. Intimidad inapropiada: Cuando una clase accede a los atributos y métodos privados de otra clase. Cadenas de mensajes: Cuando un objeto llama a otro, que a su vez llama a otro, y así sucesivamente. Esto puede resolverse mediante delegación. Bibliotecas incompletas: Cuando una biblioteca no resuelve todos los problemas necesarios y no es posible cambiarla porque es de solo lectura (read-only). En este caso, es necesario buscar soluciones alternativas. Intermediarios: Si una clase hace solo una tarea y delega todo lo demás a otra clase, su existencia no está justificada. Este problema puede surgir cuando se intenta eliminar cadenas de mensajes y se sobrecarga la delegación. 8. Principios SOLID Introducción a SOLID Proceso de desarrollo de software 15 SOLID es un acrónimo que agrupa una serie de principios clave en la programación orientada a objetos, cuyo objetivo es mejorar la mantenibilidad, flexibilidad y escalabilidad de los sistemas de software. Principio de Responsabilidad Única (SRP) Cada clase debe tener una única responsabilidad y debe ser completamente responsable de esa tarea. Este principio busca que las clases tengan alta cohesión y que cada módulo o clase solo tenga una razón para cambiar. Problema que resuelve: Evita que diferentes partes de un sistema (como distintos departamentos de una empresa) dependan de los mismos métodos de una clase, lo que puede causar conflictos cuando se requiere modificar uno de esos métodos. Ejemplo: Si en una clase "Empleado" hay métodos que son utilizados por varios departamentos diferentes (como contabilidad y recursos humanos), esto puede causar problemas si un departamento quiere modificar el cálculo de algo que otro departamento también utiliza. Solución: Separar las responsabilidades en distintas clases. Por ejemplo, tener clases especializadas para calcular el pago, registrar las horas de trabajo y almacenar los datos de los empleados. Principio Abierto-Cerrado (OCP) Los módulos deben estar abiertos para su extensión, pero cerrados para modificación. Esto significa que debemos poder añadir nuevas funcionalidades sin cambiar el código existente. Problema que resuelve: Si un cambio pequeño en los requisitos implica modificar muchas partes del sistema, entonces no se cumple con este principio. Ejemplo: Proceso de desarrollo de software 16 Un sistema de informes financieros debe poder expandirse para generar informes tanto en pantalla como en PDF sin modificar el código que ya genera el informe en pantalla. Solución: Usar una arquitectura que permita la extensión del sistema añadiendo nuevas clases o componentes, sin necesidad de modificar las clases existentes. Principio de Sustitución de Liskov (LSP) Una clase derivada debe poder sustituir a su clase base sin alterar el comportamiento del sistema. Las subclases no deben modificar el comportamiento esperado de las clases base. Problema que resuelve: Si una subclase cambia el comportamiento de la clase base de forma inesperada, esto rompe el principio de Liskov. Ejemplo: En una aplicación que gestiona tarifas de mantenimiento, las subclases "MantenimientoInterno" y "MantenimientoExterno" deben poder reemplazar a la clase "Mantenimiento" sin alterar el cálculo de tarifas, ya que ambas implementan algoritmos diferentes de manera esperada. Principio de Segregación de Interfaces (ISP) Los clientes no deben verse obligados a depender de interfaces que no necesitan. Es mejor crear interfaces pequeñas y específicas en lugar de una única interfaz general. Problema que resuelve: Si una clase está obligada a implementar métodos que no utiliza, esto viola el principio ISP. Ejemplo: En lugar de tener una clase con métodos que no todos los usuarios requieren, es preferible tener interfaces más pequeñas y específicas que se adapten a Proceso de desarrollo de software 17 las necesidades de cada usuario. Solución: Dividir interfaces grandes en varias más pequeñas para que cada clase dependa únicamente de los métodos que necesita. Principio de Inversión de Dependencias (DIP) Los sistemas deben depender de abstracciones y no de detalles concretos. Esto significa que las clases de alto nivel no deben depender de clases de bajo nivel; ambas deben depender de abstracciones (interfaces). Problema que resuelve: Si el código depende de clases concretas, cada cambio en esas clases concretas afectará a las clases de alto nivel. Ejemplo: En lugar de que una clase de aplicación dependa directamente de una clase concreta de implementación, se debería depender de una interfaz que permita cambiar la implementación sin afectar la lógica de la aplicación. Solución: Utilizar interfaces para definir dependencias entre clases, de manera que las clases concretas se implementen en función de las abstracciones. 9. Patrones Arquitecturales ¿Qué es un patrón arquitectural? Los patrones arquitecturales son esquemas de solución estandarizados para problemas de diseño que se repiten en contextos específicos. Estos esquemas definen los componentes involucrados, sus responsabilidades y la cooperación entre ellos. Patrón de Diseño en Capas Este patrón es utilizado ampliamente para facilitar el desarrollo de sistemas que pueden ser fácilmente modificados y reutilizados. Proceso de desarrollo de software 18 El sistema se organiza en capas, donde cada una contiene un conjunto de servicios. Las capas superiores dependen de las inferiores, pero no al revés. Este enfoque asegura una comunicación clara entre las capas y facilita su mantenimiento y escalabilidad. Patrón de Diseño de Tuberías y Filtros Este patrón se emplea para procesar "streams" (flujos de datos). Los filtros procesan los datos y las tuberías los transportan. Cada filtro puede ser reemplazado sin afectar la estructura del sistema. Aunque ofrece flexibilidad, el procesamiento de "streams" puede ser costoso en términos de recursos computacionales. Patrón de Diseño Pizarra Utilizado en sistemas sin una estrategia de definición cerrada, como reconocimiento de voz o navegación de vehículos autónomos. La "pizarra" actúa como un repositorio central de datos que las fuentes de conocimiento pueden leer o escribir. El controlador coordina el flujo de información entre estas fuentes y la pizarra. Patrón de Diseño Repositorio Este patrón organiza el acceso a un repositorio de datos, permitiendo consultas y modificaciones centralizadas. Se alinea con los principios SOLID y es común en sistemas que utilizan objetos de acceso a datos (DAOs). Patrón de Diseño Intermediario (Broker) Adecuado para sistemas distribuidos que requieren colaboración entre varios servidores. Involucra un intermediario que gestiona las comunicaciones entre los clientes y los servicios, mediante un servidor y proxy que actúan como mediadores. Patrón de Diseño Cliente-Servidor Proceso de desarrollo de software 19 Divide el sistema en clientes que hacen peticiones y servidores que responden con servicios. Este patrón permite una fácil modificación, escalabilidad y reutilización de los componentes, con autenticación entre clientes y servidores. Patrón de Diseño Entre Pares (Peer-to-Peer) Patrón descentralizado utilizado en aplicaciones como blockchain o sistemas de intercambio de archivos. Tiene alta tolerancia a fallas y escalabilidad, pero puede ser poco confiable debido a la falta de un sistema centralizado de respaldo. Patrón de Diseño MVC Se usa en aplicaciones con interfaces gráficas de usuario, dividiendo el sistema en tres componentes: modelo, vista y controlador. El modelo gestiona los datos, la vista representa la información y el controlador maneja la interacción del usuario. Patrón de Diseño PAC Similar al MVC, este patrón separa la presentación, abstracción y control en aplicaciones interactivas. La presentación se encarga de la interfaz del usuario, la abstracción gestiona las funciones lógicas y el control mantiene la consistencia entre ambas. Patrón de Diseño de Microservicios Basado en SOA (Arquitectura Orientada a Servicios), este patrón divide la aplicación en pequeños servicios independientes que se comunican entre sí. Popularizado en los últimos años por su capacidad de escalar y ser modificado sin afectar todo el sistema. 9.11. Patrón de Diseño de Microkernels También conocido como "plug-ins", este patrón permite agregar funcionalidades a un sistema base (core system) sin modificar el resto del Proceso de desarrollo de software 20 sistema. Es ideal para sistemas web con componentes intercambiables y servicios internos o externos. 10. Patrones de Diseño - Strategy, State, Adapter, Observer Introducción a los Patrones de Diseño Un patrón de diseño es una solución recurrente a un problema de diseño que se presenta frecuentemente en un contexto particular. El patrón está asociado con un nombre, lo que ayuda a construir un vocabulario común para describir problemas y soluciones. Incluyen una plantilla que describe cómo resolver el problema mediante relaciones, responsabilidades y colaboraciones entre los componentes del sistema. Descripción General de un Patrón de Diseño Los elementos clave de un patrón de diseño incluyen: Nombre y clasificación: Define el patrón y su tipo. Propósito: Indica qué problema resuelve el patrón. Motivación: Describe el contexto que lleva a utilizar el patrón. Aplicabilidad: Indica cuándo es apropiado usar el patrón. Participantes y Colaboraciones: Describen los elementos involucrados y sus interacciones. Consecuencias: Resultados o efectos secundarios de usar el patrón. Implementación, código de ejemplo y patrones relacionados: Indican cómo implementar el patrón y ejemplos conocidos. Patrón de Diseño Strategy Proceso de desarrollo de software 21 Propósito: Define una familia de algoritmos, los encapsula y permite que varíen independientemente del cliente que los utilice. Motivación: Se necesita cambiar el comportamiento de un objeto en tiempo de ejecución utilizando diferentes algoritmos. Aplicabilidad: Usado cuando existen varias clases relacionadas que solo difieren en sus comportamientos, o cuando se necesita variabilidad de algoritmos. Participantes: Contexto: La clase que utiliza la estrategia. Estrategia: La interfaz que define el algoritmo. EstrategiaConcreta: Implementación concreta de los algoritmos. Colaboraciones: El Contexto interactúa con la Estrategia elegida para ejecutar el algoritmo. Consecuencias: Ofrece una alternativa a la herencia, eliminando sentencias condicionales complejas. Aumenta el número de objetos y la comunicación entre el Contexto y la Estrategia. Ejemplo del Patrón Strategy Cliente selecciona el tipo de pago (tarjeta o transferencia bancaria) en un CarritoDeCompras. La interfaz IPagoStrategy define las implementaciones específicas para el pago con tarjeta (PagoTarjeta) y pago por transferencia (PagoTransferencia). Patrón State Propósito: Permite que un objeto cambie su comportamiento cuando cambia su estado interno, haciendo que el objeto parezca que cambia su clase. Motivación: Evita el uso de múltiples condicionales para manejar diferentes estados de un objeto. Proceso de desarrollo de software 22 Participantes: Contexto: Define la interfaz para interactuar con el cliente y delega el comportamiento dependiente del estado a objetos Estado. Estado: Define una interfaz para encapsular el comportamiento asociado con un estado particular del Contexto. EstadoConcreto: Implementa el comportamiento asociado con un estado del Contexto. Patrón Adapter Propósito: Permite que clases con interfaces incompatibles trabajen juntas mediante la conversión de la interfaz de una clase en otra esperada por el cliente. Motivación: Resolver la incompatibilidad entre interfaces sin cambiar las clases existentes. Participantes: Cliente: Espera trabajar con una interfaz específica. Adaptador: Traduce la interfaz del Adaptee a una interfaz esperada por el Cliente. Adaptee: Es la clase con la interfaz incompatible que necesita adaptarse. Patrón Observer Propósito: Define una relación de uno a muchos entre objetos de manera que cuando un objeto cambia su estado, todos sus dependientes son notificados automáticamente y actualizados. Motivación: Facilitar la comunicación entre objetos sin crear dependencias fuertes. Participantes: Sujeto (Subject): Mantiene una lista de Observadores y les notifica de los cambios en su estado. Proceso de desarrollo de software 23 Observador (Observer): Define una interfaz para ser notificado de los cambios en el estado del Sujeto. ConcretoSujeto: Implementa la interfaz del Sujeto y almacena el estado de interés para los Observadores. ConcretoObservador: Mantiene una referencia al Sujeto y actualiza su estado de acuerdo con las notificaciones. 11. Patrones Composite, Decorator, Iterator Patrón de Diseño Composite Propósito: Este patrón compone objetos en estructuras de árbol para representar jerarquías parte-todo. Permite a los clientes tratar objetos individuales y compuestos de manera uniforme. Es útil cuando se quiere representar jerarquías de objetos que contienen otros objetos. Aplicabilidad: Representación de jerarquías de objetos parte-todo. Permitir que los clientes obvien las diferencias entre objetos individuales y composiciones de objetos. Participantes: Componente: Interfaz común para objetos hoja y compuestos. Hoja: Objeto que no tiene hijos. Composite: Objeto que puede tener otros objetos (hojas o composites) como hijos. Cliente: Interactúa con objetos a través de la interfaz Componente. Consecuencias: Define jerarquías formadas por objetos primitivos y compuestos. Simplifica la interacción del cliente. Facilita la extensión para agregar nuevos tipos de componentes. Proceso de desarrollo de software 24 Patrón de Diseño Decorator Propósito: Agregar responsabilidades a un objeto de manera dinámica. Este patrón es una alternativa a la herencia para añadir funcionalidades, permitiendo mayor flexibilidad y modularidad. Aplicabilidad: Cuando se quiere añadir responsabilidades a objetos individuales de manera dinámica. Cuando las responsabilidades pueden ser añadidas o eliminadas. En casos donde la herencia estática resultaría en demasiadas subclases. Participantes: Componente: Define la interfaz para los objetos que pueden tener responsabilidades añadidas. ComponenteConcreto: Objeto al cual se le añadirán responsabilidades. Decorator: Objeto que añade responsabilidades adicionales. DecoratorConcreto: Extiende Decorator para agregar una responsabilidad específica. Consecuencias: Mayor flexibilidad que la herencia estática. Las responsabilidades pueden añadirse y eliminarse dinámicamente. Facilita la definición de decoradores múltiples, pero puede llevar a la creación de muchos objetos pequeños, complicando la depuración. Patrón de Diseño Iterator Propósito: Proporcionar una manera de acceder secuencialmente a los elementos de una agregación de objetos sin exponer su representación interna. Es útil cuando se necesita recorrer una colección de objetos de distintas maneras. Aplicabilidad: Proceso de desarrollo de software 25 Para acceder al contenido de una agregación de objetos sin exponer su estructura interna. Para permitir múltiples maneras de recorrer una colección de objetos. Para unificar la interfaz de recorrido de distintas colecciones. Participantes: Colección: Proporciona la interfaz para crear un iterador.a ColecciónConcreta: Implementa la interfaz para crear un iterador concreto. Iterator: Define la interfaz para acceder y recorrer los elementos. IteratorConcreto: Implementa el comportamiento de iteración concreto. Consecuencias: Simplifica el acceso a colecciones sin exponer su estructura interna. Permite definir múltiples maneras de recorrer una colección. Mayor flexibilidad al tratar con colecciones, pero puede aumentar la complejidad del diseño al añadir más objetos. 12. Patrones Factories y Template Method Simple Factory Propósito: Es un "pseudo-patrón" que devuelve diferentes objetos según los parámetros de entrada, facilitando la creación de instancias sin que el cliente necesite conocer los detalles de implementación. Motivación: Evitar la creación de múltiples instancias manuales de objetos concretos (como tipos de pizza) en el código cliente. Participantes: Fábrica Simple: Clase que encapsula la creación de instancias. Proceso de desarrollo de software 26 Producto Concreto: Clases que representan los objetos creados por la fábrica. Problemas que resuelve: Evita la duplicación de código al crear instancias repetitivas. Facilita la extensión para agregar nuevas instancias sin modificar el código existente. Factory Method (Método Fábrica) Propósito: Define una interfaz para crear un objeto, pero permite que las subclases decidan qué clase concreta instanciar. Este patrón delega la creación de objetos en las subclases. Motivación: Permite crear objetos de una familia de productos relacionados sin conocer la clase específica a crear. Aplicabilidad: Usar cuando se desea que una clase delegue la creación de objetos a sus subclases. Participantes: Producto Abstracto: Interfaz común para los productos creados. Producto Concreto: Implementación específica del producto. Creador Abstracto: Define el Factory Method. Creador Concreto: Implementa el Factory Method para crear el Producto Concreto. Ejemplo: Una pizzería con estilo cordobés y otra con estilo riojano. Cada subclase de la pizzería crea su propia pizza concreta (muzzarella, calabresa, fugazza) según la región. Proceso de desarrollo de software 27 Abstract Factory (Fábrica Abstracta) Propósito: Proporciona una interfaz para crear familias de objetos relacionados o dependientes sin especificar sus clases concretas. Motivación: Facilita la creación de productos relacionados que deben ser utilizados en conjunto, manteniendo la consistencia entre ellos. Aplicabilidad: Cuando es necesario crear familias de productos sin acoplar el código cliente con las clases concretas. Participantes: Fábrica Abstracta: Define una interfaz para crear objetos relacionados (productos). Producto Abstracto: Interfaz común para los objetos creados. Fábrica Concreta: Implementa la interfaz de la fábrica abstracta para crear productos concretos. Producto Concreto: Clase concreta de los productos creados por la fábrica concreta. Ejemplo: Una cadena de pizzerías donde cada franquicia usa una familia de ingredientes propia (queso, salsa, masa), dependiendo de la región. Template Method Propósito: Define el esqueleto de un algoritmo en una operación, delegando la implementación de algunos pasos a las subclases. Permite que las subclases redefinan ciertos pasos del algoritmo sin cambiar su estructura general. Motivación: Proceso de desarrollo de software 28 Facilitar la reutilización del código común entre varias subclases, permitiendo que las partes variables se definan en las subclases. Participantes: Clase Abstracta: Define el método plantilla y las operaciones primitivas. Clase Concreta: Implementa las operaciones primitivas. Consecuencias: Reutilización de código común entre subclases. Control sobre la estructura general del algoritmo, delegando la variabilidad a las subclases. Ejemplo: Receta para preparar café y té. Los pasos comunes (hervir agua, servir en la taza) se definen en la clase abstracta, mientras que los pasos específicos (colocar café o té, agregar complementos) se definen en las subclases. 13. Singleton, Memento, Command Singleton Propósito: El patrón Singleton garantiza que una clase tenga solo una instancia y proporciona un punto de acceso global a ella. Motivación: Se usa cuando es necesario que solo exista una única instancia de una clase y que sea fácilmente accesible. Aplicabilidad: Se requiere una sola instancia accesible desde un punto global. La única instancia debe ser extensible mediante herencia. Estructura: Singleton: Clase que implementa el patrón y asegura que solo se crea una instancia. Proceso de desarrollo de software 29 Consecuencias: Acceso controlado a la única instancia. Espacio de nombres reducido. Permite refinamiento de operaciones. Flexibilidad al poder permitir un número variable de instancias. Ejemplo en Java: Se crea una única instancia de la clase mediante un método getInstance() que controla si ya existe la instancia y, de no ser así, la crea. Memento Propósito: El patrón Memento captura y externaliza el estado interno de un objeto para que pueda ser restaurado más tarde, sin violar el principio de encapsulamiento. Motivación: Se requiere la posibilidad de hacer un "snapshot" del estado de un objeto para restaurarlo después, sin exponer detalles de implementación. Aplicabilidad: Se necesita restaurar el estado de un objeto sin romper el encapsulamiento. Útil en editores de texto o sistemas donde se implementa "deshacer". Estructura: Originador: Crea un memento que captura su estado actual. Memento: Objeto que almacena el estado capturado. Caretaker: Almacena el memento y lo usa para restaurar el estado cuando sea necesario. Consecuencias: Simplifica el Originador. Mantiene el encapsulamiento. Puede ser costoso si se guardan grandes cantidades de estado. Proceso de desarrollo de software 30 Ejemplo en Java: En un editor de texto, el Memento guarda el estado del texto, permitiendo que el usuario lo restaure tras realizar cambios. Command Propósito: Encapsula una petición como un objeto, lo que permite parametrizar clientes con diferentes solicitudes, encolar solicitudes o registrar y deshacer operaciones. Motivación: Desacoplar el objeto que emite la solicitud del objeto que la procesa, proporcionando flexibilidad para encolar, deshacer o repetir operaciones. Aplicabilidad: Parametrizar objetos con diferentes solicitudes. Facilitar la implementación de "deshacer". Estructurar un sistema en torno a operaciones de alto nivel que invocan comandos. Estructura: Command: Define la interfaz para ejecutar una operación. ConcreteCommand: Implementa la interfaz Command para ejecutar operaciones específicas. Invoker: Encapsula el comando y lo ejecuta. Receiver: El objeto que realiza la acción real en respuesta al comando. Client: Crea y configura los comandos concretos. Consecuencias: Desacopla el objeto que invoca una operación del objeto que sabe cómo realizarla. Permite registrar y deshacer operaciones. Los comandos pueden manipularse y extenderse como cualquier otro objeto. Proceso de desarrollo de software 31 Ejemplo en Java: Un sistema que abre, guarda y edita archivos de texto. El ejecuta comandos como abrir o guardar, sin conocer los detalles de Invoker implementación. 14. Patrones Facade, Visitor, Builder Patrón Facade (Fachada) Propósito: Proporcionar una interfaz unificada para un conjunto de interfaces de un subsistema, simplificando el acceso de los clientes a sistemas complejos. Motivación: El patrón Facade reduce la complejidad de un sistema al proporcionar una interfaz más sencilla, que oculta los detalles de los subsistemas subyacentes. Aplicabilidad: Cuando se necesita proporcionar una interfaz simple para un sistema complejo. Para reducir dependencias entre clientes y las clases que implementan las funcionalidades. Participantes: Fachada (Facade): Clase que proporciona la interfaz simplificada. Subsistemas: Realizan el trabajo real, pero su complejidad queda oculta al cliente. Consecuencias: Oculta la complejidad del sistema al cliente. Promueve un acoplamiento débil entre subsistemas y clientes. Permite que el sistema crezca sin impactar la interacción con los clientes. Ejemplo: El cliente interactúa con la fachada para calcular áreas geométricas (elipse, Proceso de desarrollo de software 32 triángulo, rectángulo) sin preocuparse de cómo se implementan estos cálculos internamente en los subsistemas. Patrón Visitor Propósito: Permite definir nuevas operaciones sobre una estructura de objetos sin modificar las clases de los objetos sobre los que opera. Motivación: Es útil cuando se desea realizar operaciones en una estructura compleja de objetos de diferentes clases, sin alterar las clases base de los objetos. Aplicabilidad: Cuando una estructura de objetos tiene muchas clases y se desea agregar operaciones sin modificar las clases. Cuando se necesitan muchas operaciones diferentes sobre una estructura de objetos, pero no se quieren contaminar las clases con todas esas operaciones. Participantes: Visitor: Declara una operación para cada clase de la estructura de objetos. Element: Interfaz que define un método para aceptar visitantes. ConcreteVisitor: Implementa operaciones concretas para cada tipo de objeto. ConcreteElement: Objeto que acepta visitantes y realiza las operaciones definidas. Consecuencias: Facilita la adición de nuevas operaciones. Permite agrupar operaciones similares. Dificulta la adición de nuevas clases en la estructura de objetos. Ejemplo: En un carrito de compras, los visitantes calculan el costo de los productos como libros y frutas, aplicando diferentes reglas de descuento. Proceso de desarrollo de software 33 Patrón Builder Propósito: Separar la construcción de un objeto complejo de su representación para que el mismo proceso de construcción pueda crear distintas representaciones. Motivación: El patrón Builder se utiliza para crear objetos complejos paso a paso, ofreciendo más control sobre la construcción y flexibilidad para diferentes configuraciones. Aplicabilidad: Cuando el algoritmo para crear un objeto complejo debe ser independiente de las partes que lo forman. Cuando se necesitan diferentes representaciones para el mismo tipo de objeto. Participantes: Director: Encargado de construir el objeto a través de pasos definidos en el Builder. Builder: Declara una interfaz para crear partes del producto. ConcreteBuilder: Implementa los pasos de construcción específicos para el producto. Producto: El objeto final que se construye. Consecuencias: Se puede modificar la representación interna de un objeto. El código de construcción se aísla del código de representación. Mayor control sobre el proceso de construcción. Ejemplo: Construcción de una computadora con diferentes configuraciones (disco duro, RAM, tarjeta gráfica), utilizando un Builder para agregar o quitar componentes opcionales. Proceso de desarrollo de software 34