Instanciando uma Linguagem Abstrata de Pontos de
Corte para Middleware Orientado a Aspectos
José Diego Saraiva da Silva, Thais Batista, Flávia Delicato, Paulo F. Pires Departamento de Informática – Universidade Federal do Rio Grande do Norte (UFRN) Campus Universitário – Lagoa Nova – 59.072-970 – Natal – RN jdiego@ppgsc.ufrn.br, thais@ufrnet.br, {flavia.delicato,paulo.pires}@dimap.ufrn.brAbstract. This paper presents the instantiation of an abstract pointcut definition language (APL) for aspect oriented middlewares in a concrete language: Re-AspectLua. The choice of Re-AspectLua as concrete language was motivated by its support to aspect reuse and heterogeneous composition between aspects and base elements. Such features are essential in the aspect oriented middleware context. In order to meet the requirements specified by the APL definition, our work includes the following extensions to RE-AspectLua: (i) execution joinpoints; (ii) a set of logical operators to combine pointcut expressions; (iii) support to context properties associated to function calls. Besides presenting the APL instantiation, this paper illustrates the use of the proposed extended version of RE-AspectLua in a case study that defines how distribution protocols are represented as aspects and woven with other basic services provided by an aspect oriented middleware.
Resumo. Este artigo apresenta a instanciação de uma linguagem abstrata de definição de pontos de corte (APL) para middlewares orientados a aspectos em uma linguagem concreta: Re-AspectLua. A escolha de Re-AspectLua justifica-se pelo seu suporte a reusabilidade de aspectos e possibilidade de composição heterogênea entre aspectos e elementos base. Essas características são essenciais no contexto de middleware OA. Para atender aos requisitos definidas pela APL, nós definimos as seguintes extensões a RE-AspectLua: (i) inclusão do ponto de junção execution; (ii) inclusão de um conjunto de operadores lógicos para combinar expressões de pontos de corte; (iii) inclusão de suporte a propriedades de contexto associadas a invocações de funções. Além disso, o artigo ilustra o uso da versão estendida de RE-AspectLua em um estudo de caso que define como protocolos de distribuição são representados através de um aspecto e compostos com um middleware OA.
1. Introdução
A programação orientada a aspectos (POA) [Kiczales et al. 1997] é um paradigma que permite a separação dos conceitos transversais através da introdução de uma nova abstração que os encapsula: o aspecto. A POA tem sido utilizada como mecanismo de modularização de interesses transversais presentes em diferentes contextos de desenvolvimento de software. Um contexto de emprego da POA recentemente explorado são as plataformas de middleware [H.-A. Jacobsen 2001] [Cacho et al. 2006]. Nesse contexto, o uso da POA possibilita que o middleware seja composto por um núcleo contendo somente os serviços considerados essenciais e os demais serviços providos pelo middleware sejam inseridos de forma incremental e dinâmica, permitindo assim, que o mesmo seja personalizável de acordo com os requisitos e contexto de execução das aplicações. Nessa abordagem, os serviços não essenciais são representados como aspectos, tornando o middleware mais flexível e leve. Essas características satisfazem os requisitos dos
middleware de nova geração [Coulson et al. 2002] que devem possuir capacidade de adaptação estática e dinâmica. Além disso, a abordagem baseada em um núcleo mínimo de serviços permite que o middleware seja adequado às necessidades de ambientes de recursos limitados, como é o caso de aplicações móveis.
Há diversas propostas de middleware Orientados a Aspectos (OA) [H.-A. Jacobsen 2001] [Cacho et al. 2006]. No entanto, as arquiteturas existentes de middleware OA, em geral, têm sido especificadas de maneira ad-hoc, não seguindo um vocabulário conceitual comum que permita, por exemplo, comparar as várias tecnologias de middleware OA. Para endereçar tal problema, em [Loughran et al. 2005] é apresentada uma proposta de arquitetura de referência para a construção de plataformas de middleware OA que visa formular a base para o desenvolvimento de kits de ferramentas para construção desses middlewares e identificar e especificar os principais conceitos que devem ser considerados no seu desenvolvimento. O uso de um modelo de referência facilita o entendimento, a comparação entre as plataformas de middleware e permite agrupar problemas e soluções recorrentes na produção destes middlewares. A arquitetura de referência estabelece três níveis arquiteturais. O nível 1 define conceitos gerais, princípios e padrões com o intuito de fornecer uma lista de conceitos cuja finalidade é criar abstrações que facilitem o desenvolvimento de plataformas de middlewares OA. Os seguintes elementos são definidos nesse nível: (i) componentes, unidades de decomposição funcional do sistema, (ii) um microkernel, núcleo mínimo do sistema que contém as funcionalidades principais, (iii) uma linguagem abstrata de definição de pontos de corte, denominada APL (Abstract Pointcut Language) e (iv) padrões de binding que coordenam as interações entre os componentes. Os padrões de binding são divididos em duas categorias: binding e AO-binding. O primeiro representa associações normais entre componentes, enquanto que o segundo representa associações entre componentes que representam conceitos transversais e componentes ‘regulares’. O nível 2 mapeia os conceitos transversais do middleware para as abstrações do nível 1. Ou seja, nesse nível os conceitos transversais são descritos através dos elementos definidos no nível 1. Por fim, o nível 3 mapeia o nível 2 para uma plataforma de middleware específica. Dessa maneira, o nível 3 descreve uma implementação dos níveis 1 e 2. Um dos pontos principais na construção de middlewares OA seguindo a arquitetura de referência consiste na instanciação da APL para uma linguagem concreta de definição de pontos de corte. Nesse contexto, no presente trabalho propomos o uso da linguagem RE-AspectLua [Batista and Vieira 2007] com esse intuito. RE-AspectLua é uma linguagem orientada a aspectos baseada em Lua, cujo foco está no dinamismo, na reutilização de aspectos e no suporte a composição heterogênea. RE-AspectLua foi projetada levando em conta dois requisitos fundamentais: promover o reúso de aspectos e minimizar o indesejável acoplamento entre os aspectos e os elementos do código base da aplicação. Para tanto, a definição dos aspectos é realizada em duas etapas. Primeiramente, os aspectos são definidos por um conjunto de interfaces que não fazem referências a nenhum ponto concreto do código base. Em uma próxima etapa, os pontos de junção abstratos definidos na primeira etapa são instanciados em pontos de junção concretos através de uma linguagem de conexão, a linguagem Lua. Ou seja, é nesse momento que ocorre a definição da ligação entre o código base e o do aspecto. Sendo assim, diferentes concretizações de um mesmo aspecto abstrato podem ocorrer, de acordo com os diferentes requisitos e contextos de execução das aplicações. Desta forma é possível instanciar um mesmo middleware sob diferentes configurações. Essa característica faz com que RE-AspectLua seja uma linguagem adequada para prover capacidades adaptativas aos middlewares OA.
O restante deste artigo está estruturado da forma a seguir. A seção 2 apresenta os conceitos básicos necessários para o entendimento do trabalho. A seção 3 apresenta o mapeamento da APL para RE-AspectLua. A seção 4 apresenta um estudo de caso. A seção 5 discute trabalhos relacionados e a seção 6 apresenta as considerações finais.
2. Conceitos Básicos
A seção 2.1 apresenta a APL definida na arquitetura de referência. A seção 2.2 apresenta os principais conceitos de AspectLua e RE-AspectLua.
2.1 A Linguagem Abstrata de Ponto de Corte
A APL definida na arquitetura de referência consiste em uma notação cuja finalidade é estabelecer uma maneira de expressar pontos de junção de forma independente de plataformas de orientação a aspectos específicas. Em outras palavras, a APL é uma linguagem abstrata e genérica que pode ser utilizada como um framework para a criação de linguagens de definição de pontos de junção concretas. Além de ser genérica, a APL é voltada para aplicações baseadas em componentes, descritos em termos de interfaces Provided e Required. O modelo de pontos de junção da APL é simples, direcionado para uso em middlewares, e define apenas dois tipos de pontos de junção: call e execution. A diferença entre eles está no local no qual o ponto de junção é interceptado. O ponto de junção call ocorre em uma interface do tipo Required de um componente. O ponto de junção execution ocorre em uma interface do tipo Provided.
Um ponto de corte é descrito através de uma fórmula composta por quatro sub-expressões de lógica de primeira ordem e determinado pela tupla <CP, C, I, O> onde: CP é um conjunto de containers sobre o qual a aplicação é instalada, C é um conjunto de componentes, I é um conjunto de interfaces e O é um conjunto de operações. Cada sub-expressão da APL pode ter quantificadores e variáveis quantificadas, lista de propriedades, seletores de pontos de junção, operadores lógicos e operadores da teoria dos conjuntos (pertence/não pertence) que atuam sobre containers, componentes, interfaces e operações. Para cada um desses elementos, a APL associa dois tipos de propriedades: estáticas e dinâmicas. As propriedades estáticas representam o conjunto de propriedades mínimas que devem existir no middleware, por exemplo, a arquitetura de referência define que todo componente tem uma propriedade nome, podendo essa propriedade ser referenciada através de c.name como mostra a Figura 2. Por outro lado, as propriedades dinâmicas denotam um conjunto de propriedades que podem estar presentes ou não no middleware. Essas propriedades estendem o poder de expressividade da APL. Uma propriedade dinâmica é um par < chave, valor > associada a um elemento do domínio. Por exemplo, a Figura 1 mostra a sintaxe para anexar a propriedade crypt com o valor DES ao componente arquitetural S.
)
"
"
,
"
("
.
dynprop
crypt
DES
S
Figura 1: Criação de uma propriedade dinâmica
A Figura 2 exibe um exemplo de uma expressão de ponto de corte que seleciona os pontos de junção do tipo call todos para os métodos que começam com a palavra methodA dos componente ComponentA ou ComponentB. ) ( *" " . ) " " . " " . ( . , . , , o call methodA signature o ComponentB name c ComponentA name c operations c o interfaces c i C c CP cp ∧ � ∧ � ∨ � ∈ ∀ ∈ ∀ ∈ ∀ ∈ ∀ Figura 2: Exemplo de uma expressão de ponto de corte em APL
Mecanismos de passagem de informações contextuais de um ponto de junção para um advice também são contemplados pela APL. Ela define que a passagem de informações contextuais ocorra através das propriedades de contexto, tais propriedades são anexadas às invocações de funções.
2.2 RE-AspectLua
AspectLua [Cacho et al 2005] é uma linguagem de POA baseada na linguagem Lua [Ierusalimsky et al 1996], que oferece suporte à POA dinâmica. Lua é uma linguagem dinamicamente tipada que explora reflexão computacional. Por sua vez, AspectLua implementa a orientação a aspectos através dos mecanismos reflexivos de Lua. A vantagem dessa abordagem é o fato de que o interpretador Lua padrão não precisa ser alterado. AspectLua oferece o seguinte conjunto de funcionalidades: (i) a inserção e remoção de aspectos reutilizáveis em tempo execução (ii) a definição da ordem de precedência entre os aspectos, (iii) wildcards e (iv) anticipated join points. O anticipated join point é um mecanismo que permite a interceptação de elementos ainda não declarados no programa. Assim, possibilitam a carga dinâmica de bibliotecas e métodos não definidos pela aplicação.
Os aspectos em AspectLua são definidos em termos de pontos de junção (join points) e advices. Os tipos de pontos de junção do AspectLua são: (i) call para chamadas de métodos; (ii) callone para aspectos que atuam apenas uma única vez sobre as invocações de métodos; (iii) introductions para permitir a adição de funções em objetos e (iv) get e set para capturar leituras e escritas em variáveis.
A Figura 3 exibe a sintaxe de AspectLua. Na primeira linha, tem-se a criação de um aspecto em AspectLua via o método new() da classe Aspect. O método aspect é responsável por definir o aspecto em questão. A linha 2 exibe tal método, que recebe como parâmetros as seguintes tabelas1: nome do aspecto, uma expressão de pontos de corte e o advice. A expressão de pontos de corte (linhas 3-5), é formado por um nome, um designador e pela lista de elementos que devem ser interceptados. O designador, expresso pelo campo designator, seleciona o tipo de ponto de corte (call, callone, execution, introductions, get ou set). A lista de elementos a serem interceptados é definida pelo campo list. Esse campo contém expressões de pontos de corte, ou seja, ele define um conjunto de variáveis e funções a serem interceptados.
O advice é definido pelo seu momento de atuação e pela ação a ser tomada quando o ponto de corte for atingido. O campo type define o momento (before, after ou around) no qual o aspecto atua em um ponto de junção. O campo action aponta para a ação a ser tomada. Na Figura 3, a ação a ser tomada é o método myadvice (linhas 8-10).
Entretanto, apesar de a POA endereçar a modularização dos interesses transversais, os aspectos definidos pela abordagem tradicional, como a seguida por AspectLua, não são reutilizáveis. Isso acontece porque: (i) o código do aspecto é fortemente associado com o elemento no qual ele atua; (ii) os aspectos estão acoplados a detalhes do código base que o programador é livre para alterar e (iii) o processo de composição dos aspectos com o código base é definido no código do aspecto, impedindo assim que o aspecto seja composto com diferentes
1 Vetores associativos que formam a estrutura de dados da linguagem Lua. Figura 3: Definição abstrata de um Aspecto 1. a = Aspect:new() 2. a:aspect( {name = ’nome aspecto’}, 3. {pointcutname = ’nome do ponto de corte’, 4. designator = ’tipo do designador’, 5. list = {’some-class.method1()’,’another-class.*’}, 6. {type =’advice-type’, action = myadvice} 7. ) 8. function myadvice() 9. -- código do advice 10. end
elementos ou de diferentes maneiras. AspectLua segue o modelo tradicional e, por isso, sofre desses problemas.
Para promover a reusabilidade dos aspectos e suportar a composição heterogênea, interfaces aspectuais, pontos de junção abstratos e o uso de uma linguagem de conexão para instanciação de pontos de junção abstratos foram adicionadas a AspectLua gerando uma nova linguagem denominada RE-Aspectlua [Batista and Vieira, 2007]. Em RE-AspectLua, um aspecto é um conjunto de interfaces aspectuais. Uma interface aspectual define um contrato de funcionalidade que descreve como o aspecto interage com os outros elementos do sistema. Ela é constituída por um conjunto de refinamentos. Por sua vez, um refinamento especifica um conjunto de pontos de junção abstratos e um conjunto de ações a serem tomadas quando os pontos de junção são alcançados. Os pontos de junção abstratos são declarações de pontos de junção independentes do código base da aplicação no momento da especificação. Em RE-AspectLua, um ponto de junção abstrato é uma tabela que contém um campo denominado refine e um campo denominado action. O primeiro é uma string que serve como identificador do ponto de corte abstrato na interface. Essa string será transformada em um campo dos aspectos que implementam tal interface, pois, no futuro, esse campo irá apontar para um ponto de corte real. O segundo campo é um ponteiro para a ação a ser tomada quando o ponto de corte abstrato for alcançado.
A linguagem de conexão é uma linguagem de script, a linguagem Lua, utilizada para instanciar os pontos de junção abstratos definidos nas interfaces aspectuais, ou seja, a linguagem de conexão comanda o processo de composição dos aspectos com o código da aplicação. Uma linguagem de conexão oferece alto poder de expressividade, o que aumenta a flexibilidade do processo de composição e permite a criação de relações complexas entre aspectos e componentes. RE-AspectLua divide o processo de criação dos aspectos em duas etapas: (i) especificação e (ii) instanciação. Na primeira etapa, os aspectos são definidos por um conjunto de interfaces que não fazem referências a nenhum ponto concreto do programa. No segundo momento, a instanciação, os pontos de junção abstratos definidos na primeira etapa são instanciados em pontos de junção concretos através da linguagem de conexão. A Figura 4 ilustra a etapa de especificação de um aspecto em RE-AspectLua.
As linhas 1 e 2 criam, respectivamente, o aspecto aspect1 e o aspecto aspect2. A interface interface1 (linhas 3 a 5) define um refinamento que determina que o método advice1 será executado quando o ponto de corte abstrato abstractpointA for alcançado. Finalmente, as duas últimas linhas dessa figura a interface interface1 é associada aos aspectos aspect1 e aspect2. Nesse momento, a fase de especificação está completa.
A etapa de instanciação é exibida na Figura 5. O código dessa figura define se uma dada condição for verdadeira (condition = true) o ponto de corte abstrato abstractpointA da interface interface1 irá atuar antes de todas as chamadas ao método ClassA.method1. Caso seja falsa, o ponto de corte abstrato é instanciado determinando que o aspecto atue depois de todas as
Figura 4: Definição de um Aspecto em RE-Aspectlua 1. aspect1 = Aspect : new () 2. aspect2 = Aspect : new () 3. interface1 = AspectInterface : new ({ name = 'interface1'} , 4. { { refine = 'abstractpointA' , action = advice1 } } 5. ) 6. aspect1 : i n t e r f a c e (interface1) 7. aspect2: i n t e r f a c e (interface1)
chamadas ao método ClassA.method2. Dessa maneira, tal código mostra como RE-AspectLua permite a composição heterogênea, ou seja, o mesmo aspecto atuando de formas diferentes.
3. Mapeamento da APL para RE-AspectLua
RE-AspectLua é uma linguagem concreta que descreve aspectos abstratos e suas composições, e implementa a dicotomia conceitual aspecto-base. Por sua vez, a APL é uma linguagem abstrata cujo objetivo é ser um modelo de referência para as linguagens de definição de pontos de corte. A APL descreve apenas o mecanismo de composição que define a interação entre um componente que representa um interesse transversal com outro(s) componente(s) base, pois a arquitetura de referência não contempla explicitamente a dicotomia aspecto-base. Entretanto, em uma ligação aspectual, via o AO-Binding, um componente faz o papel de aspecto, podendo-se então afirmar que a arquitetura de referência contempla implicitamente a dicotomia aspecto-base.A APL define uma expressão de ponto de corte como sendo formada por quatro sub-expressões. Cada uma dessas sub-expressões representa um elemento arquitetural descrito através de lógica de primeira ordem. Cada sub-expressão da APL pode ter quantificadores e variáveis quantificadas, lista de propriedades, seletores de pontos de junção, operadores lógicos e os operadores da teoria dos conjuntos ∈ e ∉que atuam sobre containers, componentes, interfaces
e operações. Em RE-AspectLua cada expressão de ponto de corte é formada por wildcards, padrões de tipos e padrões de assinatura que atuam sobre objetos e funções. RE-AspectLua não define nenhum tipo de operador ou propriedade de contexto. Assim, uma expressão de ponto de corte no RE-AspectLua é uma simples, porém expressiva, enumeração de padrões de casamento. Os quantificadores da APL podem ser mapeados diretamente para os wildcards do RE-AspectLua; por exemplo, o operador ∀ (para todo) pode ser mapeado para o wildcard *. As variáveis quantificadas da APL são expressas no RE-AspectLua através do conjunto de enumerações realizadas no campo List. Por exemplo, a Figura 6 apresenta uma expressão em
APL que seleciona todos os pontos de corte dos componentes cujo nome é “ClassA”. Ou seja, cp representa todos os componentes que atendem a esses requisitos. Ela pode ser rescrita em RE-AspectLua na forma exibida na Figura 7. O campo list atinge os mesmos elementos descritos na APL uma vez que declara que todos os componentes ClassA com quaisquer métodos.
"
"
.
,
c
name
ClassA
c
cp
∈
�
∀
Figura 6: Expressão de ponto de corte em APL
.*}
{ClassA
list �
Figura 7: Expressão de ponto de corte em RE-AspectLua
Os seletores de ponto de junção da APL são mapeados diretamente em RE-AspectLua no campo designator, onde tal campo define o tipo de ponto de junção. Como dito anteriormente, a arquitetura de referência possui dois tipos de seletores de pontos de junção: call e execution. Eles interceptam chamadas de funções, sendo que a única diferença entre eles está no local onde ocorre à invocação. RE-AspectLua não contempla essa diferenciação entre o local onde ocorre uma invocação de uma função. Por isso, esse trabalho adicionou o designador execution que atua na execução de uma função. Portanto, esses dois tipos de pontos de junção podem ser mapeados, respectivamente, para os pontos de junção call e execution do RE-AspectLua. O call captura
1. If (condition) then
2. aspect1.interface1 ["abstractpointA"]= { designator = 'call' , list = {'ClassA.method1'} , type= 'before'} 3. else
4. aspect1.interface1 ["abstractpointA"]= { designator = 'call' , list = {'ClassA.method2'} , type= 'after'}
todos os pontos de junções do componente que realiza uma invocação a uma dada função, i.e requisita um serviço, enquanto que o execution captura todos os pontos de junções relacionados a um componente que executa uma dada função, ou seja, que provê um serviço.
Por sua vez, os operadores, as propriedades de contexto e os mecanismos de passagem de informações não podem ser mapeados para a versão original de RE-AspectLua, pois essa última não contempla tais conceitos. RE-AspectLua baseia-se apenas em expressões que codificam enumerações de pontos de junção. A única exceção é o operador lógico OR, que pode ser simulado passando mais de uma expressão para o aspecto que está sendo definido. Para resolver essas carências, esse trabalho estende RE-AspectLua adicionando as seguintes propriedades: (i) um conjunto de operadores booleanos, (ii) um conjunto de propriedades de contexto associadas a todas as invocações e (iii) um mecanismo de passagem de informações contextuais.
O conjunto de operadores lógicos é formado pelos seguintes operadores: AND, OR e NOT. Em RE-AspectLua, os operadores são utilizados dentro do campo list para combinar expressões de ponto de corte. A expressão da Figura 2 pode ser reescrita em RE-AspectLua na forma exibida na Figura 8.
}
{"
ComponentA
.methodA
*
OR
ComponentB
.methodA*"
list �
Figura 8: Uso dos operadores lógicos em RE-AspectLua
As propriedades de contexto são valores de pares <chave; valor> associados às invocações de funções. A classe Context, definida no escopo deste trabalho, oferece métodos para recuperar e para adicionar propriedades de contexto. Para criar uma propriedade, Context disponibiliza o método setProperty(key,value), que recebe como parâmetros um identificador, key, e um objeto representando a propriedade em si, value. Para obter o valor de uma propriedade, Context oferece o método getProperty(key), que recebe a chave da propriedade. Além disso, essa classe oferece métodos para recuperar propriedades contextuais a partir de um arquivo, loadFile(file), e para gravar propriedades contextuais em um arquivo, saveFile(file). A Tabela 1 resume a API da classe Context. Método Descrição getProperty(key) Recupera a propriedade key setProperty(key,value) Atribui o valor value a propriedade indicada por key loadFile(file) Recupera propriedades de contexto a partir de um arquivo saveFile(file) Grava as propriedades contextuais em um arquivo Tabela 1: API da classe �ontext
A APL é baseada em componentes, e não faz qualquer suposição sobre como esses componentes são implementados (classes, funções, tabelas etc.) ou da linguagem escolhida para tal, portanto, ela permite expressar pontos de corte em nível de componente. Entretanto, em algumas situações é necessário capturar elementos em nível de linguagem. Para isso, as propriedades contextuais fornecem um meio elegante de expor propriedades que estão além dos limites dos componentes, aumentando o poder de expressividade da linguagem.
A passagem de informações contextuais é feita através das propriedades contextuais. Para isso, a classe JoinPoint foi criada a fim de representar o contexto de um ponto de junção. A Tabela 2 apresenta a API de tal classe. Ela é constituída pelas propriedades contextuais associadas a invocações no ponto de junção que a classe representa, pelas propriedades estáticas e pelas propriedades dinâmicas associadas ao ponto de junção. A Figura 9 ilustra a sintaxe utilizada para criar uma propriedade de contexto de um ponto de junção. O código da Figura 9 cria uma propriedade de contexto denominada joinpointA para o ponto de junção jp, uma instância da classe JoinPoint. Dessa maneira, quando o ponto de junção jp for alcançado, a
propriedade joinpointA estará definida e, portanto, o aspecto poderá acessá-la. Logo, os advices podem acessar qualquer propriedade de invocação do ponto de junção.
Para recuperar uma dada propriedade de contexto de um ponto de junção, primeiramente deve-se recuperar o ponto de junção desejado e em seguida acessar a propriedade desejada através das propriedades de invocações do ponto de junção. A primeira linha do código da Figura 10 recupera o ponto de junção joinpointA e armazena-o na variável jp. Em seguida, a linha 2 acessa a propriedade de contexto determinada pela chave propertyA.
Figura 10: Recuperando uma propriedade de contexto de um ponto de junção Método/Campo Descrição getArgs() Método que retorna os argumentos do ponto de junção getSignature() Método que retorna a assinatura do ponto de junção getTarget() Método que retorna o objeto alvo Context Campo que contém as propriedades contextuais Tabela 2: API da classe JoinPoint
4. Estudo de Caso
O contexto do estudo de caso desse trabalho é a construção de plataformas de middlewares orientadas a aspectos. Dentre os vários conceitos transversais existentes no contexto de middleware, o conceito de distribuição foi selecionado, por ser primordial na construção de qualquer plataforma de middleware.
A distribuição pode ser modelada como um serviço aspectual da plataforma de middleware. O aspecto de distribuição intercepta invocações a serviços do lado do cliente, substituindo a chamada local por uma chamada remota, implementando um protocolo de comunicação. Como inicialmente a arquitetura do middleware não possui uma infra-estrutura de distribuição, portanto, o aspecto de distribuição deve instanciar e conectar na arquitetura os componentes responsáveis pelo protocolo de comunicação empregado em cada instância do middleware. Para isso, o aspecto atua interceptando invocações realizadas sobre os objetos proxy, pois toda as requisições a serviços realizadas pelos clientes ocorrem através desses objetos. A Figura 11 mostra a interface aspectual que realiza a interceptação das invocações realizadas sobres os proxy. Para a criação do aspecto de distribução é definida a interface IRemoteInvoker, linhas 2 a 4, constituída pelo ponto de corte abstrato invoker_proxy e pelo advice make_remotable. A função make_remotable, definida nas linhas 5 a 12, instancia os componentes responsáveis por implementar a infra-estrutura de rede. Primeiramente o advice precisa descobrir o protocolo de comunicação a ser utilizado, para isso ele inspeciona a propriedade contextual system, linhas 6 e 7. Em seguida, nas linhas 7 a 11, o advice carrega e conecta os componentes exigidos pelo protocolo em questão.
A Figura 12 ilustra o código de instanciação do aspecto de distribuição. Nas linhas 1 e 2, a propriedade contextual system é criada, indicando que CORBA será utilizado como protocolo de comunicação. Em seguida, na linha 3, a variável jp é criada para representar o ponto de junção invoker_proxy. A esse ponto de junção é associado o contexto context, linha 4. Por fim, linhas 5 a 7, o ponto de junção invoker_proxy é instanciado. A linha 6 indica que todas as invocações, call, realizadas sobre objetos proxy não terão prosseguimento, elas serão substituídas por chamadas remotas contidas dentro do advice. 1. JoinPoint jp = Context.getProperty(“joinpointA”); 2. jp.Context.getProperty(“propertyA”); Context.setProperty(“joinpointA”,jp) Figura 9: Criando uma propriedade de contexto para um ponto de junção
Nota-se que para mudar o protocolo de comunicação remota basta alterar o valor da propriedade system. Isso confere alta flexibilidade e baixo acoplamento entre os elementos da plataforma de middleware e os mecanismos subjacentes que constituem a infra-estrutura de rede.
5. Trabalhos Relacionados
HALO [Herzeel et al 2006] é uma linguagem de definição de poincuts baseada em lógica temporal projetada para atender os requisitos de aplicações sensíveis ao contexto. O uso da lógica temporal permite que a HALO expresse relações temporais em pointcuts. Os pointcuts são descritos em termos de predicados, compostos por operadores temporais e o predicado escape que permite o uso de código Lisp. Os advices são escritos como regras lógicas nas quais a cabeça da regra especifica uma função Lisp que será executada quando o ponto de corte for atingido. CARMA [Gybels and Brichau 2003] é uma linguagem de definição de poincuts baseada em lógica e na linguagem Smaltalk [Goldberg and Robson 1983], similar ao HALO, porém não contempla a lógica temporal. CARMA define cinco tipos de ponto de junção. Cada tipo ponto de junção é um predicado e as expressões de ponto de corte são consultas lógicas sobre esses predicados. Os advices são escritos em Smalltak. A APL e RE-AspectLua diferem de HALO e de CARMA por serem baseadas em casamento de padrões, e não em lógica. Uma diferença significativa de RE-AspectLua para essas linguagens é o baixo acoplamento entre aspectos e código base. Como conseqüencia, os aspectos definidos em HALO e CARMA têm reutilização limitada em comparação com aqueles definidos em RE-AspectLua, pois fazem referências diretas a pontos concretos do programa base.
[Kellens et al. 2006] propõe uma linguagem de pointcut baseada em modelo que é uma extensão de CARMA. O objetivo da proposta é endereçar o problema denominado fragile pointcut [Stoerzer and Graf 2005]. Os pointcuts são definidos em termos de um modelo conceitual do programa, evitando que os pointcuts façam referência direta ao código base da aplicação. Com isso, da mesma forma que em RE-AspectLua, os pointcuts são desacoplados do código da aplicação, o que promove um maior grau de reúso dos aspectos. Contudo, a referida
1. RemoteInvoker = Aspect:new() 2. IRemoteInvoker = AspectInterface: new( 3. name = 'IRemoteInvoker', { refine = 'invoker_proxy', action = make_remotable} 4. ) 5. function make_remotable(proxy) 6. jp = Context.getProperty("invoker_proxy"); 7. System = jp.Context.getProperty("system"); 8. code = protocols[system]; 9. if(code == nil) then error("This protocol is unknown!") 10. else loadstring(code) 11. end 12. end 13. RemoteInvoker:interface(IRemoteInvoker) Figura 12: Instanciação do aspecto RemoteInvoker
Figura 11: Interface do aspecto de distribuição 1. context = Context:new() 2. context.setProperty("system","corba") 3. jp = JoinPoint:new(“invoker_proxy”) 4. jp.Context = context 5. RemoteInvoker.IRemoteInvoker["invoker_proxy"] = { 6. designator = "call", list = {"Proxy.*"}, type="around" 7. }
linguagem não trata diretamente a questão do reúso dos aspectos. RE-AspectLua endereça essa questão através das interfaces aspectuais, pontos de corte abstratos e da linguagem de conexão.
6. Conclusões
Este artigo apresentou a instanciação de uma linguagem abstrata de pontos de junção para middleware OA em uma linguagem com suporte a reusabilidade de aspectos e composição heterogênea – RE-AspectLua. Por ser uma linguagem dinâmica, RE-AspectLua é especialmente interessante para o contexto de middlewares adaptáveis. As extensões definidas em RE-AspectLua para atender a especificação da APL permitem que (i) sejam definidos pontos de junção que atuam nas interfaces required dos componentes; (ii) sejam consideradas propriedades contextuais para se definir a atuação do ponto de junção; (iii) sejam definidas expressões compostas de pontos de corte através do uso de um conjunto de operadores lógicos.
Esse trabalho está inserido em um projeto amplo que consiste em validar a arquitetura de referência para middlewares OA através da sua aplicação na refatoração do middleware OiL (Orb in Lua) [Maia, Cerqueira and Kon 2005] para definição do AO-OIL. A versão estendida de RE-AspectLua tem sido aplicada nesse contexto.
Referências
Batista, T. and Vieira, M. (2007). RE-AspectLua-Achieving Reuse in AspectLua. Journal of Universal Computer Science, 13(6):786–805.
Cacho, N., Batista, T. and Fernandes, F. (2005). AspectLua-A Dynamic AOP Approach. Journal of Universal Computer Society (J. UCS), v. 11, n. 7, p. 1177–1197, 2005.
Cacho, N., et al (2006). Improving modularity of reflective middleware with aspect-oriented programming. In Procs of the 6th International Workshop on Software Engineering and Middleware, Portland, Nov.2006.
Coulson, G. et al. (2002). The design of a configurable and reconfigurable middleware platform. Distributed Computing, v. 15, n. 2, p. 109–126, 2002.
Goldberg, A. and Robson, D. (1983). Smalltalk-80: the language. Addison-Wesley, 1983.
Gybels, K. and Brichau, J. (2003). Arranging language features for more robust pattern-based crosscuts. In Proceedings of the 2nd international Conference on Aspect-Oriented Software Development (Boston, Massachusetts, March 17 - 21, 2003). AOSD '03. ACM, New York, NY, 60-69.
H.-A. Jacobsen (2001). Middleware Architecture Design Based on Aspects, the Open Implementation Metaphor and Modularity. In Workshop on Aspect-Oriented Programming and Separation of Concerns, Lancaster, UK, August 2001.
Herzeel, C., et al. (2006). A Temporal Logic Language for Context Awareness in Pointcuts, ECOOP 2006 Workshop on Revival of Dynamic Languages (RDL), Nantes, France, July 3, 2006.
Ierusalimsky, R., Figueiredo, L. H. and Celes, W. (1996). Lua – an extensible extension language. Software: Practice and Experience, 26(6), (1996), 635-652.
Kellens, A., et al. (2006). Managing the Evolution of Aspect-Oriented Software with Model-based Pointcuts, European Conf. on Object-Oriented Programming (ECOOP) 2006, Springer Verlag, LNCS 4067, pp. 501-525.
Kiczales, G., et al. (1997). Aspect-Oriented Programming. In Procs of the European Conference on Object-Oriented Programming, v.1241 (220–242). Springer-Verlag, Berlin, Heidelberg, New York. Loughran, N., et al. (2005). Requirements and Definition of Aspect-Oriented Middleware Reference
Architecture. Technical Report AOSD-Europe. Deliverable D21, AOSD-Europe-ULANC-15, Lancaster University.
Maia, R., Cerqueira, R., and Kon, F. (2005). A Middleware for Experimentation on Dynamic Adaptation. In Procs of the 4th workshop on Reflective and adaptive middleware systems, 2005. Stoerzer, M. and Graf, J. (2005). Using Pointcut Delta Analysis to Support Evolution of Aspect-Oriented
Software. In: International Conference on Software Maintenance (ICSM), IEEE Computer Society Press (2005) 653–656.