Programação Orientada a Aspectos vs. Programação Orientada a Objetos


199

Como a maioria dos desenvolvedores aqui e no mundo inteiro, desenvolvo sistemas de software usando técnicas de programação orientada a objetos (OOP) há muitos anos. Então, quando li que a programação orientada a aspectos (AOP) aborda muitos dos problemas que a OOP tradicional não resolve completamente ou diretamente, paro e penso: é real?

Eu li muitas informações tentando aprender as chaves desse paradigma de AOP e estou no mesmo lugar; portanto, queria entender melhor seus benefícios no desenvolvimento de aplicativos no mundo real.

Alguém tem a resposta?


7
Todas as respostas foram muito boas, este é um caso perfeito para uma única resposta editada pela comunidade que combinaria todas elas. Todos estão dizendo a mesma coisa, mas de maneiras diferentes e utilizando diferentes exemplos que contribuem para o valor global
Vinko Vrsalovic

Respostas:


323

Por que "vs"? Não é "vs". Você pode usar a programação Orientada a Aspectos em combinação com a programação funcional, mas também em combinação com a Orientada a Objetos. Não é "vs", é "Programação Orientada a Aspectos com Programação Orientada a Objetos".

Para mim, AOP é algum tipo de "meta-programação". Tudo o que a AOP faz também pode ser feito sem a adição de mais código. AOP apenas poupa você escrevendo este código.

A Wikipedia tem um dos melhores exemplos para essa meta-programação. Suponha que você tenha uma classe gráfica com muitos métodos "set ... ()". Após cada método definido, os dados dos gráficos foram alterados, assim os gráficos foram alterados e, portanto, os gráficos precisam ser atualizados na tela. Suponha que repintar os gráficos que você deve chamar "Display.update ()". A abordagem clássica é resolver isso adicionando mais código . No final de cada método definido, você escreve

void set...(...) {
    :
    :
    Display.update();
}

Se você possui três métodos de conjunto, isso não é um problema. Se você tem 200 (hipotético), é realmente doloroso adicionar isso em qualquer lugar. Além disso, sempre que você adicionar um novo método de conjunto, lembre-se de não esquecer de adicioná-lo ao final, caso contrário, você acabou de criar um bug.

AOP resolve isso sem adicionar toneladas de código; em vez disso, você adiciona um aspecto:

after() : set() {
   Display.update();
}

E é isso! Em vez de escrever o código de atualização você mesmo, basta informar ao sistema que, após um pointcut set () ter sido atingido, ele deve executar esse código e executá-lo. Não é necessário atualizar 200 métodos, não se esqueça de adicionar este código em um novo método definido. Além disso, você só precisa de um pointcut:

pointcut set() : execution(* set*(*) ) && this(MyGraphicsClass) && within(com.company.*);

O que isso significa? Isso significa que se um método for chamado "conjunto *" (* significa que qualquer nome pode seguir após o conjunto), independentemente do retorno do método (primeiro asterisco) ou dos parâmetros necessários (terceiro asterisco) e é um método de MyGraphicsClass e este class faz parte do pacote "com.company. *", então este é um pointcut set (). E nosso primeiro código diz " depois executar qualquer método que seja um set pointcut, execute o seguinte código".

Veja como a AOP resolve elegantemente o problema aqui? Na verdade, tudo o que é descrito aqui pode ser feito em tempo de compilação. Um pré-processador AOP pode apenas modificar sua fonte (por exemplo, adicionar Display.update () ao final de cada método de setpoint) antes mesmo de compilar a própria classe.

No entanto, este exemplo também mostra uma das grandes desvantagens da AOP. AOP está realmente fazendo algo que muitos programadores consideram um " Antipadrão ". O padrão exato é chamado " Ação à distância ".

Ação à distância é um antipadrão (um erro comum reconhecido) no qual o comportamento em uma parte de um programa varia muito com base em operações difíceis ou impossíveis de identificar em outra parte do programa.

Como iniciante em um projeto, posso ler o código de qualquer método definido e considerá-lo quebrado, pois parece não atualizar a exibição. Não vejo apenas olhando para o código de um método set que, depois de executado, algum outro código será "magicamente" executado para atualizar a exibição. Considero isso uma desvantagem séria! Fazendo alterações em um método, erros estranhos podem ser introduzidos. Compreender melhor o fluxo de código onde certas coisas parecem funcionar corretamente, mas não são óbvias (como eu disse, elas funcionam magicamente ... de alguma forma), é realmente difícil.

Atualizar

Só para esclarecer isso: algumas pessoas podem ter a impressão de que estou dizendo que AOP é algo ruim e não deve ser usado. Não é isso que estou dizendo! AOP é realmente um ótimo recurso. Eu apenas digo "Use-o com cuidado". AOP só causará problemas se você misturar código normal e AOP para o mesmo Aspecto . No exemplo acima, temos o Aspecto de atualizar os valores de um objeto gráfico e pintar o objeto atualizado. Na verdade, esse é um aspecto único. Codificar metade dele como código normal e a outra metade como aspecto é o que adiciona o problema.

Se você usar o AOP para um aspecto completamente diferente, por exemplo, para o registro, não encontrará o problema antipadrão. Nesse caso, um iniciante no projeto pode se perguntar "De onde vêm todas essas mensagens de log? Não vejo nenhuma saída de log no código", mas isso não é um grande problema. As alterações que ele faz na lógica do programa dificilmente quebram o recurso de log e as alterações feitas no recurso de log dificilmente quebram a lógica do programa - esses aspectos são totalmente separados. O uso do AOP para o log possui a vantagem de que o código do programa pode se concentrar totalmente em fazer o que deve ser feito e você ainda pode ter um log sofisticado, sem que o seu código seja desordenado por centenas de mensagens de log em todos os lugares. Além disso, quando um novo código é introduzido, as mensagens de log magicamente aparecerão no momento certo, com o conteúdo certo.

Portanto, um bom uso do AOP no meu exemplo seria sempre registrar se algum valor foi atualizado por meio de um método definido. Isso não criará um antipadrão e dificilmente será a causa de qualquer problema.

Pode-se dizer que, se você pode abusar facilmente da AOP para criar tantos problemas, é uma má idéia usar tudo. No entanto, qual tecnologia não pode ser abusada? Você pode abusar do encapsulamento de dados, você pode abusar da herança. Praticamente todas as tecnologias de programação úteis podem ser abusadas. Considere uma linguagem de programação tão limitada que contenha apenas recursos que não possam ser abusados; um idioma em que os recursos podem ser usados ​​apenas como inicialmente pretendidos. Essa linguagem seria tão limitada que é discutível se ela pode ser usada para programação no mundo real.


4
O log parece ser um exemplo específico em que a AOP não resulta em ação a distância. No momento, a Wikipedia é o exemplo do uso de aspectos para verificações de segurança, que realmente fazem o programa fluir muito mais para entender.
Kizzx2

7
@ kizzx2: Na verdade, é um ótimo ponto de registro - é o melhor exemplo que já vi até agora, a força da AOP, sem saber muito sobre a AOP. Obrigado por compartilhar!
erros

@Mecki, Seu exemplo é excessivamente simplificado e não reflete o caso de uso geral. No seu exemplo, Display.updatenão aceita nenhum argumento. E se precisarmos passar argumentos (por exemplo, geralmente uma logfunção exigiria um messageparâmetro)? Não precisaríamos adicionar muito código clichê para fazer isso da maneira AOP?
Pacerier

3
@Pacerier Meu exemplo é simplificado porque o SO não é um fórum de ensino. Eu estava apenas respondendo à pergunta do interlocutor, provavelmente muito mais detalhado do que seria necessário. Se você quiser saber mais sobre AOP, tente ler alguma documentação do programador e se tiver uma pergunta detalhada, por que não fazer isso aqui? Não, não em um comentário, vá e crie uma nova pergunta, porque é isso que SO trata. Tenho certeza de que alguém será capaz de dissipar suas dúvidas em uma resposta.
Mecki

2
@ Pacerier Desculpe, mas não entendo o seu ponto. Veja aqui: stackoverflow.com/a/8843713/15809 Esse código registra todas as chamadas para todos os métodos públicos, incluindo todos os tipos e valores de argumentos do método. Você escreve isso exatamente uma vez e não há código clichê adicionado a qualquer método, é apenas o código mostrado na resposta.
Mecki

29

A programação orientada a aspectos fornece uma boa maneira de implementar preocupações transversais como registro em log, segurança. Essas concessões transversais são peças de lógica que precisam ser aplicadas em muitos locais, mas na verdade não têm nada a ver com a lógica de negócios.

Você não deve ver o AOP como um substituto do OOP, mais como um bom complemento, que torna seu código mais limpo, com pouco acoplamento e focado na lógica de negócios. Então, ao aplicar a AOP, você terá dois grandes benefícios:

  1. A lógica de cada preocupação agora está em um só lugar, em vez de estar espalhada por todo o código-base.

  2. as classes são mais limpas, pois contêm apenas código para sua principal preocupação (ou funcionalidade principal) e as preocupações secundárias foram movidas para aspectos.


27

OOP e AOP não são mutuamente exclusivos. AOP pode ser uma boa adição ao OOP. O AOP é especialmente útil para adicionar código padrão, como log, rastreamento de desempenho, etc. aos métodos, sem obstruir o código do método com esse código padrão.


10

Eu acho que não há resposta geral para essa pergunta, mas uma coisa a ser observada é que a AOP não substitui a OOP, mas adiciona certos recursos de decomposição que abordam a chamada tirania da composição dominante ( 1 ) (ou preocupações transversais).

Certamente ajuda em certos casos, desde que você esteja no controle das ferramentas e linguagens a serem usadas em um projeto específico, mas também adiciona um novo nível de complexidade em relação à interação de aspectos e à necessidade de ferramentas adicionais, como o AJDT ainda entenderem. seu programa.

Gregor Kiczales certa vez fez uma interessante palestra introdutória sobre AOP no Google Tech Talks, que eu recomendo assistir: Programação Orientada a Aspectos: Pesquisa Radical em Modularidade .


8

Primeiro de tudo, o AOP não substituirá o OOP. AOP estende OOP. As idéias e práticas da OOP permanecem relevantes. Ter um bom design de objeto provavelmente tornará mais fácil estendê-lo com aspectos.

Eu acho que as idéias que a AOP traz são importantes. Precisamos descobrir maneiras de implementar preocupações transversais em diferentes classes do seu programa sem precisar alterar as próprias classes. Mas acho que a AOP acabará se tornando parte de outras ferramentas que usamos e não uma ferramenta ou técnica separada. Já vemos isso acontecendo.

Algumas linguagens dinâmicas como Ruby e Python têm construções de linguagem como mixins que resolvem os mesmos problemas. Isso se parece muito com AOP, mas é melhor integrado ao idioma.

Spring e Castle e algumas outras estruturas de injeção de dependência têm opções para adicionar comportamento às classes que injetam. Essa é uma maneira de tecer em tempo de execução e acho que isso tem muito potencial.

Eu não acho que você precisará aprender um paradigma completamente novo para usar a AOP. As idéias são interessantes, mas estão sendo absorvidas lentamente pelas ferramentas e linguagens existentes. Apenas fique informado e experimente essas ferramentas.



1

Estou atrasado para responder a essa pergunta, mas é um dos meus tópicos favoritos, então deixe-me compartilhar minha opinião.

OOP é usado principalmente para organizar sua lógica de negócios, enquanto o AOP ajuda a organizar coisas não funcionais, como auditoria, log, gerenciamento de transações, segurança, etc.

Dessa forma, você pode desacoplar sua lógica de negócios com uma lógica não fictícia que torna o código mais limpo.

Outra vantagem é que você pode aplicar o conselho (auditoria de exemplo) de maneira muito consistente sem implementar nenhuma interface que ofereça grande flexibilidade para modificação sem tocar na lógica de negócios

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.