• Nenhum resultado encontrado

Figura 3.2 Processo de compilação do aspecto.

Figura 3.3 Pontos de interceptação.

de código Java.

3.3

Dynamic crosscutting

A modificação dinâmica acontece por meio de interceptação, ou seja, o aspecto inter- cepta pontos marcados nas classes, que são conhecidos como pontos de junção (join

point em inglês) (Soares et al., 2006), e são associados a chamada de métodos, constru- tores, execução de exceções, métodos de acesso a atributos da classe e inicialização de objetos. A Figura3.3mostra pontos de interceptação nas classes A e B definidos pelos pontos de corte.

A combinação de pontos de junção cria um ponto de corte (pointcut) (eclipse.org,

2009), em outras palavras, o ponto de corte declara os pontos onde se deseja interromper a execução de um programa, podendo ter acesso a suas propriedades, como o nome do método interceptado, argumentos que possui, etc. O objetivo dessa interceptação é

3.4. STATIC CROSSCUTTING

1 pointcut metodosDeProcess(): execution(public * Process.*(..)); 2

3 after(): metodosDeProcess(){

4 System.out.print("Método da classe Process foi executado"); 5 }

Figura 3.4 Pointcut para todos os métodos da classe Process.

alterar o fluxo original do programa para inserir novas chamadas, denominada advices. A definição do método interceptado pode ser abreviada com a utilização de curingas. Por exemplo, o código da Figura 3.4 (linha 1), utiliza asteriscos para declarar que o ponto de corte interceptará a execução de todos os métodos da classe Process e que retornem quaisquer tipos. A mesma regra funciona para pacotes, ou seja, a declaração package.* interceptará todas as classes do pacote package.

Um bloco de código advice é semelhante a um método de classe Java e pode ser executado antes, depois ou simplesmente substituir o código associado ao ponto de corte. Para especificar em qual momento um advice deve ser executado, a palavra reservada after, before ou around deve ser especificada seguido do nome do ponto de corte que está diretamente associado. O exemplo da Figura3.4(Linha 3), especifica que após executar qualquer método público da classe Process a mensagem "Método da classe Process foi executado"será exibida na saída padrão.

Segue abaixo os tipos de advices:

1. before: Executa quando o ponto de junção é alcançado.

2. after returning: Executa após a finalização, com sucesso, do ponto de junção. 3. after throwing: Executa após a finalização, sem sucesso, do ponto de junção. 4. after: Executa após a conclusão do ponto de junção.

5. around: Executa quando join point é alcançado, podendo substituir o ponto de junção por outro bloco de código.

3.4

Static crosscutting

Até o presente momento foi visto apenas a introdução a pontos de junção e advices que basicamente altera o fluxo de execução de uma classe. AspectJ também permite alterar a estrutura estática de uma classe java, podendo adicionar novos membros, alterar a

3.5. SUMÁRIO

1 public aspect aspectTest{

2 public void Teste.metodoTeste(){

3 System.out.println("Novo método"); 4 }

5 }

Figura 3.5 Inserindo um método através de aspecto.

1 public aspect aspectTeste{

2 declare parents: Teste implements Observer;

3 public void Classe.update(Observable o, Object arg)

4 {

5 System.out.println("Novo método update."); 6 }

7 }

Figura 3.6 Modificando a hierarquia de uma classe.

hierarquia das classes e/ou substituir exceções verificadas por não verificadas. Chamadas também de intertipos (intertypes).

O código da Figura 3.6 introduz o método metodoTeste() nos byte codes da classe Teste através de procedimento de weaving.

A palavra reservada declare parents é utilizada para especificar uma nova classe mãe para uma classe específica. A classe Teste recebe uma nova definição em sua hierarquia, implementando a interface Observer do pacote java.util, que de- fine o padrão de projeto Observador. A implementação da interface Observer, obriga que o método update(Observable, Object) seja definido, como mostrado na Figura3.6.

3.5

Sumário

Foi visto nesta seção que, mesmo com o uso da programação componentizada, ainda existirá a mistura de código, também conhecida como preocupações transversais (Cross- cutting concerns). Uma preocupação transversal é aquela onde toda sua implementação se espalha pelas entidades do programa, dificultando a manutenção e a extensão do de- senvolvimento. Um exemplo clássico é o módulo de logging de um programa, o qual é executado por quase todas as classes do sistema. Assim, aumentando a quantidade de linhas de código e dificultando a manutenção, pois caso tenha necessidade de mudar a as- sinatura de algum método, essa modificação impacta todas as classes que estiverem utili- zando. O embaralhamento de código é quando uma preocupação específica recebe linhas de código de outras preocupações, causadas pelo espalhamento (Eaddy et al.,2007).

3.5. SUMÁRIO

ajudando a combater as preocupações ortogonais através de sua compilação denomi- nada weaving. Toda implementação da preocupação é arrancada de outras preocupações (classes), concentrando a lógica em uma única entidade chamada aspecto. A sua utiliza- ção é feita através da ligação entre a preocupação implementada no aspecto com o ponto que deve ser utilizada, através dos pontos de junção. O processo de weaving junta todas as classes com os aspectos, gerando o bytecode final.

Concorrência é também uma preocupação que espalha com facilidade por todo o programa, uma vez que os programas precisam cada vez mais funcionar de forma assín- crona. A API java thread pode ser utilizada, ficando misturada com código de regra de negócio. Portanto, a proposta deste trabalho é utilizar programação orientada a aspectos como um meio de separar concorrência da implementação de regra de negócio.

4

AJCSP

4.1

Introdução

Algumas linguagens de programação tentam facilitar a especificação de sistemas concor- rentes, tornando-os mais simples e seguros. É o caso do CSP, que foi projetado com o objetivo de especificar sistemas concorrentes e distribuídos. O formalismo por trás do CSP permite verificar as propriedades dos sistemas especificados. Por exemplo, é possí- vel verificar automaticamente se um programa é livre de deadlock. Alguns trabalhos tentam trazer os conceitos de CSP para as linguagens de uso geral, que é o caso de JCSP (Welch,2006). JCSP é um framework feito em Java que implementa os conceitos e construções de CSP, sem a necessidade de utilizar diretamente as estruturas de baixo nível oferecidas pela linguagem.

Porém em muitas aplicações, independentemente de usar abordagens que facilite o desenvolvimento baixo nível, a concorrência não possui relação direta com as regras de negócio do programa em desenvolvimento. Nesse sentido, o entrelaçamento do código concorrente com as regras de negócio pode levar a um aumento indesejável dos custos de desenvolvimento e manutenção do código.

Este capítulo irá mostrar, detalhadamente, a proposta deste trabalho. Uma aborda- gem que traduz o comportamento concorrente, especificado através de anotações com sintaxe baseada em CSP, em códigos JCSP que são injetados nas classes originais uti- lizando programação orientada a aspectos. Inicialmente será mostrado o estilo de pro- gramação utilizando tais anotações, posteriormente será detalhado a implementação do compilador (Araújo et al., 2011; J. E. Araújo, 2010) proposto pela abordagem e final- mente as traduções utilizadas pelo compilador que transforma as anotaçoes CSP em código JCSP.

4.2. ESTILO DO CÓDIGO

1 <channels> 2 <one2one>

3 <name> ch </name> 4 <type> Integer </type> 5 </one2one>

6 </channels>

Figura 4.1 O arquivo channels.xml usado para declarar canais.

4.2

Estilo do código

A abordagem consiste em especificar o comportamento concorrente das classes em co- mentários, semelhante às especificações de anotações java (Flanagan, 2005). Para dife- renciar de um comentário convencional, o token @# é utilizado após o símbolo // que define comentários.

Uma vez que essas especificações também são comentários Java, todo o compor- tamento concorrente é ignorado quando o compilador javac é utilizado, gerando uma versão tradicional sequencial do sistema.

Todo o comportamento de um processo é definido através de eventos, que em mui- tas situações podem ser compartilhados com outros processos, como é o caso de um canal de comunicação. Os eventos são especificados em um arquivo XML chamado channels.xml(mostrado na Figura4.1) e podem ser do tipo <one2one>, <one2any>,

<any2one> e <any2any>. É necessário utilizar um local global para as declarações dos

canais, para que todos os processos especificados no projeto consigam ver todos os even- tos declarados.

As anotações AJCSP são verificadas em tempo de compilação, quando são analisa- das a sintaxe do comportamento, declaração das variáveis, eventos e processos. Caso um evento utilizado não esteja declarado, no arquivo channels.xml, uma exceção será apresentada em tempo de compilação, detalhando o problema.

Apesar de ser baseado em CSP, a sintaxe AJCSP possui diferenças. Por exemplo, a utilização de parênteses na chamada de um processo é similar a criação do objeto de uma classe java, como mostrado na Figura4.2. Mais detalhes serão discutidos nas próximas seções.

Documentos relacionados