¿Qué
es un patrón?
En
programación orientada a objetos se entiende por patrón una solución
probada que se puede aplicar con éxito a un determinado tipo de problemas que
aparecen repetidamente en el desarrollo de sistemas software.
Los patrones no son
una librería. Van más bien en la línea de un esqueleto básico que cada
desarrollador luego adapta a sus necesidades y a las peculiares características
de su aplicación. Se describen fundamentalmente en forma textual, acompañada de
diagramas y de seudo-código.
Algunas
definiciones:
“cada patrón es una
regla de tres partes, la cual expresa una relación entre un contexto dado, un
conjunto de fuerzas que ocurren repetitivamente en ese contexto y cierta configuración
de software que permite a esas fuerzas resolverse por sí mismas”
“Un patrón es una
pedazo de información con nombre, instructivo y significante, que captura la
esencia de una familia exitosa y completa de soluciones a un problema recurrente
en una contexto dado"
Un buen patrón debe:
-Solucionar un
problema: Un patrón captura soluciones, no solo principios abstractos o
estrategias
-Es un concepto
probado
-La solución no es
obvia
-Describe una relación:
No solo describen módulos, describen estructuras y mecanismos
-Tiene un componente
humano significante: es estético y de utilidad
Objetivos de los
patrones:
Los patrones de
diseño pretenden:
- Proporcionar catálogos de elementos reusables en el diseño de sistemas software.
- Evitar la reiteración en la búsqueda de soluciones a problemas ya conocidos y solucionados anteriormente.
- Formalizar un vocabulario común entre diseñadores.
- Estandarizar el modo en que se realiza el diseño.
- Facilitar el aprendizaje de las nuevas generaciones de diseñadores condensando conocimiento ya existente.
Asimismo, no
pretenden:
- Imponer ciertas alternativas de diseño frente a otras.
- Eliminar la creatividad inherente al proceso de diseño.
No es obligatorio
utilizar los patrones, solo es aconsejable en el caso de tener el mismo
problema o similar que soluciona el patrón, siempre teniendo en cuenta que en
un caso particular puede no ser aplicable. "Abusar o forzar el uso de los
patrones puede ser un error".
Tipos de patrones
Existen
varios tipos de patrones, dependiendo del nivel de abstracción, del contexto
particular en el cual aplican o de la etapa en proceso de desarrollo. Algunos
de estos tipos son:
·
De arquitectura
·
De diseño
·
Idiomas
·
De análisis
·
Para ambientes distribuidos
·
De negocios
·
De procesos y organizacionales
Patrones de arquitectura
Son esquemas fundamentales de organización de
un sistema software.
Especifican una serie de subsistemas y sus
responsabilidades respectivas e incluyen las reglas y criterios para organizar
las relaciones existentes entre ellos.
Se recogen aquí ocho patrones estructurales,
agrupados en cuatro categorías:
Del caos a la organización
|
Niveles
Tuberías y filtros
Pizarra
|
Sistemas distribuidos
|
Intermediario o broker
|
Sistemas interactivos
|
MVC: Modelo-Vista-Controlador
PAC: Presentación, Abstracción, Control
|
Sistemas adaptables
|
Microkernel
Reflexión
|
Patrones de diseño
Son patrones de un nivel de abstracción menor
que los patrones de arquitectura. Están por lo tanto más próximos a lo que
sería el código fuente final. Su uso no se refleja en la estructura global del
sistema.
Características de los patrones de diseño
·
Son soluciones concretas. Un catálogo de patrones es un conjunto de
recetas de diseño. Aunque existen clasificaciones de patrones, cada uno es independiente
del resto.
·
Son soluciones técnicas. Dada una determinada situación, los patrones
indican cómo resolverla mediante OO. Hay patrones específicos para un
determinado lenguaje y otros de carácter más general.
·
Se aplican en situaciones muy comunes. Los patrones de diseño proceden de la
experiencia, y han demostrado su utilidad resolviendo problemas que aparecen
frecuentemente en el DOO.
·
Son soluciones simples. Indican cómo resolver un problema particular
utilizando un pequeño número de clases relacionadas de forma determinada. No
indican cómo diseñar un determinado sistema sino sólo aspectos puntuales del
mismo.
·
Facilitan la reutilización de las clases y
del propio diseño. Los patrones favorecen la reutilización de clases ya existentes y la
programación de clases reutilizables. La propia estructura del patrón es
reutilizada cada vez que se aplica.
·
El uso de un determinado patrón no se refleja
claramente en el código. A partir de la implementación es difícil determinar que patrón de diseño
se ha usado.
·
Referencias a self. Muchos patrones utilizan la delegación de
operaciones y esto provoca el problema del self.
·
Es difícil reutilizar la implementación de un
patrón. Las clases
del patrón son roles genéricos, pero en la implementación aparecen clases
concretas.
·
Los patrones suponen una sobrecarga de
trabajo a la hora de implementar.
·
Se usan más clases, es necesario delegar mensajes, etc.
Patrón Intermediario
- Este patrón define un objeto que encapsula como un conjunto de objetos interaccionan. El intermediario facilita el acoplamiento mínimo, evitando que los objetos participantes se tengan que referenciar entre ellos explícitamente , con lo que se permite variar su interacción independientemente. Los objetos participantes solo conocen al intermediario.
El
desarrollo orientado a objetos potencia el reparto de conducta entre objetos.
Tal reparto puede resultar en una arquitectura donde existen múltiples
conexiones entre los objetos. En el peor de los casos cada objeto debería
conocer a todos los demás. Esto dificulta la reutilización. Se puede evitar
esta situación, encapsulando la conducta colectiva en un objeto llamado
intermediario. Un intermediario es responsable de controlar y coordinar las
interacciones de un grupo de objetos. Esto puede ser útil como se verá en el
ejemplo de interacciones entre elementos gráficos
Patrones y componentes
Cabría aquí preguntarse por la diferencia
entre patrones de diseño y componentes. Encontramos en el
mercado una serie de productos que incorporan un conjunto de elementos,
denominados componentes y que permiten construir de forma rápida partes de la
aplicación, en particular la interfaz de usuario. La disponibilidad inmediata
de botones, ventanas, menús desplegables, etc hacen que la construcción de una
interfaz gráfica sea desde un punto de vista técnico una tarea relativamente
sencilla. Los problemas de interacción con el usuario y el nivel de usabilidad
tienen que ver con problemas de diseño más complejos que con la construcción
'física' de la interfaz.
La diferencia fundamental con un patrón es
que el componente es una combinación fija de objetos, que se puede instanciar
mediante el arrastre desde un icono que lo representa y que se incorpora
inmediatamente a la aplicación que se está construyendo. Esto significa que se
trata de clases que combinan un conjunto de otras formando macroobjetos pero
que están integradas en la librería de clases suministrada con el producto. De
esta manera, se pueden ir implementando nuevos componentes a los cuales se
asociarán íconos que los identifiquen y que permitan utilizarlos de la misma
manera que los suministrados originalmente con el producto.
Los patrones, por su lado, no forman parte de ninguna librería de
clases . Sólo son modelos de combinación que pueden utilizarse en el
momento que se presenta un problema similar al que pretende dar solución el
patrón correspondiente. A lo sumo, y en una instalación muy bien organizada,
podrían almacenarse en una base de datos a la cual accedemos cuando nos
enfrentamos a las diversas decisiones de diseño durante las fases de análisis y
de diseño.
Descripción de patrón y plantillas de
patrones
Dependiendo del autor, del nivel de abstracción y de la publicación
misma se han presentado varios formatos para encapsular la información de un
patrón. Los puntos más significativos que debe contener un patrón son:
- Nombre: Significativo y corto, fácil de recordar y asociar a la información que sigue
- Problema: Un enunciado que describe las metas y objetivos buscados y el contexto
- Contexto: Define las precondiciones en las cuales ocurren el problema y su solución
- Fuerzas: Descripción de las fuerzas y restricciones relevantes en el problema y como interactúan o entran en conflicto
- Solución: Las relaciones estáticas y reglas dinámicas que describen cómo solucionar el problema
- Ejemplos: Uno o más ejemplos que ilustren el contexto, el problema y su solución
- Contexto Resultante: El estado en el cual queda el sistema después de aplicar el patrón y las consecuencias de hacerlo
- Racionalidad: Una explicación justificada de los pasos o reglas en el patrón
- Relaciones: relaciones estáticas y dinámicas del patrón con otros
·
Usos conocidos: Describe ocurrencias del
patrón conocidas y su aplicación dentro de los sistemas existentes.
Patrón CallBack
Propósito
Permitir que un cliente se registre en un servidor para ciertas operaciones. De esta forma, el servidor puede notificar al
cliente cuando la operación ha finalizado.
Un
Gestor de información personal distribuido realizara periódicamente costosas
peticiones a un servidor. Por ejemplo, el tiempo necesario para recuperar un proyecto completo almacenado en un servidor es absolutamente
impredecible el proyecto podría tener miles de tareas y de desarrollos.
Ante esta situación, el hecho de mantener una
conexión de red abierta supondría una limitación para el
servidor. Aunque mantener esa conexión abierta podría mejorar la eficiencia del servidor, el tener una conexión por cada
cliente limita severamente el número de peticiones cliente que el servidor
puede procesar concurrentemente.
En vez de que le cliente y el servidor se
mantengan conectados, seria mejor permitir que el servidor se conectara con el
cliente cuando finalizara su petición correspondiente. El patrón CallBack
utiliza esta aproximación.
- El cliente envía una petición para recuperar un proyecto del servidor, ofreciendo la información necesaria para la retrollamada junto con la petición.
- El cliente se desconecta del servidor y permite que este emplee el tiempo necesario para recuperar el proyecto.
- Cuando el servidor completa la tarea, conecta con el cliente y envía información del proyecto solicitado.
Entre las ventajas obtenidas por el uso de
este patrón se incluyen el ahorro de ancho de banda y el uso más eficiente
del tiempo de procesamiento en el servidor. Esta solución también da ala
servidor la libertad de ejecutar acciones como poner en cola las peticiones y
utilizar prioridad en las tareas, para gestionar de forma mas eficiente los recursos disponibles en cada momento.
Aplicabilidad
Utilice el patrón callback para un sistema cliente/servidor en el que los clientes realicen operaciones costosas, y cuando una de las
dos reglas siguientes sea cierta:
- Desea conservar los recursos del servidor para una comunicación activa.
- El cliente puede y debe continuar trabajando hasta que la información esté disponible. Esto puede lograrse simplemente haciendo que el cliente sea multithreaded.
Descripción
En algunos sistemas distribuidos, un servidor debe emplear mucho tiempo
de procesamiento para satisfacer las peticiones de los clientes. En esos
sistemas, probablemente la comunicación síncrona no sea la mejor opción, si el
servidor mantiene contacto con el cliente durante el procesamiento, utilizara
recursos que podrían ser aplicados a otra tareas como la comunicación con otros clientes.
Imagine un sistema en el que el usuario desea
ejecutar una consulta compleja sobre una tabla de una base de datos moderadamente grandes; como por
ejemplo, una tabla con información sobre clientes con más de 10.000 registros. En un sistema cliente/servidor síncrono, el proceso cliente tendría que esperar,
posiblemente durante un largo periodo de tiempo, hasta que el servidor
finalizara. El servidor ejecutaría la petición y gestionaría todos los posibles
pasos para organizar, formatear y empaquetar los datos, hasta que finalmente pudiera devolver los datos del
cliente.
La alternativa es crear un sistema que
permita a un cliente registrarse en el servidor para recibir notificaciones.
Cuando el servidor completa la operación solicita, envía una notificación al
cliente. En el tiempo transcurrido hasta que finaliza la operación, tanto el
cliente como el servidor son libres de utilizar sus recursos para propósitos
más productivos que mantener el enlace de comunicación específico.
El patrón callback proporciona esta
capacidad, permitiendo la comunicación cliente/servidor asíncrona. El proceso
consta de tres pasos principales:
1. Por
ejemplo, el cliente contacta con el servidor y realiza una petición. Normalmente,
el cliente solicita información, como las estadísticas de ventas del año 2001, o una acción como puede ser introducir al usuario en
el viaje organizado. Como el cliente no espera una respuesta inmediata,
proporciona la información necesaria para que el servidor pueda contactar con
el.
- Registro del cliente: el cliente realiza una solicitud, proporcionando información de contacto servidor.
- Procesamiento en el servidor: el servidor procesa la petición del cliente y formatea una respuesta en caso de que sea necesario. Durante ese periodo de tiempo, el cliente puede realizar otras tareas, u el servidor puede establecer comunicación con otros clientes.
- La información solicitada por el cliente. Esta aproximación es utilizada generalmente cuando el cliente nenecita todos los datos o cuando el envió de los datos ocupa relativamente poco ancho de banda.
- Un mensaje informando al cliente de que los datos o parte de los datos están disponibles. Esta opción se utiliza generalmente cuando hay una gran cantidad de información, de forma que el cliente pueda elegir entre recuperar una parte de los datos una vez que estén disponibles, o solo los datos que necesita de entre todos los solicitados.
Como por ejemplo del patrón Callback, considere
un padre y sus tres hijos que salen de compras. El hijo numero 1 quiere un Robot Láser; el hijo numero 2 quiere un ordenador portátil y el hijo
numero 3 el ultimo libro sobre Java publicado por Prentice Hall. Sin embargo:
- Encontrar todas estas cosas puede llevar mucho tiempo, especialmente no se venden en un mismo comercio.
- Los hijos solo son capaces de prestar atención durante cinco minutos y se vuelven locos si tienen que estar de compras durante mucho tiempo.
- El padre solo puede comprar una o dos cosas a la vez si comprara mas, su rendimiento caería.
Afortunadamente, el padre puede dejar a sus
hijos en la sala de juegos recreativos, o dejarlos pelear entre si,
o cualquier otra cosa que se le ocurra. Entonces el padre puede ir a compra uno
de los artículos, volver a dejarlo, ir a comprar el otro y etc.
Se puede utilizar el patrón callback en
múltiples aplicaciones:
- Los agentes de software, ahora muy populares en la Web, pueden utilizar retrollamadas para notificar al cliente que la petición ha sido completada. Por ejemplo, imagine un agente de búsqueda de empleo en Monster.com. Un usuario puede introducir un criterio de búsqueda para el empleo que desea obtener; por ejemplo podría estar buscando uno en el que se pidiera una buena nariz para hacer de catador de cerveza. Posteriormente, el servidor notifica al usuario cuando hay un puesto disponible de catador en una cervecería.
- Las aplicaciones que requieren operaciones costosas de bases de datos, como minería de datos, utilizan frecuentemente el patrón CallBack para incrementar el número de clientes a los que ofrecen un servicio de manera efectiva.
- El patrón CallBack puede ser utilizado en aplicaciones que tienen flujo de trabajo detallado en el servidor. Por ejemplo un servidor utilizado en procesamiento ordenado, a menudo ejecuta una serie de operaciones una vez que un cliente ha realizado el pedido. El servidor suele comprobar inventario, valida el pago y la información de distribución, y se coordina con otros sistemas de información, facturación y entrega de pedidos. El patrón CallBack permite que el servidor notifique a los clientes el estado de pedido después de haber ejecutado los pasos anteriores. Como estas operaciones pueden llevar horas o días, los clientes también prefieren una solución de este estilo.
Implementación:
La figura muestra el diagrama de componentes del patrón CallBack
En la figura del
diagrama se muestra la secuencia del patrón CallBack
Este patrón impone
algunos requerimientos básicos en el cliente y en el servidor:
Cliente: el cliente debe proporcionar una interfaz de retornollamada para el servidor, de forma que este pueda contactar con el cliente cuando haya finalizado la petición.
- Servidor: más allá de la interfaz tradicional del cliente, el servidor necesita alguna forma de indicar a los clientes cuando ha acabado el procesamiento. Además, el servidor debe ser capaz de procesar y, posiblemente, almacenar las peticiones del cliente.
La mayor ventaja del
patrón Callback es la mejora en la eficiencia del sistema especialmente en el rendimiento del servidor. La
mayoría de mejoras se pueden ver en dos áreas distintas:
- Procesamiento en el servidor: el servidor no tiene que mantener los threads de comunicación para servir a los clientes, por lo que puede canalizar esos recursos hacia peticiones de procesamiento de los clientes o en atender a llamadores. Además, el servidor puede realizar el procesamiento cuando lo considere adecuado; no tiene por que ser el mismo instante que recibe la petición.
- Comunicación en el servidor: el servidor no tiene que mantener una conexión abierta mientras el cliente espera los resultados. Esto significa que un servidor puede soportar un mayor número de llamadores con unos recursos de comunicación limitados, como, por ejemplo, ocurriría con los sockets (conectores).
Esa es precisamente
la mayor motivación para utilizar el patrón CallBack en los sistemas. En los casos más extremos, puede significar la
diferencia entre tener un grupo de servidores en paralelo y utilizar una maquina para atender las
peticiones de los clientes.
Otra ventaja es que
el cliente no tiene que esperar el procesamiento completo del servidor y puede
continuar con otras tareas. El cliente puede seguir con lo que estaba haciendo
mientras espera la respuesta del servidor. Cuando el resultado esté disponible,
éste puede ser mostrado de forma inmediata.
Dependiendo de la
implementación del patrón, las peticiones de los clientes pueden ponerse en
cola, permitiendo que el servidor organice y priorice su carga de trabajo. También permite que el servidor notifique a los
clientes cuando suceden cambios mas allá del tiempo de vida habitual de un cliente. Los agentes Web son un buen ejemplo de esto, porque permiten que los
clientes introduzcan una petición en una sesión Web y reciban una notificación
de otra sesión.
Un desafió del patrón
Callback es que necesita que un cliente escuche las retrollamadas del servidor.
Esto a menudo hace que el código del cliente se mas completo, e incrementa la carga de
los sistemas cliente. Un inconveniente adicional surge del hecho de que
Callback desacopla la petición del cliente. Eso suele dificultar la cancelación
o modificación de una petición una vez que ha sido enviada al servidor.
Las variaciones del
patrón Callback se centran generalmente en las estrategias de procesamiento del servidor y en las
aproximaciones sobre las notificaciones a los clientes. Las dos aproximaciones
principales para el procesamiento en el lado del servidor son:
- Procesamiento directo: con esta aproximación, el servidor crea un thread trabajador para satisfacer las peticiones de los clientes. La implementación resulta sencilla, pero esto puede ser complicado de escalar para un gran número de peticiones de servicio.
- Cola de patrones: el servidor mantiene una cola con las peticiones de los clientes y un pool de threads trabajadores. Los threads trabajadores son asignados para ejecutar el procesamiento de los clientes de forma continua.
Solo hay opciones
disponibles para notificaciones de los clientes, dependiendo de los requisitos
de las aplicaciones:
- Retrollamada activa: un cliente utiliza un proceso similar a un servidor para escuchar las comunicaciones entrantes. Eso permite que el cliente reciba directamente la notificación del servidor.
- Sondeo del cliente: necesita que el cliente revise periódicamente el estado de su petición. Cuando la petición, o una parte de ella se haya completado, el cliente solicitara la información correspondiente al servidor.
- Reconocimiento explicito: un servidor puede retrasmitir un mensaje hasta que recibe una confirmación del cliente. Esta aproximación se suele utilizar cuando el procesamiento en el servidor puede durar un tiempo mucho mayor que el tiempo de vida del cliente. Aunque esto no es relevante en TCP porque los sockets no permanecen abiertos a menos que el cliente este presente para hacer su trabajo, si resulta significativo cunado se utilizan tecnologías de comunicación no confiables UDP.
Entre lo patrones
relacionados con Callback se incluye Worker Thread. El patrón worker Thread es
utilizado para ayudar a planificar las peticiones de los clientes.