UNIVERSIDADE FEDERAL DE SANTA CATARINA

Curso: Sistemas de Informação

Disciplina: Programação Orientada a Objetos II

Professor: Antônio Augusto Fröhlich

Alunos:

  Fernanda Ariane Rangel Vieira - 00138215

           Heitor de Brito Fontana – 00138274

           Marcelo Braga – 00138401

 

 

PROGRAMAÇÃO ORIENTADA A ASPECTOS

 

Este trabalho é um estudo sobre programação orientada a aspectos. Tem como objetivo apresentar os conceitos fundamentais sobre o assunto (o que são aspectos e por que utiliza-los), e como pode ser feito um programa orientado a aspectos utilizando o AspectJ.

 

O que são Aspectos e por que devemos utiliza-los?

Pesquisas tem apontado muitos problemas de programação que nem linguagens procedurais nem as orientadas a objetos possuem técnicas suficientemente claras para implementar algumas decisões de projeto. Isto força a implementação destas decisões de projeto a serem espalhadas através do código gerando um código confuso e difícil de desenvolver e manter. Estas decisões de projeto são difíceis de capturar porque elas atravessam as funcionalidades básicas do sistema, ou seja, não é possível separa-la em um componente ou uma classe, pois ela “pertence” a todo sistema.

Neste sentido nasceu a AOP, com o intuito de apresentar técnicas de programação capazes de cobrir estas falhas. A programação orientada a aspectos permite aos programadores separar os interesses comuns do sistema (comportamentos que fogem a típica divisão de responsabilidade, como o logging), introduzindo o conceito de aspectos, os quais encapsulam comportamentos que afetam múltiplas classes.

Esses comportamentos não encaixam naturalmente dentro de um modulo de um programa, ou em vários módulos de programas fortemente relacionados. Os pioneiros da programação orientada a aspectos chamam este tipo de comportamento de crosscutting porque ele atravessa a divisão de responsabilidades dos modelos de programação tradicionais.

Na programação orientada a objetos a unidade natural de modularização é a classe, e um crosscutting é uma responsabilidade que está espalhada por muitas classes. Exemplos típico seria o tratamento de erros em contexto sensitivo, otimização de performance, e padrões de projeto.

Trabalhar com código que apontam para responsabilidades que atravessam o sistema gera problemas que resultam da falta de modularidade. Devido a implementação desses comportamentos serem espalhados, os desenvolvedores podem encontrar dificuldades em analisar, implementar e modificar tais comportamentos. Por exemplo, o código de logging é entrelaçado ao longo de outros códigos que não estão relacionados com logging.

Dependendo da complexidade e do escopo onde é inserido essa responsabilidade pode resultar em um código confuso que dependendo do local pode ter maiores ou menores implicações. A mudança de uma política de logging de uma aplicação pode envolver centenas de modificações, o que aumenta muito a quantidade de código a ser tratada, é o pior esse código vai estar espalhado em vários lugares.

AOP complementa a programação orientada a objeto por facilitar um outro tipo de modularidade que expande a implementação espalhada de uma responsabilidade dentro de uma simples unidade. Esta unidade é chamada de aspecto, daí o nome programação orientada a aspectos. Os interesses tornam-se fáceis de tratar porque estão concentrados no código de aspectos e afetaram todas as unidades desejadas.

Os aspectos de um sistema podem ser alterados, inseridos ou removidos em tempo de compilação, e freqüentemente reusados. Por estarem em um único bloco de código a manutenção é muito mais fácil e a complexidade do sistema diminui, facilitando o entendimento do mesmo.     

Uma implementação básica de AOP consiste em : uma linguagem de componente para programar os componentes, uma ou mais linguagem de aspectos para programar os aspectos, um weaver para combinar as duas linguagens, um programa de componentes e um ou mais programa de aspectos.

A linguagem de componentes pode ser qualquer linguagem de programação, já a de aspectos deve ser uma especifica para facilitar a programação. O weaver seria uma espécie de montador que tem como entrada o programa de componentes e o(s) programa(s) de aspectos e como saída uma programa numa linguagem específica(C, C++, Java...).

 

O que é AspectJ?

AspectJ é uma extensão da linguagem de programação Java que permite a implementação de aspectos, alem disso AspectJ conta com um montador que serve para unir o programa de componente com o programa de aspecto.

Depois de definirmos as responsabilidades pertencentes a todo sistema, inserimos essa responsabilidade em um modulo – chamado aspecto, definimos isso usando uma linguagem de aspecto – AspectJ por exemplo, após unimos isso com o sistema propriamente dito, essa união é feita com um montador (weaver). E então temos como resultado dessa união um programa completo – programa + aspectos do programa.

 

Um exemplo de implementação de um aspecto utilizando AspectJ:

Para termos uma idéia melhor, podemos analisar o seguinte problema.  O exemplo foi retirado do framework “Cactus” que simplifica testes de componentes server-side Java. Para facilitar no “debugging” foi pedido que seus implementadores incluíssem duas chamadas de funções pré-determinadas.  Na versão 1.2 do Cactus,  as funções foram inseridas sem utilizar AspectJ, o que fez com que um método típico ficasse parecido com o descrito abaixo:

 

Chamadas de Log manualmente inseridas em cada método.

public void doGet(JspImplicitObjects theObjects) throws ServletException

{

  logger.entry("doGet(...)");

 

  JspTestController controller = new JspTestController();

  controller.handleRequest(theObjects);

 

  logger.exit("doGet");

}

 

Sem uma exaustiva varredura de código, isso seria difícil de implementar. Nesta versão, haviam aproximadamente 80 chamadas de logs distintas espalhadas por 15 classes. Na versão 1.3 deste mesmo framework, essas 80 chamadas foram substituídas por um simples aspecto que automaticamente age sobre os métodos desejados. A seguir temos uma idéia de como foi declarado o aspecto citado anteriormente:


Chamadas de Log  automaticamente aplicadas a cada método.

public aspect AutoLog{

 

  pointcut publicMethods() : execution(public * org.apache.cactus..*(..));

 

  pointcut logObjectCalls() :

    execution(* Logger.*(..));

   

  pointcut loggableCalls() : publicMethods() && ! logObjectCalls();

   

  before() : loggableCalls(){

    Logger.entry(thisJoinPoint.getSignature().toString());

  }

   

  after() : loggableCalls(){

    Logger.exit(thisJoinPoint.getSignature().toString());

  }

}

 

Analisando o exemplo acima podemos ver que a declaração de um aspecto se assemelha e muito com a declaração de uma classe. Nela é definida Java Types, assim como em uma declaração de classe comum. Além da declaração, também foram incluídos “pointcuts” e “advices”.

 

Pointcuts e Joinpoints:

Para entender o que é um pointcut, é necessário saber primeiro o que é um joinpoint. Joinpoints representam pontos bem definidos em uma execução de um programa. Joinpoints típicos em AspectJ podem ser por exemplo chamadas de métodos, acessos a membros de uma classe entre outras ações de execução. Join points podem conter outros Join points.

Pointcut é uma construção de linguagem que junta um conjunto de Join Points baseando-se em um critério pré-definido.  O primeiro Pointcut no exemplo chamado “publicMethods” seleciona as execuções de todos os métodos públicos do pacote “org.apache.cactus “. Execution é uma primitiva de pointcut (assim como int é uma primitiva de Java Types.)  Ele seleciona a execução de qualquer método que bate com a assinatura definida entre parênteses. Um segundo pointcut chamado “logObjectCalls” seleciona todas as execuções de métodos da classe Logger. Finalmente temos o terceiro pointcut – “loggableCalls” que combina os dois pointcuts anteriores usando && !, ou seja, selecionando todos os métodos públicos em “org.apache.cactus” exceto os que se encontram também na classe Logger (Aplicar as chamadas de log aos métodos da classe logging resultaria em uma recursão infinita.)

 

Advice:

Agora que o aspecto definiu os pontos a serem “logados”, é usado o “advice” para completar implementação. Advice é o trecho de codigo  que é executado antes (before();), depois (after();) e simultaneamente  (around();) a  um Joinpoint. É algo como: - “Rode este código antes de todos os métodos que eu quero escrever um log.

 

Adiante o código retirado do trecho acima que descreve o advice:

before() : loggableCalls(){

    Logger.entry(thisJoinPoint.getSignature().toString());

}

 


O dispositivo utiliza a classe Logger . O método entry desta classe, por exemplo, esta implementado da seguinte maneira: 

public static void entry(String message){

   System.out.println("entering method " + message);

}

 

 

O resultado do aspecto “AutoLog” será:

entering method: void test.Logging.main(String[])

entering method: void test.Logging.foo()

exiting method: void test.Logging.foo()

exiting method: void test.Logging.main(String[])

 

Uma limitação da versão atual de AspectJ (atualmente a versão é a 1.0.3) é a na interpretação de bytecode, ou seja, o programa componente que for inserido no weaver deve ser o código fonte do mesmo, na versão 2.0 de AspectJ existe a promessa de conseguir fazer a mudança direta de bytecodes, não necessitando do código fonte.

 

Conclusão

A programação orientada a aspecto cada dia que passa deixa de ser uma grande promessa para fazer parte do dia-a-dia dos desenvolvedores, ainda que existam detalhes que precisam ser melhor estudado – como a falta de uma metodologia. Mas ainda assim vemos um grande futuro para a programação orientada a aspecto, por dispor de um flexibilidade não disponível na programação orientada a objetos.

Mas como toda tecnologia pode ser pensada para ser utilizada de uma forma e vir a ser utilizada de outra. Queremos acreditar que a AOP não seja utilizada apenas para cobrir furos de maus programas (ou maus desenvolvedores???). Esperamos que a AOP venha a contribuir para facilitar o entendimento de softwares complexos, e que possibilitem a diminuição do esforço necessário para a construção e manutenção desses sistemas.

Para maiores informações sobre a AOP e AspectJ recomendamos o site aspectj.org, que dispõem de inúmeros artigos sobre o assunto.