A Programação Orientada a Aspectos (AOP) separa preocupações transversais do código principal. Essas preocupações incluem logging, segurança ou transações. Muitas vezes, elas se espalham por vários módulos. Por exemplo, o mesmo log é repetido em camadas diferentes. Isso gera código emaranhado e difícil de manter. A AOP resolve isso com a modularização de aspectos.
Originalmente popularizada pelo Spring Framework e AspectJ, a AOP também existe em Python.
A biblioteca aspectlib ou decoradores personalizados são exemplos práticos.
A ideia central é separar o “o quê” (regras de negócio) do “quando” (cross-cuttings).
Consequentemente, a coesão do sistema aumenta visivelmente.
Assim, desenvolvedores focam na lógica principal sem distrações.
Conceitos fundamentais da Aop
Existem quatro elementos-chave: join point, pointcut, advice e aspecto. Join point é um ponto na execução do programa, como uma chamada de método. Pointcut é uma expressão que seleciona um conjunto de join points. Advice é a ação executada antes, depois ou ao redor do pointcut. Finalmente, o aspecto une pointcut com advice. Foi dito que isso lembra a meta-programação, mas com foco maior em separação.
A relação entre essas partes pode ser expressa assim:
Quando utilizar aop no seu projeto
Use AOP quando repetir o mesmo código em muitos lugares. Logging de entrada/saída de métodos é um caso clássico. Controle de acesso ou autorização também se beneficia muito. Gerenciamento de transações em bancos de dados é outro exemplo comum. Medição de desempenho (timers) foi aplicado com sucesso por várias equipes. Essas tarefas não pertencem à lógica de negócio principal. Por isso, elas são chamadas de “preocupações transversais”.
Além disso, evite AOP para fluxos de negócio complexos. Isso pode tornar o código obscuro e difícil de depurar. De fato, a rastreabilidade é reduzida quando muitos aspectos são usados. Então, recomenda-se começar com poucos aspectos bem documentados. Uma boa prática é limitar aspectos a infraestrutura ou segurança. Assim, você mantém a legibilidade e o benefício real da AOP.
Exemplo prático em python
O código abaixo mostra um aspecto simples de logging.
Ele intercepta qualquer função com o decorador @log_execution.
Antes da execução, imprime o nome e argumentos.
Depois, mostra o tempo gasto pela função.
Essa técnica centraliza o logging em um único lugar.
Isso é muito melhor do que copiar print em 50 funções.
Observe como a função de negócio (soma) fica limpa.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
import time import functools def log_execution(func): @functools.wraps(func) def wrapper(*args, **kwargs): print(f"Iniciando '{func.__name__}' com {args}") inicio = time.time() resultado = func(*args, **kwargs) fim = time.time() print(f"Finalizado '{func.__name__}' em {fim - inicio:.4f}s") return resultado return wrapper @log_execution def soma(a, b): """soma dois números (pura lógica de negócio)""" return a + b @log_execution def multiplica(a, b): return a * b # Teste print(soma(3, 5)) # a saída mostrará o log automaticamente print(multiplica(4, 7)) |
No exemplo, nenhuma função contém código de log.
As preocupações transversais foram isoladas no decorador.
Isso é um padrão AOP simplificado para Python.
Caso precisasse de pointcuts mais complexos, use aspectlib ou weaver.
A manutenção se torna incrivelmente mais fácil.
Você pode adicionar ou remover logs sem tocar nas funções.
Por último, lembre-se de que nem tudo deve ser aspecto.
Use com sabedoria, e seu código será mais elegante.