Descripción del Estilo Arquitectónico
Para desarrollar el presente sistema hemos elegido un estilo mixto. Esto es, con carecterísticas de invocación implícita (tool abstraction) y orientación a objetos (data abstraction). No obstante, la ultilización de uno u otro "subestilo" está limitada de modo que aquellos módulos orientados a objetos no utilizan eventos para relacionarse con otros módulos y, en forma análoga, si un módulo utiliza eventos, la única forma de acceder a sus métodos es a través de invocación implícita (salvo excepcionalmente algunos procedimientos de inicialización cuando el sistema es puesto en funcionamiento, por motivos de eficiencia).
El subestilo de orientación a objetos es mantenido puro en el sentido tradicional. Los módulos diseñados de acuerdo a esto se definen como tipos abstractos de datos, brindando acceso a los mismos por medio los procedimientos que integran sus interfaces.
Para utilizar invocación implícita se han tomado diversas
decisiones con el objetivo de establecer ciertos aspectos que no
estaban del todo claros en la bibliografía consultada o que no
eran adecuados para el sistema que debíamos diseñar.
En primer lugar, los procedimientos de un módulo diseñado bajo
esta metodología utilizan eventos para relacionarse con los
demás módulos bajo el mismo subestilo y llamadas a
procedimiento para acceder a aquellos orientados a objetos.
Llevaremos a cabo la descripción de las decisiones tomadas de acuerdo a los aspectos relevantes destacados por los autores en [SG96] (páginas 176-181). Si bien en el texto se hace referencia a una implementación, esas decisiones terminan de definir el estilo y por ello son descriptas en esta sección.
En cuanto a la declaración de eventos, optamos por una término medio entre declaración estática de eventos (static event declaration) y declaración dinámica de eventos (dynamic event declaration). Es decir, algunos eventos son declarados en tiempo de compilación y otros en tiempo de ejecución. En el último caso los módulos sólo pueden utilizar eventos con una "forma" particular definida en tiempo de compliación. Así es posible tomar provecho de algo de la flexibilidad provista por la declaración dinámica y de la predictibilidad que brindan los controles en tiempo de compilación. Los eventos declarados en tiempo de compilación serán llamados eventos constantes y aquellos que surjan en run-time serán eventos variables.
Para la estructura de los eventos nuestra decisión coincide con la de los autores, adaptada a la anterior observación. Los eventos estarán formados por un nombre de evento y, opcionalmente, una lista de parámetros que el procedimiento anunciante deberá pasar. La forma de un conjunto de eventos variables se define mediante variables que toman valores de cierto tipo y pueden ser usadas para confeccionar el nombre del evento. Los parámetros que acompañan a un evento son determinados cuando el evento es declarado, si éste es constante, ó cuando la forma del evento es declarada en el caso de eventos variables. O sea, sólo el nombre de evento puede ser diferente entre dos eventos variables con la misma forma, las listas de parámetros serán idénticas.
La asociación de procedimientos con
eventos se realiza en tiempo de ejecución. En parte esto se debe
a que el sistema de manipulación de eventos se pensó como un
componente más de software y no como una extensión del lenguaje
de programación subyacente. Esto causa que sea imposible crear
asociaciones evento-procedimiento hasta que el sistema de eventos
sea inicializado. Más allá de esta razón, la naturaleza misma
del sistema en desarrollo, requiere que el binding entre
eventos y procedimientos se lleve a cabo de forma dinámica. Esto
es porque debe ser posible modificar tales relaciones mientras el
sistema está en funcionamiento, lo cual no sería factible de
tener que recompilar con cada cambio. De todos modos, esta
decisión no impide que se representen bindings en tiempo de
compilación. De hecho nuestro sistema efectúa tales
asociaciones como parte del proceso de inicialización.
Al elegir que las relaciones entre eventos y procedimientos sean
dinámicas nos vimos en la necesidad de permitir que, junto con
el nombre del procedimiento a ejecutar ante la ocurrencia de un
evento y el interés en los parámetros que lo acompañan, fuese
posible establecer, en binding-time, valores de
parámetros fijos para la llamada correspondiente. O sea, para
establecer una asociación entre un procedimiento y un evento se
debe dar al manipulador de eventos la siguiente información: el
nombre del evento, el nombre del procedimiento a ejecutar, una
lista de valores a pasar como parámetros en cada llamada del
procedimiento por la ocurrencia de ese evento y una lista en el
orden necesario de los índices de los parámetros que
acompañarán al evento, cuando sea anunciado, que son de
interés para el procedimiento.
Hay que notar que también es posible asociar a un evento una
lista ordenada de procedimientos. Los efectos de esto serán
explicados más adelante.
Los autores denominan a esto último parámetros
seleccionables (selectable parameters)
indicando que es posible elegir cuáles de los parámetros de un
evento deben ser incluídos en la llamada a procedimiento. Como
dijimos, esa selección es posible, en nuestro estilo, mediante
una lista de los índices de los parámetros del evento (éstos
están numerados desde el 1) en el orden en que se deben pasar al
procedimiento.
Para anunciar un evento los procedimientos interesados disponen de dos funciones: announce y announce_r. Ambas funciones esperan el nombre del evento anunciado y la lista de parámetros que lo acompañan y son dirigidas al manipulador de eventos que actuará como se indica en el próximo párrafo. La diferencia entre ambas es que, con la primera, un procedimiento anuncia un evento y continúa su normal ejecución, mientras que la segunda, además de anunciar el evento causa que el anunciante se bloquee esperando un retorno por parte del manipulador de eventos. Nuestro enfoque no coincide con ninguno de los listados por los autores lo cual se debe a que, a diferencia de ellos, no estamos extendiendo un lenguaje de programación sino diseñando un componente de software que lleve a cabo la manipulación de los eventos.
Ante el anuncio de un evento el manipulador de eventos invocará todos los procedimientos que estén asociados a tal evento. Esto es lo que los autores denominan entrega completa (full delivery). Si hay varias entradas para el mismo evento los procedimientos correspondientes serán ejecutados en cualquier orden. Si asociada a un evento se encuentra una lista ordenada de procedimientos, estos serán ejecutados en ese orden y secuencialmente. De esta forma es posible, aún utilizando invocación implícita, diseñar ciertas partes de un sistema confiando en que los procedimientos repondiendo a un evento dado será ejecutados en el orden necesario. (Nota: la imposibilidad de hacer algo así estaba entre las mayores deventajas del estilo según notan los autores en la página 24). A continuación, si el evento había sido anunciado con announce_r, el manipulador de eventos retorna el valor de retorno del procedimiento invocado a aquel que anunció el evento. Es por esto que announce_r funcionará con eventos que tengan asociado sólo un procedimiento y no una lista.
Referencias
[SG96] Shaw, M., Garlan, D., Software Architecture: perspectives on an emerging discipline, Prentice Hall, Upper Saddle River, 1996.