Академический Документы
Профессиональный Документы
Культура Документы
Interacción arquitectura-requisitos
Es probable que la descomposición del sistema en subsistemas (arquitectura) influya en la
forma de estructurar los requisitos, para lograr una más clara correspondencia entre los
requisitos y el diseño.
El análisis y el diseño se entrelazan en un proceso iterativo.
El diseño puede por tanto influir en el análisis, pero cuidando de no influir en exceso.
Reutilización de diseños
La mala costumbre de “reinventar la rueda” en ingeniería del software impide su desarrollo
como disciplina de ingeniería.
Una posible razón: organización inadecuada de arquitecturas, diseños y código, que hace casi
imposible la reutilización.
Otras dificultades del diseño para el reuso:
o Es más difícil, requiere más tiempo, pero los plazos siguen siendo ajustados.
o Aumenta la complejidad, por tanto puede reducir el rendimiento.
o La clasificación y recuperación de componentes requiere búsqueda por contenido.
El uso de tecnologías de objetos y componentes facilita la reutilización: Microsoft MFC,
controles VB, objetos COM, Java Beans, etc.
Ingeniería del Software 2 – Curso 2009-2010 33
Sin fiabilidad no hay reusabilidad. Un componente reutilizado debería ser tan fiable (correcto
y robusto) como la máquina sobre la que funciona. También es esencial que estén
perfectamente especificados los contratos de operación del componente reutilizado.
Elección de un componente para reutilizarlo:
o ¿Está documentado tanto como el resto de la aplicación?
o ¿Hay que adaptar el componente o la aplicación para poder usarlo? (proxy,
recubrimiento).
o ¿Ha sido probado tanto como el resto de la aplicación?
Reutilizar tanto desarrollos (marcos, componentes) como ideas (patrones).
Noción de dependencia
La clave para lograr una descomposición modular eficaz es minimizar las dependencias.
La relación de dependencia (representada como una flecha discontinua) significa que:
o el elemento dependiente requiere la presencia del elemento independiente, y
o los cambios en el elemento independiente pueden afectar al elemento dependiente.
La dependencia puede establecerse entre cualesquiera dos elementos (componentes, clases…).
Ingeniería del Software 2 – Curso 2009-2010 35
Noción de interfaz
La dependencia queda mejor definida si se establece con respecto a una interfaz.
o De esta manera se establece una dependencia parcial o restringida: la dependencia ya
no es hacia el componente/clase, sino sólo hacia la interfaz.
o Una misma interfaz puede ser realizada por varios componentes/clases.
o Un componente UML equivale aproximadamente a un paquete Java.
Dos formas alternativas de representación:
o Abreviada: icono circular.
o Completa: rectángulo «interface» con compartimentos para atributos y operaciones.
Características de una interfaz:
o No contiene la implementación de las operaciones (métodos).
o Puede contener también atributos (properties). Esto es nuevo en UML2.
o Si un componente/clase realiza una interfaz, se compromete a implementar todas las
operaciones definidos en la interfaz. Puede tener más operaciones, pero no menos.
o Dos interfaces ofrecidas por un mismo componente no son necesariamente disjuntas.
Cómo se deben nombrar las interfaces:
o Suelen nombrarse empezando por “i” (regla de estilo no obligatoria).
o El nombre de la interfaz debe escogerse para que signifique adecuadamente el “nombre
común” (en singular) de todas sus instancias indirectas. Ejemplos:
iCaminante: implementada por Hormiga, Robot…(operaciones: avanzar, girar…).
iImprimible: implementada por Texto, Imagen … (operaciones: imprimir…).
Definición de interfaz:
o De modo general (no sólo en OO/UML, también en programación estructurada) una
interfaz es un conjunto de operaciones que ofrecen un servicio coherente.
o Pero en OO/UML toda operación se invoca sobre una instancia (salvo el caso especial
de las operaciones estáticas):
Para usar las operaciones de la interfaz es necesario crear en el componente una
clase que realiza (o implementa) la interfaz, y es necesario instanciar esta clase.
Las operaciones se invocan sobre las instancias “indirectas” de la interfaz
(instancias de la clase o clases compatibles con la interfaz).
o Así pues, una interfaz define un tipo (un tipo abstracto de datos) que proporciona un
conjunto coherente de operaciones sobre las instancias compatibles con ese tipo.
o Análoga a una clase abstracta con todas sus operaciones abstractas: no puede tener
instancias directas.
Cómo usar/instanciar las interfaces de un componente:
o Problema: para crear una instancia indirecta de una interfaz necesito una operación (las
interfaces no tienen constructores), pero sólo puedo utilizar la operación si previamente
ya tengo una instancia sobre la que invocarla.
o Existen dos soluciones generales, más una intermedia:
Proporcionar una o más clases públicas compatibles, usar sus constructores.
Proporcionar una fábrica y gestor de instancias (patrón AbstractFactory).
Proporcionar la interfaz, pero no las clases concretas.
o Ejemplo: componente GestiónEmpleados:
interfaz iEmpleado, clases públicas EmpleadoFijo, EmpleadoTemporal, etc.: más
flexibilidad, menos encapsulación (las clases se puede usar en cualquier lugar).
interfaz iGestorEmpleados, clase pública GestorEmpleados, clases de paquete (no
visibles desde fuera del mismo) EmpleadoFijo, etc.: más encapsulación, menos
flexibilidad (las operaciones de GestorEmpleados no pueden recibir ni devolver
valores de tipo Empleado).
interfaz iGestorEmpleados, interfaz iEmpleado, clase pública GestorEmpleados
clases privadas EmpleadoFijo, etc.: situación intermedia (no se puede usar el
constructor directamente, pero sí el tipo abstracto iEmpleado).
Ingeniería del Software 2 – Curso 2009-2010 36
Anidamiento de componentes
Los subcomponentes/clases que constituyen un componente se muestran en su interior.
No hay límite en el número de niveles de anidamiento, ni en el cableado interno.
La correspondencia entre interfaces super/sub componente requiere:
o Definición de puertos para las interfaces externas del supercomponente.
o Conectores de delegación entre puertos e interfaces internas (dependencia).
El sentido de la dependencia de delegación siempre es:
o Desde el puerto hacia la interfaz interna proporcionada.
o Desde la interfaz interna requerida hacia el puerto.
Un puerto tiene nombre y tipo (opcionales), puede contener varias interfaces proporcionadas y
requeridas, y puede delegar hacia/desde varias interfaces internas. Pero debe mantenerse una
definición consistente de los puertos, sin mezclar interfaces que tengan poco que ver entre sí.
Un puerto UML equivale aproximadamente a una clase pública de un paquete Java (patrón
Fachada).
Arquitecturas de repositorio
Son arquitecturas construidas principalmente en torno a los datos.
Desacoplan los componentes clientes de los que proporcionan persistencia y gestión de datos.
Ejemplos:
o Sistema de transacciones contra una base de datos.
o Entornos de desarrollo interactivos (IDEs).
o Editores de texto, aplicaciones ofimáticas.
o Repositorio (en sentido restringido): acceso uniforme a una colección de BD.
Es adecuada cuando el procesamiento es despreciable frente al formateado y almacenamiento
de los datos; extensibilidad y modificabilidad en la estructura de datos.
Peligro: que haya una gran candidad de procesamiento escondido entre los datos; complicar la
base de datos con procedimientos ad hoc almacenados que pervierten el diseño limpio de la
aplicación.
¿Cómo se logra un diseño mantenible? Para encontrar las clases abstractas adecuadas:
Anticipar una lista de posibles cambios
Examinar críticamente el diseño inicial, evaluar la mantenibilidad
Encapsular posibles variaciones dentro de clases abstractas
Un buen diseño debe localizar los efectos de los posibles cambios anticipados
Encapsular decisiones de diseño difíciles o arriesgadas
Las clases abstractas nos protegen de posibles variaciones futuras
Todo lo contario de “simular entidades del mundo real”
No creamos clases abstractas porque son evidentes en el dominio, las creamos porque hay
cambios que pueden venir del dominio y queremos controlar su impacto en el sistema
Esta técnica recibe diversos nombres: análisis defensivo (Haythorn), análisis de robustez
(Jacobson), “objetificar” las variaciones (Gamma)
Ejemplos. Parchís: tablero, jugadores, turnos, reglas...
1. ¿Qué caracteriza el diseño orientado a objetos frente al diseño basado en objetos? ¿Por qué
es insuficiente el diseño basado en objetos desde el punto de vista de la mantenibilidad?
¿Cómo ayuda la orientación a objetos a reducir la “complejidad” de un programa?
2. Describa brevemente en qué consiste el método propuesto por Wayne Haythorn para
obtener “clases magníficas”, y qué beneficios aporta. ¿Cómo se aplica el método para evaluar
y comparar diseños?
Elaborar una lista de cambios previsibles. Diseñar clases abstractas (interfaces) que
encapsulen la variabilidad identificada y así defiendan el diseño frente a ella. Medir y comparar las
modificaciones que requeriría cada diseño para hacer frente a esos cambios.