Esse artigo faz parte da revistaJava Magazine edição 34. Clique aqui para ler todos os artigos desta edição

jm34.jpg
que aqui para ler esse artigo em PDF.imagem_pdf.jpg

Ao longo dos últimos anos, a Programação Orientada a Aspectos (Aspect Oriented Programming –AOP) vem ganhando destaque, e aos poucos está se tornando um padrão de desenvolvimento, com muitas empresas incorporando a nova técnica no desenvolvimento de seus softwares. Neste artigo mostraremos como a programação orientada a aspectos pode resolver, de forma útil e elegante, muitos dos problemas com que nos deparamos no dia-a-dia do desenvolvimento.

Interesses transversais

Vamos começar apresentando alguns conceitos importantes. Um interesse (concern) é um requisito ou funcionalidade específica, que deve ser tratado para satisfazer o objetivo geral de um software. Normalmente, quando implementamos uma aplicação, procuramos “fatiá-la” em partes menores e tratar essas partes separadamente. Essa abordagem, denominada de Separação de Interesses (Separation of Concerns – SoC), é bastante antiga. Em 1976, E. Dijkstra, um dos fundadores da moderna ciência da computação, abordou o SoC em seu livro "A Discipline of Programming" e na década de 90 pesquisadores como Kiczales, Hursch e Lopes e iniciaram as pesquisas modernas sobre o tema (veja as referências ao final do artigo).

A separação de interesses é um conceito fundamental da engenharia de software, e base para diversos paradigmas de programação. Como sabemos, os softwares são modelados e implementados a partir das unidades que fundamentam cada paradigma. No paradigma procedural cria-se o sistema com base em procedimentos, que juntos realizam as funcionalidades do sistema. No paradigma OO, o programa é modelado e decomposto em classes, instanciadas sob forma de objetos, que interagem para produzir o comportamento esperado do software.

Apesar de nos oferecer maior abstração e muitas possibilidades, a orientação a objetos também possui limitações. O paradigma OO contempla apenas uma unidade de decomposição: a classe. Assim, todo software OO é modularizado em classes, e procura-se separar cada interesse em uma classe distinta. No entanto, isso nem sempre é possível. Aqueles que possuem alguma vivência com a orientação a objetos já se depararam com situações em que interesses distintos aparecem misturados numa mesma classe, ou interesses específicos aparecem espalhados em várias classes.

Imagine o interesse de logging, por exemplo. O acesso aos arquivos de log e a formatação das mensagens podem ser facilmente encapsulados em classes específicas, e algumas APIs facilitam esse trabalho (como é o caso do Log4j da Apache). Porém, o uso dessas APIs (a criação das classes específicas e as chamadas de seus métodos) não pode ser modularizado. A Listagem 1 mostra um exemplo na qual código de depuração (registro no log com o método debug()) está entrelaçado com código do negócio (efetuar o saque).

Listagem 1. Logging: um exemplo clássico de interesse transversal

import org.apache.log4j.Logger;
 
public class Conta {
  private static Logger logger =
      Logger.getLogger(Conta.class);
 
  private float saldo = 1000f;
 
  public float getSaldo() {
    return saldo;
  }
 
  public void setSaldo(float saldo) {
    this.saldo = saldo;
  }
 
  public void saque(float valor) {
    setSaldo(getSaldo() - valor);
    logger.debug("saque efetuado com sucesso");
  }
}

A exemplo do logging, alguns interesses não podem ser decompostos utilizando a orientação a objetos. Esses interesses são, por definição, “ortogonais” à decomposição em classes e entrecortam sua estrutura. Por isso são denominados interesses transversais. As implementações desses tipos de interesse obrigatoriamente estão espalhadas pela aplicação e misturadas com o código relativo a outros interesses. Alguns exemplos típicos de interesses transversais são gerenciamento de transações, concorrência, persistência, distribuição e segurança.

Vamos examinar um exemplo real. As Figuras 1 e 2, extraídas do site do AspectJ, ilustram a implementação de dois interesses distintos no código do Apache Tomcat. As barras verticais representam os diversos pacotes do Tomcat e as linhas vermelhas indicam os códigos que implementam os interesses em questão. Na Figura 1 é exibida a implementação do parsing de arquivos XML. Nota-se que todo o código relativo a esse interesse concentra-se em um único módulo, o que facilita a sua alteração e evolução. Na Figura 2, no entanto, observa-se exatamente o contrário: o interesse relativo ao logging está espalhado por toda a aplicação e, mesmo dentro de um único módulo, o código desse interesse encontra-se disperso (o que é indicado pela separação entre as linhas vermelhas). Utilizando OO não há como evitar esse problema, pois logging é um interesse transversal.

image004.gif
Figura 1
. Exemplo de modularização: as linhas vermelhas mostram a concentração do código de parsing XML do Tomcat em um único módulo

image006.gif
Figura 2
. Exemplo de falta de modularização: as linhas vermelhas mostram a distribuição do código de logging do Tomcat em vários módulos

...
Quer ler esse conteúdo completo? Tenha acesso completo