pLinker: Relaciones con Patrones de Diseño

Anuncio
pLinker: Relaciones con Patrones de Diseño
Leonardo Liebener1,2, Marcos Andrés Rossi1,2 and Claudia Marcos1
1
ISISTAN Research Institute, Facultad de Ciencias
Exactas, UNICEN
Paraje Arroyo Seco, B7001BBO Tandil, Argentina
Tel/Fax: + 54–2293–440362/3
http://www.exa.unicen.edu.ar/~isistan/
E-mail: [lliebner, mrossi, cmarcos]@exa.unicen.edu.ar
2
TELPIN Cooperativa Telefónica de Pinamar
Jason 1026, B7167ACT Pinamar, Argentina
Tel: + 54-2254-483000 Fax: + 54-2254-482024
http://www.telpin.com.ar/sistemas
E-mail: [lliebener, mrossi]@telpin.com.ar
Resumen. Los patrones de diseño se han convertido en una técnica importante para el reuso de conocimiento de
software. Cada patrón provee información sobre su diseño, describiendo las clases, métodos y relaciones que
resuelven un problema de diseño en particular. Sin embargo, su documentación no brinda información sobre la
integración de los mismos en un diseño existente, simplemente describen de manera poco detallada los patrones con
los cuales esta relacionado. Este trabajo, presenta una clasificación de las relaciones entre patrones y cómo la
estructura de clases de un diseño existente se ve afectada al incorporar un nuevo patrón. Con el objetivo de asistir al
usuario en la construcción de diseños utilizando patrones y sus relaciones, se implementó pLinker. Dicha herramienta
permite construir diagramas de clase UML e incorporar patrones en ellos.
Palabras claves: Patrones de diseño, Arquitecturas de software, Desarrollo de software OO.
1. Introducción
Los patrones de diseño se han convertido en una técnica popular para el reuso de conocimiento de diseño de
software. La motivación principal de los patrones de diseño la constituye el hecho de encontrar frecuentemente, en
diferentes diseños, problemas similares.
Los patrones de diseño de software son patrones de organización de jerarquías de clases, protocolos y
distribución de responsabilidades entre clases que caracterizan construcciones elementales del diseño orientado a
objetos. Es decir, un patrón es una estructura de clases que aparece repetidamente en diversos diseños orientados a
objetos, la cuál es utilizada para resolver un problema determinado de forma flexible y adaptable dinámicamente. El
propósito de un patrón de diseño es capturar el conocimiento de un diseño de software y hacerlo reusable.
Los patrones han sido agrupados y organizados en catálogos ([BMRS+96], [GHJV95], [Grand98]), cada
uno dando diferentes clasificaciones y descripciones. Algunos catálogos describen patrones de análisis mientras que
otros patrones de diseño, incluyendo también patrones de un dominio particular, o bien, independientes del dominio.
El proceso de construcción de aplicaciones utilizando patrones se reduce a que, cada vez que el diseñador
encuentra un problema, busca en los catálogos un patrón que lo resuelva. Si no existiera tal patrón, el diseñador debe
pensar en una solución. En cambio, si existe un patrón, el diseñador puede aplicarlo en su diseño. En general, esto
significa que los elementos de diseño de la descripción correspondiente al patrón deben ser mapeados e integrados
con los elementos de diseño preexistente. Es decir, se deben identificar las clases, métodos y atributos de la
aplicación que juegan el rol de aquellos prescritos por el patrón.
Lamentablemente, los aspectos que implican integrar un patrón en un diseño parcial existente no son
resueltos por la descripción de los patrones. Cada patrón provee información acerca de su propia implementación de
una manera informal, pero no resuelve uno de los aspectos generales de la arquitectura de software con patrones,
como es la integración de los mismos en diseños preexistentes. Es decir, no existe una guía o descripción que asista
al diseñador a la hora de integrar un patrón a un diseño existente.
Por otro lado, en la mayoría de los catálogos, como parte de la descripción de cada patrón, se mencionan
posibles relaciones de éste con otros patrones de diseño. Estas relaciones muestran que un patrón puede
complementar, de alguna manera, la funcionalidad de otro; o bien puede servir como alternativa del mismo. Así, se
puede notar que si se aplica un determinado patrón quizás se lo pueda utilizar en conjunto con algún otro patrón
relacionado para obtener una solución de diseño más completa. Desafortunadamente, la descripción de dichas
relaciones no se encuentra documentada de la misma manera en la que se documenta un patrón de diseño. Más bien
se trata de una descripción informal o poco detallada. Generalmente sólo se hace referencia al nombre del patrón que
puede ser usado en conjunto con un patrón de diseño dado para mejorar o complementar su funcionalidad, pero no se
describe en que manera se ve afectada la estructura de clases del primero para reflejar esta relación. Entonces, la
descripción no ayuda al diseñador a integrar dos patrones relacionados para lograr una solución de diseño más
completa. Esto hace dificultosa la tarea de construir un diseño de software aprovechando las relaciones entre los
patrones.
De manera de ayudar y asistir al diseñador en la construcción de aplicaciones con patrones de diseño, este
trabajo propone una clasificación de las diferentes relaciones entre patrones. Se han analizado diferentes catálogos de
patrones de diseño y definido relaciones entre ellos. Dichas relaciones han sido documentadas siguiendo un esquema
de documentación similar al que es utilizado para describir patrones de diseño, lo cual facilita la comprensión y la
forma de aplicación de las relaciones entre patrones. Con el objetivo de asistir al usuario en la construcción de
diseños utilizando patrones y sus relaciones de manera simple, se implementó pLinker. Esta herramienta permite
construir diagramas de clase UML e incorporar patrones en ellos. Una vez incorporado un patrón, la herramienta
mostrará las relaciones existentes del patrón aplicado con el resto de los patrones y proveerá acciones a desarrollar, o
puede desarrollar actividades automáticamente, de manera de incorporar el segundo patrón al diseño.
El trabajo esta organizado de la siguiente manera. A continuación se describen las relaciones entre patrones
de diseño definidas y el esquema de documentación utilizado. Sección 3 presenta la herramienta pLinker con sus
características y sus dos modos de trabajo mostrando cada uno de ellos por medio de un ejemplo. Por último, en la
Sección 4 se presentan las conclusiones de este trabajo.
2. Relaciones entre patrones
En la mayoría de los catálogos, los patrones están documentados por medio de una plantilla o ficha
descriptiva. Como parte de esta ficha, cada patrón debe indicar, entre otras cosas, sus relaciones con otros patrones.
Pero, desafortunadamente estas relaciones se encuentran descriptas muy brevemente y además, los diferentes
catálogos de patrones describen distintas relaciones de diferentes maneras. Es decir, cada catálogo o libro de patrones
de diseño, describe a las relaciones entre los patrones usando su propia clasificación idiomática de esas relaciones.
Por ejemplo, las relaciones en [GHJV95] son descriptas de manera informal, usando el lenguaje natural.
Generalmente sólo se hace referencia al nombre del patrón que puede ser usado en conjunto con un patrón de diseño
dado para mejorar o complementar su funcionalidad, pero no se describe en que manera se ve afectada la estructura
de clases del primero para reflejar esta relación. Entonces, la descripción, no ayuda al diseñador a integrar dos
patrones relacionados para lograr una solución de diseño más completa.
Esta inconsistencia, hace que los patrones sean difíciles de utilizar. La relación de un patrón con otro es,
desde la perspectiva de este trabajo, una de las partes más importantes de la descripción de los patrones; y la
inconsistencia de las descripciones hace que sea difícil, para los diseñadores, entender estas relaciones y aprovechar
así las ventajas de los patrones de diseño.
Se han definido y clasificado los tipos de relaciones existentes entre patrones de diseño. Esta categorización
surgió luego del estudio exhaustivo de algunos de los catálogos de patrones más importantes ([GHJV95],
[BMRS+96], [Grand98], [Larman98]), y tiene el propósito de ayudar al diseñador a comprender mejor las relaciones
entre los patrones.
En el mismo, se propone un esquema de documentación similar al que es utilizado para describir patrones
de diseño, lo cuál facilita la comprensión y la forma de aplicación de las relaciones entre patrones.
1.1. Documentación de relaciones
Para describir los distintos tipos de relaciones definidas se utiliza un esquema de documentación en la cuál
la descripción de cada tipo de relación está organizada en diferentes secciones, descriptas a continuación. La plantilla
permite que la estructura de la información sea uniforme, haciendo más simple la comprensión y posible utilización
de los tipos de relaciones encontradas.
Nombre de la relación: el nombre con el cuál se identifica al tipo de relación.
Descripción: en esta sección se muestran los detalles del tipo de relación. Entre estos detalles se puede
encontrar, una descripción del contexto de aplicación de la relación, la descripción de la funcionalidad adicional
proporcionada por el segundo patrón de la relación, la categoría de los patrones involucrados, etc.
Momento de aplicación: esta propiedad establece cuándo puede ser aplicada una relación dada entre dos
patrones. Básicamente, una relación es aplicable antes de utilizar un patrón en el diseño preexistente (pre-aplicable),
implícitamente con la aplicación del patrón (implícito), o bien, después que un patrón ha sido aplicado en el diseño
del usuario (post-aplicable).
Consecuencias de la aplicación: en esta sección se describen las implicancias, las ventajas y desventajas de
la aplicación de la relación.
Acciones a realizar sobre la estructura del patrón original: describen el objetivo que tienen las acciones
a realizar sobre la estructura de clases del patrón original para reflejar su relación con el segundo patrón. Este
apartado no siempre está disponible ya que depende del momento de aplicación de la relación (generalmente
presente en relaciones post-aplicables). Un ejemplo de una acción podría ser: “Agregar un método llamado op1() a
la clase MyClass”.
Actividades a realizar luego de la aplicación de la relación: una actividad es una tarea pendiente que
debe ser llevada a cabo posteriormente a la aplicación de la relación para completar el uso de la misma.
Generalmente, estas actividades son expresadas en lenguaje natural. En la descripción del tipo de relación
generalmente se indica cual es el objetivo, o como surgen las actividades asociadas a la relación y pueden tener
asociada una prioridad que indique su grado de importancia.
Vínculos entre clases: los vínculos entre clases establecen la correspondencia de las clases del segundo
patrón (X) con las del primero (Y), es decir, se indica cual es el rol de cada clase del patrón Y en la estructura de
clases del patrón X.
Ejemplos: para finalizar con la descripción del tipo de relación es importante mostrar ejemplos con
patrones de diseños reales, que ayude a la identificación y comprensión del tipo de relación.
1.2. Tipos de Relaciones
Se han definido seis tipos de relaciones entre patrones de diseño, las cuales son descriptas brevemente a
continuación:
X es alternativa de Y: este tipo de relación se establece entre dos patrones que proponen dos soluciones
mutuamente excluyentes a un problema de diseño. Es decir, no pueden convivir la estructura de ambos
patrones en un diseño para resolver un determinado problema.
X especializa a Y: es una relación unidireccional que se establece entre dos patrones que poseen la misma
estructura, se aplican bajo el mismo contexto y tienen una motivación similar, pero el patrón X incorpora
nueva funcionalidad para soportar requerimientos adicionales o se comporta de manera diferente. Es decir,
en este tipo de relación, X trata con una especialización del problema que trata Y.
X crea a Y: generalmente, el primer patrón que conforma la relación (X) forma parte de la categoría de
“patrones creacionales”, mientras que el patrón Y forma parte de la categoría de “patrones estructurales”. Se
trata de una relación unidireccional en la que el patrón X crea una o más estructuras de clases similares a las
que conforman la solución del patrón Y.
X usa a Y en su solución: al construir la solución para el problema en el que se enfoca el patrón de diseño
X, un subproblema es similar al problema al que apunta el patrón de diseño Y. En consecuencia, el patrón de
diseño X usa al patrón de diseño Y en su solución. Esto implica, que la estructura de clases de Y utiliza una
parte de la estructura de clases de X. Se trata de una relación unidireccional.
X se usa en conjunto con Y: este tipo de relación es la más simple de detectar. Se puede dar entre patrones
de diferentes categorías. Al combinar el patrón X con el patrón Y, se logra una solución de diseño más
completa. Cuando esta relación es usada, la estructura de clases del patrón Y debe ser integrada a la
estructura de clases del patrón X.
X se aplica en cascada: este tipo de relación es establecida entre dos instancias de un mismo patrón de
diseño. Algunos patrones pueden ser aplicados repetidamente para resolver un problema de diseño. Es decir,
la estructura de diseño de un patrón es combinada con la misma estructura repetidamente, para resolver
problemas de diseño más complejos.
Por ejemplo la relación X se usa en conjunto con Y es documentada de la siguiente manera:
Descripción: dos patrones se usan en conjunto para brindar una solución a un problema de diseño que no es
resuelto directamente por ningún otro patrón. En casos simples, generalmente se puede encontrar un patrón de gran
escala que resuelve un problema completo y otro patrón de menor escala que provee la solución a un subproblema.
Por otro lado, en situaciones más complejas, dos patrones se combinan para producir una solución a un problema. El
problema mismo y la manera en la cuál estos patrones son combinados no se encuentran explícitamente capturado en
las descripciones de dichos patrones. Aquí, todo patrón puede ser considerado para usarlo en conjunto con cualquier
otro patrón, para brindar una solución a un problema de gran escala que no se encuentra resuelto por ningún patrón
individual. Cuando esta relación es activada, la estructura de clases del patrón Y debe ser integrada a la estructura de
clases del patrón X.
Consecuencias de la aplicación: las consecuencias de utilizar este tipo de relación en un diseño pueden
expresarse como el resultado de aplicar el primer patrón, junto con el resultado de aplicar el segundo patrón
involucrado en la relación. Las consecuencias de aplicar cada uno de los patrones involucrados en la relación en un
diseño, pueden encontrarse documentadas en la ficha descriptiva del catálogo a cual pertenece cada uno de los
patrones.
Momento de aplicación: el momento de aplicación de esta relación es posterior (post-aplicable) al uso del
patrón X. Al seleccionar el patrón X, cualquier otro patrón puede ser considerado para combinarlo con X, con el fin
de proveer una estructura de solución más completa al problema que se está tratando de resolver.
Acciones a realizar sobre la estructura del patrón original: las acciones que surgen con la aplicación de
este tipo de relación, tendrán como objetivo la integración de la estructura de clases del patrón X con la estructura de
clases del patrón Y.
Actividades a realizar luego de la aplicación de la relación: aplicar esta relación significa que, además de
haber utilizado el patrón X en un diseño dado, también se utilizará una o más veces el patrón Y, por lo que las
actividades que surgirán serán aquellas correspondientes a la utilización de Y.
Vínculos entre clases: aquí es importante definir los vínculos entre la o las clases del patrón X y las clases
del patrón Y, de tal manera que cualquier modificación sobre la estructura de clases de Y se vea reflejada en el patrón
X.
Ejemplo: como ejemplo se pueden considerar los patrones de diseño Composite y al patrón Iterator.
El patrón Composite (Figura 1) permite construir objetos complejos por medio de la composición recursiva
de objetos similares. También permite que estos objetos sean tratados de manera uniforme, si hacer distinciones entre
los objetos simples y los complejos.
AbstractComponent
*
operation( )
ConcreteComponent1
ConcreteComponent2
operation( )
operation( )
...
AbstractComposite
operation( )
add(AbstractComponent)
remove(AbstractComonent)
getChild(int)
...
ConcreteComposite1
ConcreteComposite2
operation( )
add(AbstractComponent)
remove(AbstractComonent)
getChild(int)
operation( )
add(AbstractComponent)
remove(AbstractComonent)
getChild(int)
Figura 1: Patrón de diseño Composite
El patrón Iterator (Figura 2) define una interfaz que declara métodos para el acceso secuencial de los
objetos de una colección. Una clase que acceda a una colección a través de una interfaz, permanecerá independiente
de la clase que implementa dicha interfaz.
«interface»
CollectionIF
Creates
iterator( ) : IteratorIF( )
...
Collection
«interface»
IteratorIF
hasNextItem( ) : boolean
getNextItem( ) : InventoryItem
Fetches-objects-from
Iterator
Figura 2: Patrón de diseño Iterator
Estos dos patrones pueden ser combinados para resolver el problema de recorrer estructuras de objetos
complejos sin conocer la estructura interna de los mismos. Es decir, con la aplicación del patrón Iterator se logra
independizar el recorrido del Composite de la organización interna de los objetos.
En la Figura 3 se muestra la estructura de estos dos patrones combinados. Se puede ver que la clase
AbstractComposite del patrón Composite, en la combinación ha asumido el rol de la clase Collection del patrón
Iterator.
Por lo tanto, la clase AbstractComposite deberá implementar el método iterator() que crea un iterador para
recorrer la estructura interna de los objetos compuestos del patrón Composite. En realidad, por tratarse de una clase
abstracta, las subclases de AbstractComposite tendrán la responsabilidad de redefinir este método.
Complementariamente al estudio realizado para la identificación de relaciones entre patrones de diseño se
ha aplicado el mismo concepto a patrones de diferentes niveles de abstracción. Existen patrones de mayor nivel de
abstracción, conocidos comúnmente como patrones arquitectónicos, y de menor nivel de abstracción (patrones de
diseño). De esta manera es posible especificar relaciones que permitan identificar y describir los patrones de diseño
que se utilizan para el diseño detallado de cada uno de los componentes de la arquitectura de software. Por ejemplo,
el patrón arquitectónico Model View Controller usa los patrones de diseño Observer, Strategy y Composite: el
patrón Observer conecta la vista (View) al modelo (Model), el patrón Strategy permite al controlador (Controller)
manejar los eventos que ocurren sobre la vista, y el patrón Composite provee una jerarquía de vistas.
AbstractComponent
<<Interface>>
CollectionIF
operation()
iterator()
ConcreteComponent
<<Interface>>
IteratorIF
creates
hasNextItem() : boolean
getNextItem() : InvetoryItem
AbstractComposite
operation()
add(AbstractComponent)
re mo ve(AbstractComponen t)
getChild (i nt)
fetch e s objec ts f rom
Iterator
Figura 3: Resultado de combinar las estructuras de clases de los patrones Composite e Iterator
Además, es posible determinar en que parte del patrón arquitectónico, o sea, en que componente
arquitectónico es usado un determinado patrón de diseño. Siguiendo con el ejemplo, el patrón de diseño Composite
es usado en el componente arquitectónico View. Esta información resulta útil para construir aplicaciones utilizando
patrones de software de diferentes niveles de abstracción.
3. pLinker
Se ha desarrollado una herramienta denominada pLinker la cual pretende que el usuario aproveche las
ventajas del uso de patrones de diseño y, principalmente de las relaciones entre los mismos sin tener un conocimiento
avanzado sobre el tema.
pLinker consiste de un editor gráfico de clases UML que facilita la utilización y administración de patrones
de diseño, permitiendo mantener y actualizar un catálogo de patrones de diseño y las relaciones entre los mismos.
Por otro lado, provee mecanismos que simplifican la incorporación de patrones a diseños preexistentes,
aprovechando además, las relaciones entre dichos patrones. pLinker posee dos modos de trabajo:
El primer modo esta orientado a la construcción de diseños con patrones, permite modelar visualmente
clases, interfaces y relaciones entre las mismas (herencia, uso, e implementación). Pero su principal característica es
la posibilidad de incorporación de forma sencilla de patrones de diseño a un modelo de clases existente. Además,
permite distinguir cuales fueron los patrones utilizados y ofrece opciones que ayudan a mejorar el diseño en
desarrollo incorporando nuevos patrones en forma automática, valiéndose para ello de las relaciones existentes entre
los patrones involucrados.
El segundo modo esta destinado a mantener y actualizar el catálogo de patrones de diseño y sus relaciones.
La incorporación de un nuevo patrón puede hacerse tomando como referencia la plantilla de documentación del
mismo, disponible en cualquiera de los catálogos de patrones. Además, de incorporar la descripción del nuevo patrón
se deben describir las relaciones del mismo con los patrones ya existentes en la herramienta y las acciones a
desarrollar en cada uno de los casos.
Otra característica que posee pLinker es que permite crear diseños partiendo de arquitecturas de software,
organizando de esta manera las clases del modelo del usuario en componentes arquitectónicos. Esto brinda una ayuda
adicional a la hora de utilizar un patrón de diseño, ya que por cada componente arquitectónico, pLinker propone los
patrones de diseño que se usan más comúnmente en él.
4.1. Configuración de pLinker
Por cada patrón de diseño, pLinker mantiene tres tipos de información: la descripción general, la estructura
de clases que conforma el patrón, y las actividades a realizar para complementar su uso.
En la descripción genera,l se deben especificar el nombre del patrón, la intención, la motivación y otros
datos relevantes que ayuden al usuario a optar o no por un determinado patrón de diseño. La estructura de clases se
refiere a las clases y relaciones entre ellas involucradas para resolver un problema de diseño particular Finalmente,
las actividades representan un conjunto de tareas que debe realizar el usuario con el fin de completar la inserción de
un patrón en su diseño. Por ejemplo, una actividad que surge generalmente es la de renombrar una clase del patrón
para que su nombre represente exactamente lo que modela. Una actividad tiene un nombre (como podría ser:
“Renombrar clase C”), una descripción que muestra los detalles y una prioridad que indica la importancia de la
misma.
Para incorporar la información correspondiente a esta relación, el usuario debe indicar cuales son los
patrones involucrados, el tipo de relación y la descripción de la relación. También deben establecerse los vínculos
entre las clases que permiten mantener la consistencia entre las estructuras de diseño de los patrones involucrados en
la relación. Al establecer estos vínculos, pLinker creará automáticamente las acciones necesarias que permitan
incorporar el segundo patrón de la relación en la estructura de clases del primero.
Adicionalmente, pLinker permite almacenar información acerca de arquitecturas de software y sus
componentes. Un componente arquitectónico puede estar diseñado con un conjunto de patrones de diseño. Por cada
uno de estos componentes, pLinker permite establecer cuales son los patrones de diseño más frecuentemente
utilizados en su diseño.
La Figura 4 muestra cómo establecer una relación entre dos patrones en pLinker. En la misma se puede
observar la configuración de la relación entre los patrones Composite y Decorador. A la izquierda de la pantalla de
configuración se muestra las clases del patrón Composite y a la derecha las correspondientes al patrón Decorador.
En el panel inferior se puede observar los vínculos establecidos entre las clases de ambos patrones para establecer la
relación entre los mismos.
4.1 Construcción de aplicaciones
A continuación se muestran las características principales de pLinker cuando es utilizado para la
construcción de aplicaciones. Para ello se utilizará como ejemplo la construcción de un diseño que soporte la
creación de diferentes juegos de tablero. Entre los juegos que se tienen en cuenta para el diseño se pueden mencionar
el ajedrez, las damas, cuatro en línea, ta-te-ti, etc., por lo que se lo podría utilizar para crear juegos en los que
participen muchos jugadores, o bien que existan distintos tipos de piezas, además de muchas otras características que
incluyen los juegos mencionados.
En cuanto a los jugadores que participan en el juego, el diseño no hace distinción entre lo que puede ser un
jugador humano y otro que esté controlado por un algoritmo. La idea básica es que los jugadores involucrados,
generen comandos y los apliquen al juego. El juego se encargará de verificar que dichas acciones sean válidas,
actualizará su estado de acuerdo a ellos, y quedará a la espera de nuevas acciones. Una acción será, por ejemplo para
un juego de ajedrez, “mover el alfil de tal lugar a tal otro”, o bien si se piensa en un juego como el reversi, “poner
una ficha roja en tal celda”.
Figura 4: Configuración de pLinker: Relaciones entre patrones
4.1.1. Creación de un proyecto pLinker
Lo primero que se debe hacer antes de comenzar a incorporar clases y relaciones al diseño, es crear un
proyecto. El proyecto será la unidad de trabajo de pLinker, y es el encargado de contener tanto el diseño de clases del
usuario como las instancias de los patrones utilizados. Así mismo, organiza el diseño en componentes
arquitectónicos. pLinker permite trabajar con múltiples proyectos a la vez.
El primer paso para crear un proyecto es indicar la arquitectura de software a utilizar, para el caso de la
aplicación ejemplo, se utilizará arquitectura de software Model-View-Controller (MVC), por lo que el diseño se verá
estructurado en tres componentes arquitectónicos. En caso de que no se utilice una arquitectura de software, el diseño
será organizado en un único componente. Continuando con la construcción de la aplicación se procede a la creación
y organización de las clases iniciales de cada uno de los componentes de la arquitectura MVC. Por ejemplo, el
componente Model inicialmente tendrá las siguientes clases (Figura 5):
Player: Contiene información referente al jugador (por ejemplo su nombre). Además, tiene conocimiento de
las fichas que tiene para jugar y que no se encuentran sobre el tablero. Esto se puede ver en el juego del scrabbel, en
el cual los jugadores disponen de letras (fichas) con las que deben formar palabras sobre el tablero.
Piece: Existen muchos juegos de tablero en los que se utilizan diferentes piezas o fichas. Esta clase
representa a tales piezas. Una pieza tiene el conocimiento de cuales son las celdas con las que se puede operar, a
partir de una celda origen, con una determinada pieza. Esto se ve en el juego de ajedrez, en donde se sabe que la
pieza alfil solo se puede mover a celdas diagonales contiguas.
Board: Representa al tablero de juego y provee métodos para acceder a las distintas celdas, además
completa el chequeo de si el movimiento de una pieza es válido. Siguiendo con el ejemplo de ajedrez, se puede
verificar a nivel pieza que un alfil se mueva solo en diagonal, pero a este nivel se desconoce si en la celda destino se
encuentra alguna otra pieza del mismo color, por ejemplo. Esta responsabilidad es del tablero.
Cell: El tablero esta compuesto por celdas. La celda brinda mecanismos para poner y sacar piezas de ella.
Game: Contiene la lógica y reglas del juego y tiene conocimiento del estado del mismo, los jugadores,
maneja los turnos, fichas sobre el tablero, etc.
Figura 5: Clases que diseñan (inicialmente) el componente arquitectónico Model
4.1.2. Creación de instancias de patrones de diseño
Es posible que el usuario desee utilizar en su diseño varias veces un determinado patrón dado (por ejemplo,
el patrón Singleton). Es por ello que surge el concepto de instancia de patrón de diseño. Una instancia puede verse
como una “copia” de un patrón de diseño dado. Incluye además, información para mantener vínculos entre las clases
del usuario y las clases que conforman la estructura del patrón. Estos vínculos representan los roles. Un rol indica
que clase del modelo del usuario juega el rol de una clase que se encuentra dentro de la estructura de la instancia de
un patrón. Entonces, cualquier modificación que ocurra sobre una clase de la instancia de un patrón, afectará
directamente a una clase del usuario.
Para incorporar un patrón de diseño (de los que se encuentran en el catálogo de pLinker) a la estructura de
clases preexistente, primero se debe establecer el nombre de la instancia. Luego se debe determinar cual será el
patrón a instanciar. Los patrones disponibles dependerán del componente arquitectónico seleccionado ya que solo se
mostrarán aquellos que son factibles de utilizar. Sin embargo, el usuario puede no tener en cuenta el componente
arquitectónico y utilizar cualquier patrón de diseño incluído en el catálogo. Una vez seleccionado el patrón de diseño
a instanciar, la herramienta propone alternativas del mismo. Tales alternativas estarán dadas por las relaciones
existentes entre patrones. Solo aparecerán como alternativas aquellas relaciones entre patrones cuyo tipo implique
que deben usadas antes de la instanciación de un patrón.
Continuando con el componente arquitectónico View, la Figura 6.a muestra las clases que diseñan
inicialmente dicho componente. Cada una de estas clases es encargada de representar gráficamente los diferentes
elementos de un juego de tablero. Se puede ver como la clase GameView tiene la responsabilidad de manejar la vista
correspondiente al tablero (BoardView) y las vistas de los jugadores (PlayerView). Para reducir esta complejidad, y
manejar esta jerarquía de vistas de manera homogénea, es posible utilizar el patrón de diseño Composite [GHJV95].
Al intentar instanciar un patrón para el diseño del componente View, pLinker ofrecerá el Composite puesto
que dicho patrón es frecuentemente usado en este componente arquitectónico. Entre las actividades que surgirán
cuando se cree una instancia de este patrón estarán las de renombrar las clases y los métodos (por ejemplo,
AbstractComponent por AbstractView y operation por paint).
En cuanto a los roles, la clases PieceView y PlayerView jugarán el rol de ConcreteComponents, ya que
pueden verse como hojas del árbol de vistas. De manera similar, las clases BoardView, GameView y CellView
jugarán el rol de AbstractComposite. En la Figura 6.b se la instanciación de el patrón Composite.
4.1.3. Activación de las relaciones entre patrones
Una vez instanciado un patrón, pLinker propone al usuario, los patrones de diseño que pueden ser utilizados
en conjunto con el primero. Solo aparecerán aquellas relaciones entre patrones cuyo tipo implique que deben usadas
después de la instanciación de un patrón dado.
6.a
6.b
Figura 6.a: Clases que diseñan el componente View 6.b: Uso del patrón Composite en el diseño del componente View
Para el diseño del juego, se activará la relación entre los patrones de diseño Composite y Decorator (Figura
7). Esto permitirá que las diferentes vistas (que ahora forman parte del Composite) se dibujen de diferente manera,
dependiendo posiblemente, del estado del objeto que representan. Por ejemplo, es posible que cuando el usuario
seleccione una celda del tablero, la misma se dibuje con un recuadro.
Figura 7: Activación de la relación entre los patrones Composite y Decorator
Entonces, pLinker se encarga de actualizar el modelo de clases del usuario para reflejar la activación de
dicha relación. La activación de una relación implica que se ha utilizado un nuevo patrón (o instancia del mismo) en
el diseño del usuario. Entonces, la herramienta crea automáticamente una instancia de dicho patrón.
De esta manera, a medida que se van aplicando patrones en el diseño, la herramienta va asistiendo al
diseñador para la incorporación de nuevos patrones de manera de completar el diseño de la aplicación. Una vez que
las posibles relaciones entre patrones han sido mostradas por la herramienta y utilizada esa información por el
diseñador, este último deberá analizar el diseño resultante en caso de tener que incorporar nuevas clases o patrones
no surgidos de las relaciones.
4. Conclusiones
En este trabajo se realizó un estudio y clasificación de los tipos de relaciones existentes entre patrones de
diseño. Se identificaron puntos en común que permitieron clasificar y documentar más formalmente tales tipos de
relaciones. Como resultado de este estudio surgió un esquema de documentación similar al que es utilizado para
describir patrones de diseño, lo que facilita la comprensión y la forma de aplicación de las relaciones entre patrones.
Al descubrirse una relación entre dos patrones de diseño dados, no solo es posible clasificarla, sino que también se la
puede documentar de manera que permita utilizarla posteriormente en una herramienta de desarrollo que contemple
el uso patrones de diseño y relaciones entre los mismos.
Con el objetivo de asistir al usuario en la construcción de diseños utilizando patrones y sus relaciones de
manera simple, se implementó pLinker, una herramienta gráfica que permite modelar diagramas de clase UML e
incorporar patrones en ellos y aprovechar las relaciones existentes entre los mismos. pLinker provee mecanismos que
facilitan la incorporación de patrones a un diseño preexistente de manera simple, permitiendo establecer vínculos
entre las clases del patrón y las clases del usuario para mantener la consistencia entre las instancias de patrones de
diseño. Al insertar un patrón de diseño en un diagrama de clases dado, pLinker ofrece opciones que implícitamente
llevan a “activar” relaciones entre el patrón original y aquellos con los cuales esté relacionado. Al activar una
relación entre patrones, pLinker se encarga de mantener consistente el modelo del usuario, tomando para ello la
información propia de la relación.
Por otro lado, pLinker permite trabajar con arquitecturas de software y sus respectivos componentes
arquitectónicos, dando la posibilidad de indicar cuales son los patrones de diseño frecuentemente usados en un
determinado componente arquitectónico, mejorando así la posible elección y uso de un determinado patrón, dentro
de un diseño dado. La configuración de pLinker está fuertemente relacionada con la documentación de relaciones
entre patrones propuesta. Es por ello que es posible tomar dicha información e incorporarla sin mayores problemas a
la herramienta.
5. Bibliografía
[AISJ+77]
[BASS97]
[BMRS+96]
[Garlan94]
[GHJV95]
[Grand98]
[JHotDraw]
[Larman98]
[Lorenz97]
[Meijers96]
[Noble98]
[Rumbaugh96]
[Yeates97]
[Zimm94]
C. Alexander, S. Ishikawa, M. Silverstein, M. Jacobson, I. Fiksdahl-King, and S. Angel. A
Pattern Language - Towns-Buildings-Construction. Oxford University Press, 1977.
Len Bass, Paul Clements and Rick Kazman, Software Architecture in Practice. AddisonWesley, 1997.
Frank Buschmann, Regine Meunier, Hans Rohmrt, Peter Sommerlad, and Michael Stal,
Pattern-Oriented Software Architecture - A System of Patterns. Wiley and Sons Ltd, 1996.
David Garland and Mary Shaw, An introduction to Software Architecture. CMU-CS-94166, School of Computer Science, Carnegie Mellon University, Pittsburgh, PA 15213-3890,
1994.
Erich Gamma, Richard Helm, Raph Johnson, and John Vlissides, Design Patterns –
Elements of Reusable Object-Oriented Software. Addison-Wesley, Reading, MA, 1995.
Mark Grand, Patterns in Java: a catalog of reusable design patterns illustrated with UML.
Wiley and Sons, Inc, 1998.
Erich Gamma and Thomas Eggenschwiler, A Java GUI framework for technical and
structured Graphics. http://www.jhotdraw.org.
Claig Larman, Applying UML and patterns. Upper Saddle River, N.J. Prentice Hall PTR,
1998.
D.H. Lorenz, Tiling Design Patterns – a case studio. ECCOP Proceeding, 1997.
Marco Meijers, Tool Support for Object-Oriented Design Patterns, Master’s Thesis. Utrecht
University, CS Dept, INF-SCR-96-28, August 1996.
James Noble, Classifying Relationships Between Object-Oriented Design Patterns.
Microsoft Research Institute, Macquarie University, Sydney, Australia, 1998.
James Rumbaugh, Michael Blaha, William Premerlani, Frederick Eddy, William Lorensen,
Modelado y Diseño Orientados a Objetos. Metodología OMT. Prentice Hall, 1996.
S.A. Yeates, Design a garbage collector using design patterns. TOOLS Pacific 25, 1997.
Walter Zimmer, Relationships between design patterns in Pattern Languages of Program
Design, Addison-Wesley, 1994.
Descargar