Sunteți pe pagina 1din 22

Instituto Universitario de

Tecnología
del Estado Trujillo

INGENIERIA DE SOFTWARE
Maily Nava, C.I: 13.048.734
PNF en Informática Trayecto III Fin de Semana

FRAMEWORKS, PATRONES DE DISEÑO


COMPONENTES
MEDICIÓN DE ATRIBUTOS DE DISEÑO

1.- Introducción a los marcos (frameworks)


 Al inventar el modelo de clases puede ser recomendable desarrollar o utilizar una
colección de software preexistente que forma la base de una familia de aplicaciones
similares: esta colección es lo que llamamos un marco (framework).
 Un marco es una colección de clases, normalmente interrelacionadas e incluidas en un
paquete, que pueden ser usadas por varias aplicaciones diferentes. Las clases de un
marco pueden ser abstractas, es decir, pensadas para usarse sólo a través de herencia.
 La aplicación se descompone en paquetes marco y paquetes de aplicación que los usan
 Ejemplo: Java Application Programming Interface (API)
 Los paquetes de la aplicación se relacionan con los paquetes marco a través de
herencia o Agregación (en realidad asociación, o tipado).
 Java Abstract Windowing Toolkit: el paquete awt no se modifica al usarlo, sino que las
clases propias de la aplicación heredan de clases awt, o agregan objetos awt en
forma de atributos.
 Los marcos pueden ser de propósito general o específico:
 General: sirven para un rango de aplicaciones muy variado (Java API)
 Específico: desarrollados a la vez que una aplicación determinada, sólo
servirán normalmente para aplicaciones muy semejantes.
 Algunos creen que los marcos sólo deberían desarrollarse si van a ser usados por un
gran número de aplicaciones. No obstante, también hay ventajas en desarrollar un
marco parcial en paralelo con una aplicación, aunque no vaya a ser empleado en
muchas otras aplicaciones.
 Ejemplos de marcos específicos:
 Encounter: marco para juegos de rol en general.
 Parchís: marco para juegos de tablero y fichas.

Marcos (frameworks) y Patrones


 Marco: conjunto de clases reutilizable, librería
 reutilizar desarrollos
 Patrón: estructura que proporciona una determinada función
 reutilizar ideas
 Relación entre ambos:
 Los marcos implementan patrones
 Los marcos pueden implementar otras ideas que no sean “patrones”
 Los patrones pueden implementarse directamente sin usar marcos
2.- Patrones de Diseño Software
Christopher Alexander comenta en su libro publicado en 1977 "A Pattern Language:
Towns/Building/Construction", que “Cada patrón describe un problema que ocurre una y
otra vez en nuestro entorno, para describir después el núcleo de la solución a ese
problema, de tal manera que esa solución pueda ser usada más de un millón de veces sin
hacerlo siquiera dos veces de la misma forma”. El patrón es un esquema de solución que se
aplica a un tipo de problema, esta aplicación del patrón no es mecánica, sino que requiere
de adaptación y matices. Por ello, dice Alexander que los numerosos usos de un patrón no
se repiten dos veces de la misma forma.
La idea de patrones de diseño estaba "en el aire", la prueba es que numerosos
diseñadores se dirigieron a aplicar las ideas de Alexander a su contexto. El catálogo más
famoso de patrones se encuentra en “Design Patterns: Elements of Reusable Object-
Oriented Software”, de Erich Gamma, Richard Helm, Ralph Johnson y John Vlissides,
1995, Addison-Wesley, también conocido como el libro GOF (Gang-Of-Four).
Siguiendo el libro de GOF los patrones se clasifican según el propósito para el que han
sido definidos:
• Creacionales: solucionan problemas de creación de instancias. Nos ayudan a
encapsular y abstraer dicha creación.
• Estructurales: solucionan problemas de composición (agregación) de clases y
objetos.
• De Comportamiento: soluciones respecto a la interacción y responsabilidades entre
clases y objetos, así como los algoritmos que encapsulan.
Según el ámbito se clasifican en patrones de clase y de objeto:
Creación Estructural De Conducta
Método de Interprete
Clase Adaptador (clases)
Fabricación Plantilla
Cadena de Responsabilidad,
Fábrica, Adaptador (objetos),
Comando (orden), Iterador,
Constructor, Puente, Composición,
Objeto Intermediario, Observador,
Prototipo, Decorador, Fachada,
Estado, Estrategia, Visitante,
Singleton Flyweight
Memoria

Concepto de patrón de diseño:

"Una arquitectura orientada a objetos bien estructurada está llena de patrones. La


calidad de un sistema orientado a objetos se mide por la atención que los diseñadores han
prestado a las colaboraciones entre sus objetos. Los patrones conducen a arquitecturas más
pequeñas, más simples y más comprensibles". (Grady Booch)
Los patrones de diseño son descripciones de clases cuyas instancias colaboran
entre sí. Cada patrón es adecuado para ser adaptado a un cierto tipo de problema. Para
describir un caso debemos especificar:
• Nombre
• Propósito o finalidad
• Sinónimos (otros nombres por los que puede ser conocido)
• Problema al que es aplicable
• Estructura (diagrama de clases)
• Participantes (responsabilidad de cada clase)
• Colaboraciones (diagrama de interacciones)
• Implementación (consejos, notas y ejemplos)
• Otros patrones con los que está relacionado

Ventajas de los patrones:


La clave para la reutilización es anticiparse a los nuevos requisitos y cambios, de
modo que los sistemas evolucionen de forma adecuada. Cada patrón permite que algunos
aspectos de la estructura del sistema puedan cambiar independientemente de otros
aspectos. Facilitan la reusabilidad, extensibilidad y mantenimiento.
Un patrón es un esquema o microarquitectura que supone una solución a
problemas (dominios de aplicación) semejantes (aunque los dominios de problema pueden
ser muy diferentes e ir desde una aplicación CAD a un cuadro de mando empresarial).
Interesa constatar una vez más la vieja distinción entre dominio del problema (donde
aparecen las clases propias del dominio, como cuenta, empleado, coche o beneficiario) y el
dominio de la solución o aplicación (donde además aparecen clases como ventana, menú,
contenedor o listener). Los patrones son patrones del dominio de la solución.
También conviene distinguir entre un patrón y una arquitectura global del sistema. Por
decirlo en breve, es la misma distancia que hay entre el diseño de un componente (o
módulo) y el análisis del sistema. Es la diferencia que hay entre el aspecto micro y el macro,
por ello, en ocasiones se denomina a los patrones como "microarquitecturas".
En resumen, un patrón es el denominador común, una estructura común que tienen
aplicaciones semejantes. Esto también ocurre en otros órdenes de la vida. Por ejemplo, en
nuestra vida cotidiana aplicamos a menudo el esquema saludo-presentación-mensaje-
despedida en ocasiones diversas, que van desde un intento de ligar hasta dar una
conferencia (si todavía no cree que existan patrones o que no son útiles intente ligar con el
esquema despedida-mensaje-presentación-saludo, a ver que ocurre).

Cómo seleccionar un patrón de diseño:


• Considerar cómo los patrones de diseño resuelven problemas de diseño.
• Explorar los “propósitos” (intent) de los patrones.
• Estudiar cómo se interrelacionan los patrones.
• Estudiar patrones de propósito similar.
• Examinar posibles causas de rediseño.
• Considerar lo que podría variar en el diseño.

Cómo usar un patrón de diseño:


• Leer el patrón entero para tener una impresión general sin profundizar.
• Volver a estudiar la Estructura, Participantes y Colaboraciones.
• Observar la Muestra de Código para ver un ejemplo concreto del patrón.
• Elegir nombres para los participantes en el patrón que sean significativos en el
contexto de la aplicación.
• Definir las clases.
• Definir nombres específicos de la aplicación para las operaciones del patrón.
• Implementar las operaciones para llevar a cabo las responsabilidades y
colaboraciones en el patrón.

Algunos patrones de diseño


Delegado (Delegate)
Compuesto (Composite)
Decorador (Decorator)
Mediador (Mediator)
Iterador (Iterator)
Observador (Observer)
Modelo-vista-controlador (Model-View-Controller)
Factoria (Factory)
Data Access Object (DAO)

PATRÓN "DELEGADO"
Descripción
La herencia es útil para modelar relaciones de tipo es-un o es-una, ya que estos tipos de
relaciones son de naturaleza estática. Sin embargo, relaciones de tipo: es-un-rol-ejecutado-
por, son mal modeladas con herencia.
Un objeto receptor delega operaciones en su delegado. Presente en muchos patrones:
State, Strategy, Visitor,..
Un ejemplo: supongamos que un objeto debe ordenar una estructura de datos. Puede
delegar en otro objeto el método de comparación. En Java tenemos un caso: la clase
Collections tiene el método estático sort(); desde este método se delega en un comparador
para establecer el orden:
• Collections tiene el método sort() con un algoritmo de ordenación.
• Comparador tiene el método compare() que implementa el orden de comparación.

PATRÓN "COMPUESTO"
Descripción
Crear jerarquías parte/todo de tal forma que los clientes manejan a los objetos primitivos y
compuestos de forma uniforme. Por ejemplo, crear figuras que son una composición de
otras figuras simples. Otro ejemplo puede ser un activo financiero (un fondo de inversión)
que es un compuesto de otros activos financieros simples (valores o acciones).
Los clientes pueden tratar objetos primitivos y compuestos de modo uniforme y es fácil
añadir nuevos tipos de componentes.

Implementación
Vamos a ver un ejemplo con un applet AWT en donde existen diferentes subclases de
Component:
• Componentes simples como TextField, List, Button, etc.
• Componentes compuestos como Container, del que hereda Panel.

Veamos los atributos de la clase:


Para crear compuestos podemos:
• Añadir un componente simple a un Panel (tipo de Container): panel_sup.add( t_n1 )
• Crear compuestos recursivos, añadiendo un Panel a otro Panel: panel_global.add(
panel_sup, BorderLayout.NORTH )
Referencias de componentes hijos a su padre puede ayudar a el recorrido y manejo de la
estructura compuesta.

PATRÓN "DECORADOR"
Descripción
Imaginemos que tenemos un editor de texto básico y queremos añadirle nuevas
funcionalidades, como un scroll o un borde. Una solución podría ser crear subclases para un
editor con scroll, sin scroll, con scroll y con borde, etc. Evidentemente esta no es una buena
solución, ya que acabamos con una jungla de clases y subclases.
Con este patrón tratamos de evitar este efecto de herencia-jungla, ya que asignamos
dinámicamente nuevas responsabilidades a un objeto. Es una alternativa más flexible
a crear subclases para extender la funcionalidad de una clase. De esta forma añadimos
atributos o comportamiento adicional a un objeto concreto, no a una clase.

El componente no conoce a su decorador (en este caso el scroll). Es el decorador el que


referencia a su componente. Esta es la razón de que al añadir (add) al contenedor raíz
debamos usar el decorador (scroll) y no el componente (editor).
Componentes y decoradores deben heredar de una clase común. En nuestro ejemplo
JEditorPane y JScrollPane heredan de JComponent.
PATRÓN "INTERMEDIARIO"
Descripción
Supongamos una ventana con numerosos componentes gráficos (widgets) que tienen
fuertes dependencias entre si. Por ejemplo, reglas del tipo "si el campo de edición E2 está
relleno, entonces inhabilito el botón B1 y el campo de edición E3".
El mediador o intermediario encapsula la forma en que interaccionan un conjunto de objetos
("colegas"). Es el especialista que define las interdependencias entre ellos. Favorece un bajo
acoplamiento, ya que evita que los objetos se referencien unos a otros de forma explícita.
Permite variar la interacción sin tocar los colegas, por tanto favorece la reutilización.

Ventajas:
• Evita crear subclases
• Desacopla a los colegas
• Simplifica los protocolos entre las clases
• Abstrae el cómo cooperan los objetos
• Centraliza el control en el mediador: clase difícil de mantener

Para la implementación:
• No hay necesidad de definir una clase abstracta Mediator si los colegas trabajan con
un único mediador
• Los colegas deben comunicarse con el mediador cuando un evento de interés ocurre,
esta comunicación puede hacerse con un Observer o un interfaz de notificación
(ViewManager de Smalltalk-V).
• Cada colega tiene una referencia al mediador y de esta manera le pueden informar de
los cambios realizados. Por ejemplo, una lista informa al mediador del cambio de item
seleccionado; el mediador puede responder solicitando el texto seleccionado en la
lista y mandándolo a un campo de texto. Ver el siguiente diagrama:
PATRÓN "ITERADOR"
Descripción
Supongamos que tenemos un contenedor (por ejemplo, un vector) y queremos tener una
forma de acceder a los elementos sin mostrar los detalles. Un objeto contenedor debe
permitir una forma de recorrer sus elementos sin exponer su estructura interna, es decir,
separar el contenedor de la forma de recorrer sus elementos. Con este patrón tenemos
la ventaja de simplificar la interfaz de un contenedor, ya que no contiene los métodos de
recorrerlo.
Un ejemplo típico lo tenemos en Java. El cliente solicita al contenedor un iterador. A
continuación el iterador dirige la forma de recorrer el contenedor:
PATRÓN "OBSERVADOR"
Descripción
Definir una dependencia de 1:n de forma que cuando el objeto 1 cambie su estado, los n
objetos sean avisados y se actualicen automáticamente.
Supongamos que tenemos un o unos objetos dependientes de otro. Por ejemplo,
supongamos que una ventana o applet depende de los componentes gráficos que reciben
eventos (clic en botón, etc.). Otro caso, típico del patrón, es tener diversas vistas de una
fuente de datos, de tal forma que si cambia la fuente, entonces las vistas se actualicen
automáticamente.
El observador no es un mediador entre los sujetos (objetos que cambian de estado) y los
objetos dependientes, ya que el mismo es un objeto dependiente. El observador recibe la
orden de actualizarse por parte del sujeto "dominante"

Interesante cuando un cambio en un objeto implique cambios en otros y no se sepa cuantos


objetos necesitan cambiar. Como se puede observar en el siguiente diagrama el sujeto tiene
un método notify() que se encarga de mandar el mensaje de update() a todos los
observadores.

Permite la división de un sistema en niveles. Además de permitir reusar sujetos y


observadores por separado.
Una extensión natural de este patrón es hacer mezcla del patrón mediador y del patrón
observador, de tal forma que los avisos de cambios que mandamos al observador sean
notificados a otros objetos dependientes. El observador recibe un mensaje de cambio de
estado y notifica a los objetos dependientes que se actualicen. Dicho de otra forma, cuando
las relaciones de dependencia entre Subject y Observer son complicadas conviene
encapsular la semántica de actualización en una clase ManejadorCambio(Mediador).

Implementación
Es posible que un observer esté ligado a más de un subject: la operación update tendrá
como argumento el subject.¿Quién dispara la notificación?
• Métodos set en la clase Subject
• Clientes de la clase Subject
Asegurarse de notificar siendo el estado de Subject consistente. Al registrar un observer es
posible asociarle el evento sobre el que quiere ser notificado:

PATRÓN "MODELO-VISTA-CONTROLADOR"
Descripción
Para el diseño de aplicaciones con sofisticados interfaces se utiliza el patrón de diseño
Modelo-Vista-Controlador. La lógica de un interfaz de usuario cambia con más frecuencia
que los almacenes de datos y la lógica de negocio. Si realizamos un diseño ofuscado, es
decir, un pastiche que mezcle los componentes de interfaz y de negocio, entonces la
consecuencia será que, cuando necesitemos cambiar el interfaz, tendremos que modificar
trabajosamente los componentes de negocio. Mayor trabajo y más riesgo de error.
Se trata de realizar un diseño que desacople la vista del modelo, con la finalidad de mejorar
la reusabilidad. De esta forma las modificaciones en las vistas impactan en menor medida
en la lógica de negocio o de datos.
Elementos del patrón:
• Modelo: datos y reglas de negocio
• Vista: muestra la información del modelo al usuario
• Controlador: gestiona las entradas del usuario

Un modelo puede tener diversas vistas, cada una con su correspondiente controlador. Un
ejemplo clásico es el de la información de una base de datos, que se puede presentar de
diversas formas: diagrama de tarta, de barras, tabular, etc. Veamos cada componente:
1. El modelo es el responsable de:
o Acceder a la capa de almacenamiento de datos. Lo ideal es que el modelo sea
independiente del sistema de almacenamiento.
o Define las reglas de negocio (la funcionalidad del sistema). Un ejemplo de
regla puede ser: "Si la mercancía pedida no está en el almacén, consultar el
tiempo de entrega estándar del proveedor".
o Lleva un registro de las vistas y controladores del sistema.
o Si estamos ante un modelo activo, notificará a las vistas los cambios que en
los datos pueda producir un agente externo (por ejemplo, un fichero bath que
actualiza los datos, un temporizador que desencadena una inserción, etc).

2. El controlador es responsable de:


o Recibe los eventos de entrada (un clic, un cambio en un campo de texto, etc.).
o Contiene reglas de gestión de eventos, del tipo "SI Evento Z, entonces Acción
W". Estas acciones pueden suponer peticiones al modelo o a las vistas. Una
de estas peticiones a las vistas puede ser una llamada al método "Actualizar()".
Una petición al modelo puede ser "Obtener_tiempo_de_entrega(
nueva_orden_de_venta )".

3. Las vistas son responsables de:


o Recibir datos del modelo y los muestra al usuario.
o Tienen un registro de su controlador asociado (normalmente porque además lo
instancia).
o Pueden dar el servicio de "Actualización()", para que sea invocado por el
controlador o por el modelo (cuando es un modelo activo que informa de los
cambios en los datos producidos por otros agentes).
Un ejemplo de MVC con un modelo pasivo (aquel que no notifica cambios en los datos) es la
navegación web, que responde a las entradas del usuario, pero no detecta los cambios en
datos del servidor.

El diagrama de secuencia:
Pasos:
1. El usuario introduce el evento.
2. El Controlador recibe el evento y lo traduce en una petición al Modelo (aunque
también puede llamar directamente a la vista).
3. El modelo (si es necesario) llama a la vista para su actualización.
4. Para cumplir con la actualización la Vista puede solicitar datos al Modelo.
5. El Controlador recibe el control.
PATRÓN "FACTORIA"
Descripción
En realidad son una familia de patrones:
• Factoria simple: una clase que crea objetos de otras clases. No delega en otras
subclases y sus métodos pueden ser estáticos.
• Factory Method: Se define una interface para crear objetos, como en el Abstract
Factory, pero se delega a las subclases implementar la creación en concreto.
• Abstract Factory: Nos da una interface para crear objetos de alguna familia, sin
especificar la clase en concreto.
Los dos últimos están incluidos en el catálogo del GoF

Estos patrones entran en la categoría de patrones de creación [GoF95], la cual comparten


con otros patrones tales como el Singleton, Builder y Prototype [GoF95]. Tienen la
responsabilidad de crear instancias de objetos de otras clases. Tienen además la
responsabilidad y el conocimiento necesario para encapsular la forma en que se crean
determinados tipos de objetos en una aplicación. Existen diferentes patrones de tipo
Factory.
Factoria simple
Como en todas las factorias, tenemos las clases instanciadas (JuegoDelDado y
JuegoDeMoneda) que se relacionan con una clase madre (extends) o con un interfaz
lógico (implements). En nuestro caso usamos interfaz.
PATRÓN "DATA ACCESS OBJECT"
Descripción
El problema que viene a resolver este patrón es el de contar con diversas fuentes de datos
(base de datos, archivos, servicios externos, etc). De tal forma que se encapsula la forma de
acceder a la fuente de datos. Este patrón surge históricamente de la necesidad de gestionar
una diversidad de fuentes de datos, aunque su uso se extiende al problema de ancapsular
no sólo la fuente de datos, sino además ocultar la forma de acceder a los datos. Se trata de
que el software cliente se centre en los datos que necesita y se olvide de cómo se realiza el
acceso a los datos o de cuál es la fuente de almacenamiento.
Las aplicaciones pueden utilizar el API JDBC para acceder a los datos de una base de datos
relacional. Este API permite una forma estándar de acceder y manipular datos en una base
de datos ralacional. El API JDBC permite a las aplicaciones J2EE utilizar sentencias SQL,
que son el método estándar para acceder a tablas y vistas. La idea de este patrón es ocultar
la fuente de datos y la complejidad del uso de JDBC a la capa de presentación o de negocio.
Un DAO define la relación entre la lógica de presentación y empresa por una parte y por otra
los datos. El DAO tiene un interfaz común, sea cual sea el modo y fuente de acceso a datos.
Algunas características:
• No es imprescindible, pero en proyectos de cierta complejidad resulta util que el DAO
implemente un interfaz. De esta forma los objetos cliente tienen una forma unificada
de acceder a los DAO.
• El DAO accede a la fuente de datos y la encapsula para los objetos clientes.
Entendiendo que oculta tanto la fuente como el modo (JDBC) de acceder a ella.
• El TransferObject encapsula una unidad de información de la fuente de datos. El
ejemplo sencillo es entenderlo como un "bean de tabla", es decir, como una
representación de una tabla de la base de datos, por lo que representamos las
columnas de la tabla como atributos del TransferObject. El DAO crea un
TransferObject (o una colección de ellos) como consecuencia de una transacción
contra la fuente de datos. Por ejemplo, una consulta sobre ventas debe crear tantos
objetos (TransferObject) de la clase Venta como registros de la consulta; el DAO
devolverá la colección de TrasnferObject de la clase Venta al objeto Cliente. También
puede ocurrir que el objeto Cliente mande un TransferObject para parametrizar una
consulta o actualización de datos por parte del DAO.
En el siguiente gráfico se muestran las interacciones entre los elementos del patrón. En este
gráfico el TransferObject se denomina ValueObject. Puede observarse las llamadas que
recibe y genera el DAO para una consulta y actualización de datos:
1. El DAO es creado por el cliente (BusinessObject) (llamada 1 del gráfico).
2. A continuación el cliente solicita los datos al DAO (getData) (2).
3. El DAO responde a la llamada pidiendo los datos a la fuente de datos (2.1).
4. Para cada fila recibida, el DAO crea un TransferObjet (ValueObject del gráfico) (2.2).
5. El DAO devuelve al cliente el(los) TransferObject (2.3).
6. A continuación el cliente define un TransferObject mediante llamadas a setProperty.
Por ejemplo, supongamos que buscamos personas de sexo varón y 36 años; para
ello el BusinessObject define en el objeto de la clase Persona la edad y sexo que
busca. Lo siguiete es fácil de imaginar: el BusinessObject invoca al DAO, pasando a
la persona como argumento (3,4, y 5 del gráfico).
7. En DAO.setData() se solicita (5.1 y 5.2) al TransferObjet o ValueObject (nuestra
persona del ejemplo) los datos (edad, sexo, etc.) para realizar el acceso a datos
(dataSource.setData()), (5.3).
Ejemplo de código: los bean (Transfer Object)
En el siguiente sencillo ejemplo tenemos dos tablas en nuestra base de datos. La tabla de
clientes incluye:
• Codigo (clave primaria)
• Nombre, apellido 1 y apellido 2
• Edad
En la tabla de ventas tenemos las ventas realizadas a cada cliente:
• Id de la venta (clave primaria)
• Codigo de cliente (clave externa)
• Precio y coste de la venta
PATRÓN "PROXY"
Introducción
El proxy es útil si queremos añadir o modificar comportamiento de una clase (la
llamaremos "objeto real") sin tener que modificarla. El proxy es un intermediario que
implica un recubrimiento del objeto real.
El resultado final sería:
Otras características
El proxy y el objeto real comparten interface. El proxy debe tener una referencia al objeto
real.

Ya hemos dicho que el proxy es un intermediario que implica un recubrimiento del objeto
real para añadir o modificar comportamiento. Especialmente apropiado cuando estamos en
situaciones en las que tenemos que elegir entre las operaciones del objeto real y las del
proxy. Aunque en el ejemplo anterior no hacemos instancia del objeto real ni permitimos
ningún acceso directo a él, podríamos tener dos tipos de acceso: uno directo al objeto real y
otro al proxy.
3.- Componente

• Bloque de construcción modular para software de computadora.


• “Una parte modular, entregable y reemplazable de un sistema que encapsula su
implementación y expone un conjunto de interfaces” según la OMG Unified Modeling
Language Specification.
• Se puede definir y usar componentes desde 3 puntos de vista:
 Orientado a Objetos
 “Convencional”
 Relacionado a procesos

Orientado a objetos:
 Desde este punto de vista, un componente contiene un conjuunto de clases que
colaboran entre sí.
 El diseño de un componente implica añadir a la definición de clases en el análisis
(dominio del problema) información para su implementación en software.

Ejemplo de elaboración de un componente de diseño

[Pressman 2005]
“Convencional”

 Desde este punto de vista, un componente es un elemento funcional de un programa


que incluye lógica de procesamiento, estructuras de datos internas requeridas para
implementar dicha lógica y una interfaz que permite que el componente sea invocado
y que se le puedan pasar datos.
 Normalmente llamado “módulo”.

Roles de un componente “convencional”

 Componente de control: Coordina el llamado a otros componentes del dominio del


problema.
 Componente del dominio del problema: implementa una función completa o parcial
que es requerida por el usuario.
 Componente de infraestructura: responsable de las funciones que apoyan el
procesamiento requerido en el dominio del problema.
 Utilizan cartas de estructura para describir sistemas.

Relacionado a procesos

 Reutiliza software.
 Cuando se desarrolla la arquitectura, se escogen componentes o patrones de diseño
de un catálogo, los cuales fueron creados para ser reutilizados.

Diseñando componentes basados en clases: Hay 4 principios básicos de diseño que se


pueden aplicar:
- Principio “abierto-cerrado”: Un componente debe estar abierto a extensiones pero
debe estar cerrado para modificaciones. El/la diseñador(a) debe especificar el
componente de manera que puede extenderse sin necesidad de hacer modificaciones
internas al código.
- Principio de substitución de Liskov: Las subclases deben ser sustituibles por sus
clases bases. Cualquier clase derivada de una clase base debe cumplir con cualquier
contrato implícito de la clase base con respecto a los componentes que la usan. Un
“contrato” es una precondición que debe ser verdadera antes de que el componente
use la clase base, y una post-condición debe ser verdadera después de que el
componente usa la clase base.
- Principio de dependencia de inversión: “Se debe depender de abstracciones, no
de eventos concretos”
- Principio de segregación de interfaces: “Varias interfaces dependientes del cliente
son mejor que una interfaz de propósito general”
- Principio de equivalencia de liberación y reuso: “La granularidad del reusó es la
granularidad de liberación.” Agrupar clases reusables en paquetes que se puedan
administrar y controlar cuando una nueva versión se genere.
- Principio de agrupamiento común: “Las clases que cambian al mismo tiempo
deben agruparse”
- Principio de reuso común: “Las clases que no se reúsan al mismo tiempo no deben
agruparse”
4.- Medición de Atributos de calidad y entidades de diseño

En primer lugar debemos acotar el contexto en el que nos movemos, ya que la


calidad, en el software, se puede entender como calidad de proceso o de producto. La
calidad de proceso ha sido objeto de mucho interés en las últimas décadas (Humphrey,
1989) y su desarrollo ha concienciado a los profesionales de la necesidad de aplicar la
calidad a otros aspectos del software. En nuestro caso estamos claramente centrados en la
calidad del producto software y, dentro de ella, en el producto derivado de la fase de diseño
(Software design, part 2, 2004). Fenton y Pfleeger (1998) explican que es un paso previo al
establecimiento de las métricas el definir qué atributos o propiedades de qué elementos son
los que queremos medir.
Posteriormente podremos establecer si para medir dichos atributos es necesario
medir otros y derivar los que nos interesan de ellos o bien se puede hacer directamente. En
nuestro caso la única norma que hemos encontrado en la literatura que da una definición de
calidad de producto software en base a atributos es ISO 9126 (ISO/IEC, 2001). Dicha norma
establece que la medición de la calidad de un producto software debe hacerse en base a
sus atributos, siendo éstos internos, propiedades características de cómo se estructura el
software, o externos, cualidades observables aún sin conocer cómo está construido.
De hecho no se habla de calidad, en general, sino de calidad interna y calidad
externa, afirmándose que la calidad interna de un producto software influye directamente en
su calidad externa. De algún modo se está diciendo que mejorando la calidad interna se
mejora directamente la calidad observada en atributos de uso del producto software. Tanto
la calidad interna como la externa se definen, en ISO 9126, como un conjunto de 6
características:
• Funcionalidad: la capacidad del software de proveer las funciones que cumplen con las
necesidades implícitas y explícitas cuando el mismo es utilizado bajo ciertas condiciones.
• Fiabilidad: la capacidad del software de mantener un nivel específico de rendimiento bajo
determinadas condiciones de uso.
• Usabilidad: la capacidad del producto software de ser entendido, aprendido, usado y
atractivo al usuario, cuando se usa bajo ciertas condiciones.
• Eficiencia: la capacidad del software de ofrecer el rendimiento apropiado con respecto a la
cantidad de recursos utilizados, bajo condiciones prefijadas.
• Mantenibilidad: la capacidad del producto de ser modificado. Dichas modificaciones
pueden incluir correcciones, mejoras o adaptaciones a cambios en el entorno y en los
requisitos y especificaciones funcionales.
• Portabilidad: la capacidad del software de ser trasladado de un entorno (informático) a
otro.
Estas características son generales para cualquier tipo de programa informático o
software independientemente de si el paradigma empleado para construirlo es el Orientado
a Objetos, el estructurado u otro cualquiera, sin embargo si que afectará a la manera de
medirlas. Dichas características se dividen a su vez en subcaracterísticas tal como se puede
ver en el siguiente esquema.
5.- CONCLUSIÓN

Los patrones considerados en este trabajo, y muchos otros que podrían ser útiles en
el desarrollo de programas o software, proporcionan soluciones elegantes a determinados
problemas y hacen que, en general, el software desarrollado sea más fácil de mantener y de
ampliar. Como contrapartida, normalmente implican algún nivel adicional de
direccionamiento, que en casos concretos puede implicar una cierta pérdida de eficiencia.
Se usen o no patrones, nuestra conclusión final es que el tiempo dedicado a realizar
un cierto análisis y diseño previo, tratando de formalizar (en cierta forma) los conceptos a
plasmar en forma de programas mediante una notación como UML, no es un tiempo
perdido, siempre que no se caiga en una “análisis-parálisis”, el extremo contrario.

6.- ANEXOS
EJEMPLOS DE PATRONES

Patrones de creación: Abstract Factory


Ejemplos:
 Editor de documentos adaptable a distintos estándares de apariencia.
 Juegos con representación 2D o 3D.
 Diseño de interiores: mobiliario de una cocina.
 Problema:
- El cliente usa una familia de objetos relacionados.
- Se desea flexibilizar el diseño para que sea fácil cambiar de una familia a otra.
- La estructura de la familia es común en todas las familias: cambia el tipo de familia,
pero no la forma de usarla (interfaz); cada familia representa un “estilo” diferente para
objetos conceptualmente iguales.
 Solución:
- Se define una interfaz (clase abstracta) para cada objeto o producto de la familia: el
cliente conoce esta interfaz, pero no la clase concreta utilizada.
- Cada familia tiene una factoría de objetos asociada; las distintas factorías de objetos
tienen también una interfaz común.
- Se crea una factoría concreta (instancia de la subclase concreta; patrón Singleton); es
fácil cambiarla en tiempo de ejecución; la factoría escogida determina la familia
entera, estilo de presentación, etc.
- En lugar de usar los constructores concretos (que requerirían mencionar las clases
concretas), la factoría proporciona una interfaz uniforme para la creación de objetos
de todas las familias.
 Consecuencias:
- (+)El cliente manipula los objetos de la familia a través de la definición abstracta de la
familia (interfaz común); no menciona en absoluto las clases concretas utilizadas, que
sólo son conocidas por la factoría.
- (+)Es fácil cambiar en tiempo de ejecución la familia concreta utilizada (estilo).
- (+)Facilita el uso consistente de objetos de una misma familia (sin mezclas).
- (–)Dificulta la adición de nuevos productos a la familia, ya que habría que modificar la
interfaz de las factorías y todas las factorías concretas.

Patrones de estructura: Decorator


Ejemplos:
 Añadir elementos gráficos en un editor de documentos.
 Añadir efectos sonoros o visuales en un juego.
 Problema:
- Es posible añadir responsabilidades mediante la especialización: la subclase hace
todo lo que hace la superclase, y añade los efectos deseados.
- Pero este diseño resulta inflexible, ya que las responsabilidades se definen de modo
estático, no es posible añadirlas en tiempo de ejecución.
- Podría producirse incluso una explosión de especializaciones, para intentar reflejar
todas las posibles combinaciones de responsabilidades.
 Solución:
- Empaquetar el objeto dentro de otro que añade las responsabilidades.
- El objeto que empaqueta o decorador tiene la misma interfaz que el objeto
componente, de modo que su presencia es transparente al cliente
- Los decoradores se pueden empaquetar de modo recursivo, formando una cadena de
decoradores ilimitada hasta llegar al componente concreto.
- La cadena se puede modificar fácilmente en tiempo de ejecución, añadiendo o
quitando responsabilidades.
- Cada operación del decorador se transmite por la cadena hasta llegar al componente
concreto; cada decorador puede añadir responsabilidades antes o después en cada
paso.
 Consecuencias:
- (+)Mayor flexibilidad que la herencia, que es estática.
- (+)Permite la adición incremental de responsabilidades, en lugar de intentar soportar
todas las responsabilidades imaginables en clases complejas.
- (–)Aunque la interfaz sea la misma, la identidad del decorador no es la misma que la
del componente: transparencia de interfaz, pero no de identidad.
- (–)Añade multitud de pequeños objetos que sólo se diferencian por la forma en que
están conectados, dificultando la comprensión de la estructura.

S-ar putea să vă placă și