Componentes - Departamento de Ingeniería de Sistemas
Transcripción
Componentes - Departamento de Ingeniería de Sistemas
Diseño y Evaluación de Arquitecturas de Software Principios de diseño César Julio Bustacara Medina Facultad de Ingeniería Pontificia Universidad Javeriana 1 Arquitectura de Software 2 Arquitectura y dependencias • El diseño de muchas aplicaciones de software inician como una imagen en la mente del diseñador. Pero no siempre llevan a una solución adecuada!!! 3 Detección de un diseño degradado Síntomas de un diseño degradado • RIGIDEZ: Tendencia del software a ser difícil de cambiar. – Un diseño rígido, involucra que al cambiar los requerimientos de diseño deberán realizarse cambios muy grandes del mismo. – Significa que el diseño no tiene la capacidad de separarse en módulos independientes. 4 Detección de un diseño degradado • FRAGILIDAD: Un cambio en alguna parte del software, ocasiona cambios en otros sectores. – Tal software causa la sospecha de administradores y consumidores de que los diseñadores y desarrolladores han perdido control de su software. – Genera desconfianza y se pierde la credibilidad. 5 Detección de un diseño degradado • INMOVILIDAD: Inhabilidad de reusar software • Por ejemplo: un ingeniero descubre que puede utilizar módulos que ya ha diseñado, pero debido a la inmovilidad de su diseño, deberá volver a reescribir dicho módulo para este caso específico. • Cuando un módulo resuelve un problema que puede llegar a aparecer en otro momento es muy importante tener en cuenta el concepto de inmovilidad. 6 Detección de un diseño degradado • VISCOSIDAD: Enfrentados a un cambio, los ingenieros usualmente encuentran más de una forma de realizarlo. • De entorno: Entorno de desarrollo ineficiente. • De diseño: Cuando los métodos de preservar el diseño son mas difícil de emplear que los métodos que no preservan el diseño. 7 CONCLUSION Los módulos deben ser lo más cohesivos (unidos) posible y lo menos dependientes posible. 8 Arquitectura y dependencias Las arquitecturas de acuerdo a las definiciones (Perry, 1992) están conformadas por: • Componentes • Conectores • Forma • Razonamiento (rationale) 9 Qué es un Componente? • OMG Unified Modeling Language Specification [OMG01] define un componente como – “… a modular, deployable, and replaceable part of a system that encapsulates implementation and exposes a set of interfaces.” • OO view: un componente contiene un conjunto de clases colaborando • Conventional view: lógica, las estructuras de datos internas que son requeridas para implementar el procesamiento lógico, y una interface que habilita al componente para ser invocado (llamada y datos). 10 Componente OO a na l y si s c l a ss Prin t Jo b n u m b e rOf Pa ge s n u m b e rOf Sid e s p a p e rTy p e m ag n i f i c a t io n p rod u c t io n Fe a t u re s d esig n c o m p o n e nt c o m p u t eJo b Co st( ) c o m p u t eJo b p a ssJo b t o Pri nt e r( ) Prin t Jo b in i t i at e Jo b < < in t er f ace> > co m p u t eJo b comput ePageCost ( ) comput ePaper Cost ( ) comput ePr odCost ( ) comput eTot alJobCost ( ) elaborat ed design class Print Job number Of Pages number Of Sides paper Type paper Weight paper Size paper Color magnif icat ion color Requir ement s pr oduct ionFeat ur es < < in t er f ace> > in it iat eJo b buildWor kOr der ( ) checkPr ior it y ( ) passJobt o Pr oduct ion( ) collat ionOpt ions bindingOpt ions cover St ock bleed pr ior it y t ot alJobCost WOnumber comput ePageCost ( ) comput ePaper Cost ( ) comput ePr odCost ( ) comput eTot alJobCost ( ) buildWor kOr der ( ) checkPr ior it y ( ) passJobt o Pr oduct ion( ) 11 Componente convencional design component getJobData ComputePageCost accessCostsDB elaborated module PageCost in: numberPages in: numberDocs in: sides= 1 , 2 in: color=1 , 2 , 3 , 4 in: page size = A, B, C, B out : page cost in: j ob size in: color=1 , 2 , 3 , 4 in: pageSize = A, B, C, B out : BPC out : SF g e t Jo b Dat a ( n u m b e rPag e s, n u m b e rDo cs, sid e s, co lo r, p ag e Size , p ag e Co st ) acce ssCo st sDB (j o b Size , co lo r, p ag e Size , BPC, SF) co m p u t e Pag e Co st( ) j o b size ( JS) = n u m b e rPag e s * n u m b e rDo cs; lo o ku p b ase p ag e co st ( BPC) --> acce ssCo st sDB ( JS, co lo r) ; lo o ku p size fact o r ( SF) --> acce ssCo st DB ( JS, co lo r, size ) j o b co m p le xit y fact o r ( JCF) = 1 + [ ( sid e s-1 ) * sid e Co st + SF] p ag e co st = BPC * JCF 12 Diseño de componentes basados en clases • Antes de pensar en toda una arquitectura de software, es necesario identificar si un componente esta bien diseñado. • Sugerencia Usar los principios de diseño, acompañados de los principios de dependibilidad (cohesión y acoplamiento) 13 Principios de diseño básicos • The Open-Closed Principle (OCP). “A module [component] should be open for extension but closed for modification. • The Liskov Substitution Principle (LSP). “Subclasses should be substitutable for their base classes. • Dependency Inversion Principle (DIP). “Depend on abstractions. Do not depend on concretions.” • The Interface Segregation Principle (ISP). “Many client-specific interfaces are better than one general purpose interface. • The Release Reuse Equivalency Principle (REP). “The granule of reuse is the granule of release.” • The Common Closure Principle (CCP). “Classes that change together belong together.” • The Common Reuse Principle (CRP). “Classes that aren’t reused together should not be grouped together.” 14 The Open-Closed Principle (OCP) • Debemos ser capaz de modificar los módulos sin modificar la fuente de código de dicho modulo. • La abstracción es la clave para el OCP. • Las clases abstractas presentan un nivel de "abstracción" tan elevado que no sirven para instanciar objetos de ellas y solo sirven para derivar otras clases. • Técnicas: Polimorfismo dinámico – Polimorfismo estático 15 The Open-Closed Principle (OCP) Polimorfismo dinámico: es aquél en el que el código no incluye ningún tipo de especificación sobre el tipo de datos sobre el que se trabaja. Así, puede ser utilizado a todo tipo de datos compatible. Ejemplo: public class Animal(){ public void habla(){ System.out.println("No se que soy"); } } public class Perro() extends Animal{ public void() habla(){ System.out.println("Guau"); } } public class Gato() extends Animal{ public void() habla(){ System.out.println("Miau"); } public class Zoo(){ public static void main(String[] args) { Animal animal = new Gato(); animal.habla(); animal=new Perro(); animal.habla(); } } El resultado por consola será: "Miau" "Guau" 16 The Open-Closed Principle (OCP) Polimorfismo estático: es aquél en el que los tipos a los que se aplica el polimorfismo deben ser explicitados y declarados uno por uno antes de poder ser utilizados Ejemplo: public class Animal(){ public void habla(int a){ if a=1 System.out.println("Guau"); else if a=2 System.out.println("Miau"); } } public class Zoo(){ public static void main(String[] args) { Animal animal = new Animal(); animal.habla(1); animal.habla(2); } } El resultado por consola será: "Miau" "Guau" 17 The Liskov Substitution Principle (LSP) • Las clases se deben diseñar de forma que cualquier clase derivada sea aceptable donde lo sea su superclase. Ejemplo: el circulo en si es un elipse, todos los círculos son elipses que coinciden en sus focos por esto podemos modelar al circulo como un caso particular de elipse y no al revés. Las subclases deben ser sustitutas de sus clases base. Un usuario de una clase base debe continuar funcionando correctamente si se le pasa una instancia de una clase extendida. Violaciones del LSP son violaciones latentes del OCP. 19 The Dependency Inversion Principle (DIP) • Depende de abstracciones y no depende de implementaciones. – Usar clases abstractas o interfaces para que las clases cliente que utilizan estas abstracciones, no conozcan nada de las implementaciones que se harían en las clases que extienden de las abstractas o implementan las interfaces. 20 The Dependency Inversion Principle (DIP) • Arquitectónicamente, los módulos de alto nivel tratan con las políticas de alto nivel de la aplicación. A estas políticas generalmente no le interesan los detalles de sus implementaciones. Cualquier cosa concreta es volátil. La no volatilidad no es un reemplazo para la capacidad de sustitución de una interface abstracta. 21 The Interface Segregation Principle (ISP) • Los clientes de una clase no deberían depender de interfaces que no utilizan Ejemplo: La figura muestra un sistema de clientes y una gran interface para atenderlos, como vemos si necesitamos realizar un cambio en uno de los métodos del cliente A esto afectara al cliente B y cliente C. Por lo tanto será necesario recompilar y redistribuirlos. 25 The Interface Segregation Principle (ISP) Solución: utilizar para cada cliente una interfaz específica. De este modo si la interface para el cliente A necesita un cambio los clientes B y cliente C no serán afectados. Como con todos los principios, se debe cuidar de no exagerar en su uso!!! 26 Independencia Funcional 27 Modularidad (acoplamiento y cohesión) Se alcanza desarrollando módulos con una sola función y además debemos tener una aversión al excesivo uso de los módulos. Ejemplo : Calcular Sueldo neto •Calcular sueldo base •Cálculo leyes sociales •Cálculo de impuesto “Este modulo tiene una sola entrada y no necesita de otro para funcionar” El diseño de software debiera ser tal que cada modulo direcciones una subfunción especifica de los requerimientos y tenga una interfaz simple cuando se lea desde otra estructura. 28 Modularidad (acoplamiento y cohesión) • Importancia de la independencia funcional • El software con modularidad efectiva es fácil de desarrollar debido a que la función puede ser compartida y las interfaces pueden simplificarse. • Los módulos independientes son más fáciles de mantener ya que los efectos de modificaciones se limitan al modulo evitando la propagación de errores. • La independencia funcional es la clave para el buen diseño y la clave para desarrollar un buen software. 29 Cohesión • Es una medida de la fortaleza funcional relativa de un módulo • Un módulo cohesivo ejecuta solo una sola tarea en un procedimiento de software y requiere poca interacción con otros procedimientos que se ejecutan en otra parte del software, es decir, un modulo cohesivo ejecuta una sola cosa. 30 Tipos de Cohesión Menos deseable Coincidencial Lógica Baja Deseable Temporal Comunicacional Procedural o por procedimiento Espectro de la cohesión Funcional Secuencial Alta 31 Tipos de Cohesión 1. Coincidencial Se encuentra cuando los elementos o tareas en un modulo no tienen relación dentro de ellas. Se puede encontrar cuando un programa grande es dividido en módulos pequeños en forma arbitraria sin aplicar criterios en la división. 2. Lógica Un modulo es cohesionado lógicamente si sus elementos manifiestan relaciones en torno a tareas de una categoría general. Viajar en auto Viajar en tren Viajar en bus Viajar a caballo 32 Tipos de Cohesión 3. Temporal Es aquellas cuyos elementos están relacionados por el hecho en que todos sus elementos deben ejecutarse en un mismo margen de tiempo. Ejemplo: Modulo encargado de Inicializar un sistema. 4. Procedimental Es cuando todos los elementos del modulo están relacionados en forma tal que no involucra relación de actividades sino que en un conjunto de reglas se caracteriza porque el control fluye de una actividad a otra. Los elementos de un modulo están relacionados y deben desarrollarse en un orden especifico. Ejemplo: Limpiar utensilios de cocina, preparar almuerzo. "El orden es meramente coyuntural y no existe una lógica de operación derivada de un proceso específico." 33 Tipos de Cohesión 5. Comunicacional Es aquella cuyos elementos participan en actividades cuyos elementos usan los mismos datos de entrada y salida. Ejemplo : Impresión Grabación de archivo. 6. Secuencial Se presenta cuando los elementos están involucrados en actividades tales de manera que los datos de un a actividad sirven como entrada a la próxima actividad. Ejemplo : Leer siguiente transacción Actualizar maestro 34 Tipos de Cohesión 7. Funcional Todos lo elementos de un modulo se encuentran relacionados al desempeño de una sola función. Ejemplo : Cálculo sueldo neto 35 Para determinar la cohesión de un modulo 1. Se debe escribir una frase describiendo la función del módulo y luego hacer un análisis de esa frase, si de ese análisis el módulo puede ser expresado como un verbo imperativo preciso y el predicado como un objeto específico => hay cohesión funcional. Ejemplo : Verbo imperativo Leer Calcular Objeto Registro de transacción Sueldo neto 36 Para determinar la cohesión de un modulo 2. Si el módulo puede ser expresado en forma de un cierto número de acciones, ej: validar transacciones, actualizar maestro, es decir, encontramos más de una relación del verbo imperativo estamos en presencia de una cohesión secuencial. 3. Si el módulo puede ser expresado en término de cierto nº de funciones que están realizando sus tareas con los mismos datos estamos en presencia de una cohesión comunicacional. Ejemplo : un módulo que permita calcular promedio, salario mínimo y salario máximo de los empleados. Las 3 tareas se ejecutarán con los mismos datos. 37 Para determinar la cohesión de un modulo 4. Si el módulo se puede expresar en función de nombres típicos de diagrama de flujo (rutina, switch, módulo) cohesión procedural. La definición describe el procedimiento y el contenido. 5. Si los módulos pueden asociarse a nombre relacionados con cuentas temporales cohesión temporal Ejemplo : END-OF-FILE START-UP 38 Para determinar la cohesión de un modulo 6. Si el módulo puede expresarse en propósitos generales más que propósitos específicos habrá cohesión lógica. Ejemplo: Editar datos Editar datos numéricos (FLAG) 7. Si los nombres de módulo son poco significativos hay cohesión coincidencial. Aquí es muy difícil ponerle un nombre significativo al módulo jefe ya que no tienen ninguna relación. En esencia el tipo de cohesión se puede determinar a través de una serie de preguntas. 39 Para determinar la cohesión de un modulo • Es importante alcanzar una cohesión alta y reconocer una cohesión baja de manera que el diseño de software pueda alcanzar una mayor independencia funcional. • Entre más baja es la cohesión el particionamiento no es el mejor, por lo tanto, hay que hacer un reparticionamiento del problema. 40 Cohesión 𝑁 7 𝐶𝑜ℎ𝑒𝑠𝑖ó𝑛𝑡𝑜𝑡𝑎𝑙 = 𝑐𝑜ℎ𝑒𝑠𝑖ó𝑛 𝑀ó𝑑𝑢𝑙𝑜𝑖𝑘 𝑖=1 𝑘=1 41 Acoplamiento • Es el grado de relación o interdependencia que existe entre los módulos de una estructura de programas. • Para medirlo se toma en cuenta el nº y tipo de conexiones y la información comunicada a través de ellos. • Mientras menos sea el nº de conexiones y más simples sean éstas será el indicador de un mejor diseño. 42 Acoplamiento • La conexión simple entre módulos dará como resultado un software fácil de comprender y menos propenso a un efecto en cadena que es causado cuando los errores ocurren en un lugar y se propagan a través del sistema. • La idea es minimizar el acoplamiento. • Un bajo acoplamiento va a ser un indicador de un buen diseño (buen particionamiento). 43 Acoplamiento Se obtiene un buen acoplamiento: - Eliminando las relaciones innecesarias. - Reduciendo el nº de relaciones necesarias - Minimizando la cantidad de elementos pasados en una relación (transformando elementos en paquetes de información). 44 Acoplamiento Se busca obtener un bajo acoplamiento porque: • Las réplicas de un error son menores. • Al intercambiar un módulo se asegura que el riesgo de tener que cambiar otro sea mínimo. • Cuando se hace mantenimiento a un módulo no se desea conocer detalles internos de otros módulos. • Que sea un sistema muy simple de entender. 45 Tipos de acoplamiento Deseable Menos deseable Por datos Indirecto Bajo Por control Por estructuras de datos Común Externo Espectro de Acoplamiento Por contenido Alto 46 Tipos de acoplamiento 1. Indirecto No existe ninguna relación entre los módulos porque dependen de módulos distintos. Ejemplo : 47 Tipos de acoplamiento 2. Por Datos Dos módulos son de acoplamiento por datos si ellos se comunican por parámetros, cada parámetro puede ser un campo simple o una tabla homogénea ( arreglo en que cada elemento tiene información del mismo. Generar factura de Ejemplo : Alquiler automóvil Kms Dias Monto Tipo-auto Calcular monto 48 Tipos de acoplamiento 3. Por estructuras de Datos Dos módulos están acoplados por estructuras si ambos se refieren a la misma estructura de datos ( registro). Registro Cliente Generar factura de alquiler automóvil Reg Cliente Monto base Calcular monto base Reg Cliente Monto por gasolina Monto por gasolina -Rol socio automóvil -Nro de licencia -Tipo de Automóvil -Km -Días -Gasolina usada -Nro teléfono del socio 49 Tipos de acoplamiento El módulo invocado necesita solo algunos campos, pero igual recibe el registro completo. Limitaciones: • Cualquier cambio que se produzca en el registro ya sea en el formato o en la estructura, afectará todos los módulos donde el regitro está asociado y a aquellos módulos que no hagan referencia a los campos modificados. • Crea dependencia entre módulos y un cambio en uno de ellos afecta a otros aunque no tengan relación 50 Tipos de acoplamiento 4. Por Control Dos módulos estan acoplados por control si uno entrega al otro información interna de otro módulo. MOD 1 MOD 2 Ejemplo: FLAG FLAG A B MOD 2 C FLAG El módulo que invoca decide que parte del subordinado debe ejecutarse. 51 Tipos de acoplamiento 5. Externo Dos módulos son de acoplamiento externo si ambos están ligados a un ambiente externo al software. Ejemplo: operación de entrada y salida se conecta a un módulo de dispositivos específicos, formatos y protocolos de comunicación. Este debe estar presente en número muy pequeño dentro de una estructura. 52 Tipos de acoplamiento 6. Común Dos módulos son de acoplamiento común cuando ambos hacen referencia a una misma área de datos globales. Ejemplo : Nº Parte Nombre parte Nº de partes Encontrar nombre de parte Nº de unidad reducir Reducir Stock Nº de parte inexistente Nombre parte Stock insuficiente Nº de parte antigua Tabla de partes ERRORES 53 Tipos de acoplamiento 7. Por contenido Dos módulos son de acoplamiento por contenido si uno de ellos hace referencia al interior del otro, esto se puede dar cuando un módulo se refiere o cambia los datos de otro módulo. Es el tipo de acoplamiento menos deseable dentro de una arquitectura de software. 54 Acoplamiento 𝑁 𝑁 𝐴𝑐𝑜𝑝𝑙𝑎𝑚𝑖𝑒𝑛𝑡𝑜𝑡𝑜𝑡𝑎𝑙 = 𝑎𝑐𝑜𝑝𝑙𝑎𝑚𝑖𝑒𝑛𝑡𝑜 𝑀ó𝑑𝑢𝑙𝑜𝑖𝑗 𝑖=1 𝑗=1 55 Lineamientos de diseño • Componentes – Convención para nombrar los componentes debe ser establecida. Esta lista forma parte del modelo arquitectural que luego será refinado para alcanzar el modelo de componentes. • Interfaces – Proveen información importante sobre la comunicación y colaboración (ayudan para alcanzar el OPC) • Dependencias y Herencia – Es una buena idea modelar las dependencias de izquierda a derecha y la herencia desde abajo (clases derivadas) hacia arriba (clases base) 56 Diseño a nivel de Componentes • Paso 1. – Identificar todas las clases de diseño que corresponden al dominio del problema. – Identificar todos los componentes que corresponden al dominio del problema. • Paso 2. – Identificar todas las clases de diseño que correspondan al dominio de la infraestructura. – Identificar todos los componentes de diseño que correspondan al dominio de la infraestructura. 59 Diseño a nivel de Componentes • Paso 3. – Elaborar el diseño de clases que no son adquiridas como componentes reusables. – Elaborar el diseño de componentes que no son adquiridos como componentes reusables. Paso 3a. Specify message details when classes or component collaborate. (UML collaboration diagram) Paso 3b. Identify appropriate interfaces for each component. Paso 3c. Elaborate attributes and define data types and data structures required to implement them. Paso 3d. Describe processing flow within each operation in detail. (UML activity diagram) 60 Diseño a nivel de Componentes • Paso 4. – Describa las fuentes de datos persistentes (bases de datos y archivos) e identifique las clases requeridas para manejarlos – Describa las fuentes de datos persistentes (bases de datos y archivos) e identifique los componentes requeridos para manejarlos • Paso 5. – Desarrolle y elabore representaciones de comportamiento para las clases – Desarrolle y elabore representaciones de comportamiento para los componentes (UML statechart) 61 Diseño a nivel de Componentes • Paso 6. – Elabore los diagramas de despliegue para proveer detalles de implementación adicional. • Paso 7. – Obtenga la representación final (diseño) del componente y evalúelo. 62 Principios de arquitectura de paquetes La cohesión de los paquetes • The Release Reuse Equivalency Principle (REP) – Principio de equivalencia de liberación y reuso – The Common Closure Principle (CCP) – The Common Reuse Principle (CRP) • Principios de Acoplamiento de Paquetes – The Acyclic Dependencies Principle (ADP) – The Stable Dependencies Principle (SDP) – The Stable Abstractions Principle (SAP) 63