AOP vs Recursos

A Programação Orientada a Aspectos (AOP) é ​​um paradigma de programação bastante popular. O artigo da Wikipedia explica bem a motivação para essa abordagem.

imagem

AOP é uma excelente ferramenta para conceitos globais, como: registro em log, que, diretamente, não afetam a lógica do código.

No entanto, problemas com o AOP são descobertos quando usados ​​para requisitos de negócios, como autorização. Tais aspectos devem estar claramente visíveis no código apropriado, para que o desenvolvedor possa ver imediatamente ao ler o código-fonte se eles estão implementados corretamente. As estruturas de AOP geralmente resolvem esse problema com anotações:

@RequireRole(Role.Admin) // clearly visible aspect fun updateUserPermissions(…) { // logic here } 

No entanto, em termos de legibilidade, não é muito diferente da abordagem funcional, usando o método requireRole em vez da anotação.

Nota do tradutor : no artigo original, é usada a expressão quando reescrita de forma funcional ou abordagem funcional, que pode ser interpretada como usando uma abordagem funcional ou uma chamada de função direta / específica. O artigo tem exemplos que podem ser interpretados de maneiras diferentes.

Também:

1. No futuro, retornaremos ao conceito de funções de ordem superior

2. O artigo encontra a palavra aspecto, que é o inglês e o conceito no aspecto AOP


 fun updateUserPermissions(…) { requireRole(Role.Admin) // throws SecurityException // logic here } 

Além disso, a abordagem funcional tem a vantagem de escalar para verificações de controle de acesso mais complexas, como análise de parâmetros de método, antes de decidir qual função do usuário é necessária.

O mesmo vale para outros tipos de aspectos, como transações. Infelizmente, apresentar funcionalmente conceitos mais complexos em Java é complicado e inconveniente, o que cria a popularidade artificial das estruturas de AOP no ecossistema Java.

No Kotlin, em vez de uma abordagem de transação semelhante a Java usando AOP e anotações como esta:

 @Transactional fun updateUserPermissions(…) { // logic here } 

Também é legível e parece limpo quando reescrito sem anotações, com uma abordagem funcional.

 fun updateUserPermissions(…) = transactional { // logic here } 

A vantagem dessa abordagem é que você sempre pode pressionar Ctrl / Cmd + Clique na declaração da função transacional no seu IDE e ver imediatamente o que exatamente faz. O que geralmente não é possível com nenhuma das estruturas de AOP comumente usadas. Mesmo quando a navegação para o código de aspecto é fornecida usando o plug-in IDE, a descriptografia de sua lógica requer conhecimento de uma API e / ou convenções multifuncionais separadas.

Infelizmente, há problemas com o dimensionamento da maneira de substituir as anotações de AOP no Kotlin. Para o caso em que vários aspectos são aplicados à mesma função, com o acúmulo de chaves e recuos:

 fun updateUserPermissions(…) = logged { transactional { // logic here } } 

Uma solução alternativa é criar uma função de ordem superior para preservar o código aceitável ao aplicar vários aspectos:

 fun updateUserPermissions(…) = loggedTransactional { // logic here } 

Outra desvantagem da abordagem funcional é que aspectos como o log exigem acesso aos parâmetros do método. Eles geralmente estão disponíveis em estruturas de AOP por meio de APIs especiais, mas usando as funções padrão da linguagem Kotlin, você não pode acessá-las facilmente. Portanto, para realmente apresentar um exemplo real do aspecto do registro, em uma forma puramente funcional, você ainda precisa escrever uma quantidade significativa de código da placa da caldeira :

 fun updateUserPermissions(params: Params) = logged("updateUserPermissions($params)") { // logic here } 

Essa consideração ainda faz da AOP a ferramenta de log preferida quando você realmente precisa tê-la global e consistentemente em seu aplicativo. Ao mesmo tempo, usar o AOP para funcionalidades como autorização e transações é um abuso, dadas as ricas abstrações funcionais disponíveis no Kotlin. As funções lidam com esses requisitos de maneira melhor e mais limpa.

Concluindo, eu diria que o aprimoramento adicional das abstrações funcionais para fornecer uma substituição ainda melhor da AOP poderia ser um vetor promissor para o desenvolvimento futuro da linguagem Kotlin. As estruturas de AOP baseadas em Java são tipicamente específicas da JVM e percebidas como mágicas, enquanto as abstrações funcionais do Kotlin são verdadeiramente multiplataforma e transparentes para o usuário.
Nota do tradutor :
1. Artigo em suporte (eng) .
2. O autor do artigo original é Roman Elizarov (Team Lead JetBrains, trabalhando em corotinas e bibliotecas Kotlin, programação esportiva / ICPC, concorrência e algoritmos, matemática / finanças quantitativas; anteriormente Devexperts). Em Habr elizarov

Source: https://habr.com/ru/post/pt435454/


All Articles