Programação Orientada a Aspectos
Em ciência da computação, programação orientada a aspectos ou POA, é um paradigma de programação de computadores que permite aos desenvolvedores de software separar e organizar o código de acordo com a sua importância para a aplicação (separation of concerns). Todo o programa escrito no paradigma orientado a objetos possui código que é alheio a implementação do comportamento do objeto. Este código é todo aquele utilizado para implementar funcionalidades secundárias e que encontra-se espalhado por toda a aplicação (crosscutting concern). A POA permite que esse código seja encapsulado e modularizado.
Os paradigmas de programação mais antigos, como a programação procedural e programação orientada a objeto, implementam a separação do código, através de entidades únicas. Por exemplo, a funcionalidade de log de dados, numa linguagem orientada a objetos, é implementada em uma única classe, que é referenciada em todos os pontos onde é necessário fazer log de dados. Como praticamente todo método necessita que alguns dados sejam registrados em log, as chamadas a essa classe são espalhadas por toda a aplicação.
Tipicamente uma implementação da POA busca encapsular essas chamadas através de uma nova construção chamada de “aspecto”. Um aspecto pode alterar o comportamento de um código (a parte do programa não orientada a aspectos) pela aplicação de um comportamento adicional, advice, sobre um “ponto de execução”, ou join point. A descrição lógica de um conjunto de join points é chamada de pointcut.
Em muitas linguagens POA, a execução de um método e referências a atributos são exemplos de join points. Um pointcut consiste, por exemplo, de todas as referências a um conjunto de atributos.
POA e uma ferramenta para resolvermos alguns problemas de POO
Problemas de POO
- Complexidade de software sempre Aumenta
- Fatores de qualidade não são adequadamente tratados
- Separação de interesses em OO
- Oferece suporte a implementação de requisitos funcionais
- Não se preocupa com os requisitos não funcionais
A POA vem para junto com a POO resolver e somar mais qualidade ao software final
Conceitos de Orientação Orientada a Aspectos
Responsabilidades ou interesses
Sistemas de software consistem de um conjunto de “áreas de interesse” ou responsabilidades distintas como, por exemplo, responsabilidades funcionais (lógica de negócio) e não-funcionais (performance, persistência de dados, logging, autenticação de usuários, segurança, verificação de erros, etc.). Existem também as preocupações relacionadas com o processo de desenvolvimento de software, como clareza de entendimento, facilidade de manutenção, rastreabilidade, simplicidade de evolução do software, etc.
Separação das responsabilidades
A melhor maneira de se projetar um sistema é através da separação de suas responsabilidades distintas de tal modo que podemos alterar/re-projetar cada uma sem que isto afete as demais partes do sistema. A eficiência do desenvolvimento aumenta na medida em que conseguimos separar as suas diferentes responsabilidades em módulos estanques. Este princípio é razoavelmente antigo, e a POO nos trouxe uma importante resposta a ele: a classe como uma dimensão para a decomposição de responsabilidades. Mas algumas responsabilidades não são tão facilmente decompostas em apenas uma dimensão…
Responsabilidades transversais
Em sistemas complexos, sempre existem responsabilidades de interesse comum que são utilizadas por vários módulos. As responsabilidades não-funcionais que citamos geralmente têm esta característica, mas também algumas funcionais. Estas responsabilidades são difíceis de isolar porque são necessárias em vários pontos do código. Em POO, uma classe oferece uma boa maneira de se separar a maioria das responsabilidades funcionais, mas é bastante limitada quando se trata de responsabilidades transversais. Com a POO, os crosscutting concerns ficam espalhados por vários módulos em pequenos trechos de código que são, em geral, repetitivos, resultando em sistemas difíceis de projetar, entender, implementar, manter e evoluir.
Um exemplo pode ajudar a esclarecer melhor os conceitos. Imagine um sistema bancário. Este sistema tem como uma de suas responsabilidades funcionais centrais o controle das contas correntes dos clientes, candidata natural a se tornar uma classe. Mas este mesmo sistema tem diversas outras responsabilidades não-funcionais como: logging, integridade das transações, autenticação dos usuários, segurança, performance, etc., que são necessárias como suporte a várias classes funcionais, isto é, elas são transversais às divisões de responsabilidades entre os múltiplos módulos básicos do sistema (crosscutting concerns).
A POA complementa a POO por introduzir uma nova dimensão para a decomposição das responsabilidades transversais: os aspectos.
O paradigma da POA consiste na separação das responsabilidades transversais de um sistema em aspectos (unidades modulares) e a sua posterior composição junto às classes, formando um sistema único. Os aspectos podem ser inseridos, alterados ou removidos em tempo de compilação. Por estarem em um único bloco de código, sua manutenção é mais simples, diminuindo a complexidade do sistema e facilitando o seu entendimento. Além disso, o código das classes fica livre do código relacionado às responsabilidades transversais, o que facilita sua reutilização em diferentes contextos, combinando diferentes aspectos dependendo das necessidades da aplicação.
A POA envolve três fases distintas:
Decomposição: os vários concerns do sistema são identificados e classificados como comuns ou crosscutting.
Implementação: os concerns são implementados separadamente em classes (para os concerns comuns) e aspectos (para os crosscutting concerns).
Recomposição: o sistema é recomposto à partir dos concerns implementados segundo regras de recomposição. Esta fase é chamada de weaving.
Uma implementação básica de AOP consiste em: uma linguagem para programar os componentes (por exemplo, Java), uma linguagem para programar os aspectos (por exemplo, o AspectJ) e um weaver para combinar as duas linguagens (ferramenta que também faz parte do AspectJ). O weaver é uma espécie de montador que tem como entrada um programa de componente e o(s) programa(s) de aspectos e como saída um programa em uma linguagem específica (por exemplo, Java).
AspectJ
O AspectJ é uma ferramenta open source que acrescenta os conceitos de AOP à linguagem Java, através de uma extensão à linguagem: os “aspects”. Ele utiliza Java como a linguagem para a implementação dos concerns individuais, e tem construções para a especificação das regras de weaving, que são especificadas em termos de join points, pointcuts e advices, e tudo isto é encapsulado em um aspect.
Join points: representam pontos bem definidos na execução de um programa onde um determinado aspecto pode ser aplicado. Em AspectJ, join points podem ser chamadas de métodos, acessos a membros de uma classe, etc. Join points podem conter outros join points.
Pointcuts: pointcut é um agrupamento de join points baseando-se em um critério pré-definido.
Advices: trechos de código que são executados nos pointcuts. Um advice contém as alterações que devem ser aplicadas ortogonalmente ao sistema.
Aspects: são similares a classes: têm um tipo, podem ser estendidos, podem ser abstratos ou concretos e podem conter campos, métodos e tipos como membros. Mas são diferentes de classes: não têm construtor nem destrutor, não podem ser criados com o operador “new”, podem conter pointcuts e advices como membros e podem acessar membros de outros tipos.
Então O que são Aspectos?