• Nenhum resultado encontrado

Uma vez explicado em que ´e que consiste a arquitectura, nomeadamente o papel de cada uma das suas interfaces, e sabendo de antem˜ao quais s˜ao os seus objectivos, isto ´e, quais s˜ao os problemas que visa resolver, ´e ent˜ao chegada a altura de mostrar como ´e que o faz. Pretende- se assim explicar que opera¸c˜oes s˜ao executadas nos componentes e elementos da RIC, aquando dos trˆes principais eventos: registo de um componente (registo no elemento da RIC + registo como observador); execu¸c˜ao de um componente; e notifica¸c˜ao de um componente.

Para al´em das opera¸c˜oes concretas, pretende-se tamb´em mostrar que, apesar de ser transparente para os utilizadores, h´a todo um conjunto de opera¸c˜oes que s˜ao executadas pela pr´opria arquitectura, no sentido de garantir que tudo corre conforme o esperado, facilitando assim a utiliza¸c˜ao dos componentes e, como tal, a constru¸c˜ao de compiladores.

7.2.1 Registo dos componentes

A Figura 7.3 representa o diagrama sequencial com as principais opera¸c˜oes que s˜ao executadas aquando do registo de um componente. Na figura est˜ao representados trˆes tipos de intervenientes: o utilizador, que tanto pode ser um componente ou quem efectua a especi- fica¸c˜ao do compilador; o componente que vai ser registado a pedido do utilizador (Comp1) e

que implementa a interface Component ; e um conjunto de elementos da RIC. Elemv ´e o ele-

mento mais acess´ıvel para o utilizador e sobre o qual este requer o registo de Comp1. Elemrc

´

e o elemento utilizado para se efectuar o registo do componente que, como tal, implementa a interface compManager. Elemro ´e o elemento do qual o estado de Comp1 est´a dependente.

´

E, como tal, o elemento onde Comp1dever´a efectuar o registo como observador. Significa isto

que, Comp1implementa a interface Observer e que Elemroimplementa a interface Observed.

Elemrc ´e tamb´em respons´avel por reencaminhar as mensagens provenientes do observador

(Comp1) at´e ao elemento observado (Elemro), como tal, implementa a interface regObserver.

O processo de registo de Comp1 tem in´ıcio na instancia¸c˜ao deste componente (new

Comp1(Elemv)), opera¸c˜ao que ´e despoletada pelo utilizador, indicando o elemento atrav´es

do qual o registo se dever´a efectuar (Elemv). ´E de referir, no entanto, que o registo n˜ao

tem que ser feito directamente no elemento no qual o componente vai ficar efectivamente registado, como ali´as acontece neste exemplo. Esta facilidade de efectuar o registo num elemento diferente daquele onde o componente deve ficar registado, cabe a quem desenvolve os componentes, n˜ao ´e no entanto de implementa¸c˜ao obrigat´oria mas recomend´avel, como

7.2. Funcionamento da arquitectura 133

Figura 7.3: Diagrama sequencial do registo dos componentes.

´e explicado na Sec¸c˜ao 5.2.2. O construtor de Comp1 acede a Elemrc, a partir de Elemv,

para tal, ´e importante que a rela¸c˜ao entre estes dois elementos seja de um para um (ver explica¸c˜ao na Sec¸c˜ao 5.2.2). De seguida, o construtor invoca setElem(Elemrc), que ´e o

m´etodo de Comp1 que efectivamente faz o registo do componente. Para tal utiliza o m´etodo

regComp(this), do elemento sobre o qual se efectua o registo (Elemrc), ficando o processo

conclu´ıdo com a confirma¸c˜ao desta opera¸c˜ao.

No entanto, se o estado de Comp1 depender da RIC, o componente pode e deve re-

querer o registo como observador nos elementos que influenciam o seu estado. Este registo como observador ´e efectuado atrav´es do m´etodo regObs(this, ...), que pode ser invocado di- rectamente do elemento a observar (Elemro), ou a partir de um outro elemento que tenha a

capacidade de reencaminhar a mensagem de registo (e outras) at´e Elemro. Como ali´as acon-

tece no exemplo da Figura7.3, em que o registo ´e efectuado sobre Elemrc, que apesar de n˜ao

ser o destinat´ario da mensagem, tem a fun¸c˜ao de a reencaminhar at´e ao elemento a observar. Para que isto seja poss´ıvel, Elemrc deve implementar a interface regObserver, os elementos

da RIC devem estar devidamente identificados, e as mensagens devem levar a identifica¸c˜ao dos destinat´arios (segundo parˆametro do m´etodo regObs(this, ...)). Conv´em ainda relembrar que, com uma ´unica mensagem, ´e poss´ıvel efectuar o registo em v´arios elementos da RIC e

at´e mesmo em elementos de tipos distintos. A implementa¸c˜ao destes mecanismos de reenca- minhamento, que s˜ao descritos na Sec¸c˜ao5.2.3, n˜ao cabe aos utilizadores da framework, mas cabe a estes requererem a sua inclus˜ao nos elementos da RIC, como se explica na Sec¸c˜ao 7.3. Em rela¸c˜ao ao registo dos componentes, conv´em acrescentar que existe um mecanismo de teste que permite averiguar se um determinado componente est´a, ou n˜ao, registado como observador num dado elemento. Isto porque a implementa¸c˜ao dos componentes pode ser efectuada por terceiros, que por desconhecimento ou por outros motivos, podem n˜ao realizar os registos dos componentes enquanto observadores. Conforme explicado na Sec¸c˜ao 5.2.3, a falta de tais registos pode ser grave dado que s˜ao fundamentais para controlar a consistˆencia dos componentes em rela¸c˜ao `a RIC. A situa¸c˜ao ser´a mesmo grave se os componentes conti- verem informa¸c˜ao relacionada com a RIC; e se funcionarem como componentes de suporte, isto ´e, componentes que visam disponibilizar informa¸c˜ao a outros componentes (principais). Assim, e de forma a evitar uma utiliza¸c˜ao pouco segura dos componentes de suporte, existem dois mecanismos de seguran¸ca. O primeiro, passa pela utiliza¸c˜ao do m´etodo getS- tate(...), o qual por omiss˜ao, isto ´e, se quem desenvolve os componentes nada fizer para con- trolar o estado dos componentes, devolve OUTDATED. Significa isto que a informa¸c˜ao do componente n˜ao est´a consistente com a RIC, mesmo que tal seja verdade. Isto protege contra situa¸c˜oes de negligˆencia ou de desconhecimento, mas n˜ao contra situa¸c˜oes mal intencionadas, dado que quem implementa o componente pode sempre for¸car a vari´avel state a assumir o valor UPDATED. A segunda solu¸c˜ao, que n˜ao ´e 100% eficaz, permite pelo menos identificar se o componente est´a registado como observador nos elementos que eventualmente deveria supervisionar. Solu¸c˜ao essa disponibilizada atrav´es do m´etodo bool certify(Component*,long long) da interface regObserver e Observed. Conv´em no entanto real¸car que esta n˜ao ´e uma solu¸c˜ao 100% eficaz, o componente pode perfeitamente efectuar os registos e no entanto n˜ao se comportar devidamente.

O esquema da Figura7.3´e ainda importante para se perceber o quanto a arquitectura ´

e fundamental para facilitar a utiliza¸c˜ao dos componentes. De notar que para o utilizador apenas ´e vis´ıvel a parte correspondente `a Especifica¸c˜ao, isto ´e, `a zona mais `a esquerda da figura, que inclui apenas a instancia¸c˜ao do componente e quando muito o pedido de certifica¸c˜ao (certif y(c1, ...)). Tudo o resto ´e invis´ıvel. ´E a arquitectura que garante uma

utiliza¸c˜ao simples, eficiente e segura.

Mesmo para quem desenvolve componentes, a solu¸c˜ao continua a ser bastante simples. No que diz respeito ao registo do componente basta implementar o setElem(...), que essenci- almente inclui a invoca¸c˜ao do regComp(...) e dos regObs(...) (ver exemplo da Figura5.26). Toda a parte direita da Figura 7.3, que diz respeito `a RIC, faz parte da DIR. ´E, como tal, transparente a quem utiliza ou implementa os componentes.

7.2.2 Execu¸c˜ao dos componentes

A Figura7.4 representa o diagrama sequencial com as opera¸c˜oes efectuadas aquando da execu¸c˜ao de um componente. A figura cont´em quatro intervenientes: o utilizador do componente; o componente que vai ser executado a pedido do utilizador (Compprinc); um

componente de suporte (Compsup); e o elemento da RIC sobre o qual est´a registado o com-

ponente de suporte (Elemsup).

A execu¸c˜ao do componente ´e requerida pelo utilizador atrav´es de bool execute() ou de bool update(). O utilizador tanto pode ser quem especifica o compilador, um elemento da RIC ou outro componente. Se o componente que vai ser executado, neste caso Compprinc, tiver

dependˆencias funcionais, como acontece neste exemplo, ent˜ao deve requerer a execu¸c˜ao dos componentes de suporte (Compsup), utilizando o m´etodo bool update(char*) (2). O pedido

´

7.2. Funcionamento da arquitectura 135

Figura 7.4: Diagrama sequencial da execu¸c˜ao dos componentes.

(Elemsup), isto ´e, o elemento onde ´e efectuado o registo do componente de suporte. A

execu¸c˜ao deste pode ser efectuada antes, durante ou depois da execu¸c˜ao do componente principal (tudo depende da forma como este ´ultimo est´a implementado). Quando o elemento da RIC recebe a mensagem de update(char*) (2), verifica se j´a possui alguma instˆancia registada do componente requerido. Se assim acontecer efectua um pedido de actualiza¸c˜ao directamente a essa instˆancia, utilizando o m´etodo bool update() (3), devolvendo o valor que resulta da invoca¸c˜ao deste ´ultimo m´etodo. No entanto, se o elemento da RIC n˜ao possuir nenhuma instˆancia do componente requisitado, devolve false. Neste caso, Compprinc

pode criar directamente uma instˆancia de Compsup e regist´a-la em Elemsup, em que os

procedimentos a realizar s˜ao iguais aos do exemplo da Figura 7.3.

A execu¸c˜ao do componente principal (executeprinc(...)) s´o poder´a ser integralmente

efectuada, se for poss´ıvel obter todas as instˆancias dos componentes de suporte devidamente actualizadas. Se assim acontecer, o processo termina devolvendo ao utilizador true. Se por algum motivo algo falhar na execu¸c˜ao do componente, ent˜ao o resultado final ser´a false.

Tamb´em aqui, a Figura 7.4 permite perceber o quanto a arquitectura contribui para tornar a execu¸c˜ao dos componentes simples e eficiente. Para o utilizador apenas ´e relevante a parte esquerda da figura (Especifica¸c˜ao). Basta-lhe invocar o execute() ou o update() do componente, que tudo resto ficar´a a cargo dos componentes e da RIC, desde que tenham sido implementados segundo a arquitectura. Isto garante, que todos os componentes de suporte estar˜ao presentes no momento em que s˜ao necess´arios, que a sua informa¸c˜ao estar´a devidamente actualizada e que ser´a minimizado o n´umero de instˆancias utilizadas e n´umero de vezes que estas s˜ao recomputadas.

Mesmo para quem implementa componentes, apenas ter´a que requerer a actualiza¸c˜ao dos componentes de suporte (update(Compsup)) e quando muito, ou seja, `a falta destes, criar

7.2.3 Notifica¸c˜ao dos componentes

A Figura7.5 representa o diagrama sequencial com as opera¸c˜oes efectuadas aquando da notifica¸c˜ao de um componente. Est˜ao envolvidos trˆes intervenientes: uma instˆancia de um componente (Compobservador), cujo estado depende de um ou mais elementos da RIC, estando

assim registado nestes como observador; um dos elemento da RIC (Elemobservado) observado

por Compobservador; e um segundo componente (Compopt), cuja execu¸c˜ao vai alterar o estado

de Elemobservado.

Figura 7.5: Diagrama sequencial da notifica¸c˜ao dos componentes. ´

E na altura desta altera¸c˜ao do estado de Elemobservado, que se d´a in´ıcio ao processo

de notifica¸c˜ao. A altera¸c˜ao est´a representada atrav´es de um m´etodo fict´ıcio (changeS- tate(...)), que representa um qualquer m´etodo de Elemobservado, capaz de alterar o estado

desse elemento. Quando Elemobservado recebe uma mensagem deste tipo, pode, se assim ti-

ver sido requerido por pelo menos um componente, capturar o estado do elemento observado (Elemobservado), conforme explicado na Sec¸c˜ao 6.3. S´o posteriormente ´e que executa as ope-

ra¸c˜oes que normalmente teria que efectuar. Depois, e conforme explicado na Sec¸c˜ao 6.2.3, Elemobservado pode construir um relat´orio com informa¸c˜ao do m´etodo invocado (represen-

tado no exemplo por changeState(...)), desde que tal tenha sido solicitado por pelo menos um dos componentes observadores (ver Sec¸c˜ao 6.2). Nesse relat´orio, constru´ıdo a partir da classe Report, vai a identifica¸c˜ao da classe e do m´etodo, os valores dos parˆametros e o valor de retorno (se estes existirem). Independentemente de ter sido ou n˜ao requerido o relat´orio, no final Elemobservado invoca sempre bool notify() (2), que vai tratar de notificar todos os

observadores registados em Elemobservado.

No entanto, o tipo de mensagem utilizada para notificar os componentes, depende se foi ou n˜ao requerido relat´orio. Se foi, ´e utilizado o m´etodo bool notify(Observed*,Report*) sen˜ao, ´e utilizado o m´etodo bool notify(Observed*). Em ambos casos vai a identifica¸c˜ao de Elemobservado (Observed* ). Em alternativa, o componente observador pode requerer o relat´o-

rio atrav´es dos m´etodos Report* getReport() ou long long getReport(Observer*, Dict<Observed*, Report*>*).