Programmation orientée aspect vs programmation orientée objet


199

Comme la plupart des développeurs ici et dans le monde entier, je développe des systèmes logiciels utilisant des techniques de programmation orientée objet (POO) depuis de nombreuses années. Donc, quand je lis que la programmation orientée aspect (AOP) résout bon nombre des problèmes que la POO traditionnelle ne résout pas complètement ou directement, je m'arrête et je pense, est-ce réel?

J'ai lu beaucoup d'informations en essayant d'apprendre les clés de ce paradigme AOP et je suis au même endroit, donc je voulais mieux comprendre ses avantages dans le développement d'applications dans le monde réel.

Quelqu'un a-t-il la réponse?


7
Toutes les réponses ont été très bonnes, c'est un cas parfait pour une réponse éditée par une seule communauté qui les combinerait toutes. Tous disent la même chose mais de différentes manières et en utilisant des exemples différents qui ajoutent à la valeur globale
Vinko Vrsalovic

Réponses:


323

Pourquoi "vs"? Ce n'est pas "vs". Vous pouvez utiliser la programmation orientée aspect en combinaison avec la programmation fonctionnelle, mais également en combinaison avec la programmation orientée objet. Ce n'est pas "vs", c'est "Programmation Orientée Aspect avec Programmation Orientée Objet".

Pour moi, l'AOP est une sorte de "méta-programmation". Tout ce que fait AOP pourrait également être fait sans lui en ajoutant simplement plus de code. AOP vous évite simplement d'écrire ce code.

Wikipedia a l'un des meilleurs exemples de cette méta-programmation. Supposons que vous ayez une classe graphique avec de nombreuses méthodes "set ... ()". Après chaque méthode définie, les données des graphiques ont changé, ainsi les graphiques ont changé et donc les graphiques doivent être mis à jour à l'écran. Supposons que pour repeindre les graphiques, vous devez appeler "Display.update ()". L'approche classique consiste à résoudre ce problème en ajoutant plus de code . À la fin de chaque méthode définie, vous écrivez

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

Si vous avez 3 méthodes set, ce n'est pas un problème. Si vous en avez 200 (hypothétique), cela devient vraiment pénible d'ajouter cela partout. De plus, chaque fois que vous ajoutez une nouvelle méthode set, vous devez vous assurer de ne pas oublier de l'ajouter à la fin, sinon vous venez de créer un bogue.

AOP résout cela sans ajouter des tonnes de code, à la place, vous ajoutez un aspect:

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

Et c'est tout! Au lieu d'écrire le code de mise à jour vous-même, vous dites simplement au système qu'après avoir atteint un pointcut set (), il doit exécuter ce code et il l'exécutera. Pas besoin de mettre à jour 200 méthodes, pas besoin de s'assurer de ne pas oublier d'ajouter ce code sur une nouvelle méthode set. De plus, vous avez juste besoin d'un point:

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

Qu'est-ce que ça veut dire? Cela signifie que si une méthode est nommée "set *" (* signifie que n'importe quel nom peut suivre après set), indépendamment de ce que la méthode retourne (premier astérisque) ou des paramètres qu'elle prend (troisième astérisque) et c'est une méthode de MyGraphicsClass et ceci classe fait partie du package "com.company. *", il s'agit alors d'un pointcut set (). Et notre premier code dit " après avoir exécuté une méthode qui est un point de consigne, exécutez le code suivant".

Voyez comment AOP résout élégamment le problème ici? En fait, tout ce qui est décrit ici peut être fait au moment de la compilation. Un préprocesseur AOP peut simplement modifier votre source (par exemple en ajoutant Display.update () à la fin de chaque méthode set-pointcut) avant même de compiler la classe elle-même.

Cependant, cet exemple montre également l'un des gros inconvénients d'AOP. AOP fait en fait quelque chose que de nombreux programmeurs considèrent comme un " anti-modèle ". Le motif exact est appelé " Action à distance ".

L'action à distance est un anti-modèle (une erreur commune reconnue) dans lequel le comportement dans une partie d'un programme varie énormément en fonction des opérations difficiles ou impossibles à identifier dans une autre partie du programme.

En tant que débutant dans un projet, je pourrais simplement lire le code de n'importe quelle méthode set et le considérer comme cassé, car il ne semble pas mettre à jour l'affichage. Je ne vois pas en regardant simplement le code d'une méthode set, qu'après son exécution, un autre code sera "magiquement" exécuté pour mettre à jour l'affichage. Je considère cela comme un sérieux inconvénient! En apportant des modifications à une méthode, des bogues étranges peuvent être introduits. Comprendre davantage le flux de code où certaines choses semblent fonctionner correctement, mais ne sont pas évidentes (comme je l'ai dit, elles fonctionnent comme par magie ... d'une manière ou d'une autre), est vraiment difficile.

Mettre à jour

Juste pour clarifier cela: Certaines personnes pourraient avoir l'impression que je dis que l'AOP est quelque chose de mauvais et ne devrait pas être utilisé. Ce n'est pas ce que je dis! AOP est en fait une excellente fonctionnalité. Je dis juste "Utilisez-le soigneusement". AOP ne causera des problèmes que si vous mélangez du code normal et AOP pour le même aspect . Dans l'exemple ci-dessus, nous avons l'aspect de mettre à jour les valeurs d'un objet graphique et de peindre l'objet mis à jour. Il s'agit en fait d'un seul aspect. Le codage de la moitié en code normal et de l'autre moitié en tant qu'aspect est ce qui ajoute le problème.

Si vous utilisez AOP pour un aspect complètement différent, par exemple pour la journalisation, vous ne rencontrerez pas le problème anti-modèle. Dans ce cas, un débutant dans le projet pourrait se demander "D'où viennent tous ces messages de journal? Je ne vois aucune sortie de journal dans le code", mais ce n'est pas un gros problème. Les modifications qu'il apporte à la logique du programme ne briseront guère la fonction de journalisation et les modifications apportées à la fonction de journal ne briseront guère la logique de son programme - ces aspects sont totalement séparés. L'utilisation d'AOP pour la journalisation a l'avantage que votre code de programme peut se concentrer pleinement sur ce qu'il doit faire et vous pouvez toujours avoir une journalisation sophistiquée, sans que votre code soit encombré par des centaines de messages de journal partout. De plus, lorsqu'un nouveau code est introduit, les messages de journal apparaissent comme par magie au bon moment avec le bon contenu.

Donc, une bonne utilisation d'AOP dans mon exemple serait de toujours se connecter si une valeur a été mise à jour via une méthode set. Cela ne créera pas d'anti-motif et ne sera presque jamais la cause d'un problème.

On pourrait dire que si vous pouvez facilement abuser d'AOP pour créer autant de problèmes, c'est une mauvaise idée de tout utiliser. Mais quelle technologie ne peut pas être utilisée abusivement? Vous pouvez abuser de l'encapsulation des données, vous pouvez abuser de l'héritage. Presque toutes les technologies de programmation utiles peuvent être utilisées à mauvais escient. Considérez un langage de programmation si limité qu'il ne contient que des fonctionnalités qui ne peuvent pas être utilisées abusivement; un langage où les fonctionnalités ne peuvent être utilisées que comme elles étaient initialement destinées à être utilisées. Un tel langage serait si limité qu'il est discutable s'il peut même être utilisé pour une programmation du monde réel.


4
La journalisation semble être un exemple spécifique où AOP ne se traduit pas par une action à distance. À l'heure actuelle, wikipedia comme exemple d'utilisation d'aspect pour des choses comme les contrôles de sécurité, qui rendent le flux du programme beaucoup plus compréhensible.
kizzx2

7
@ kizzx2: Excellent point sur la journalisation, en fait - c'est le meilleur exemple que j'ai vu jusqu'ici la force d'AOP, sans en savoir trop sur AOP. Merci d'avoir partagé!
bévues

@Mecki, votre exemple est trop simplifié et ne reflète pas le cas d'utilisation général. Dans votre exemple, Display.updatene prend aucun argument. Que se passe-t-il si nous devons transmettre des arguments (par exemple, une logfonction nécessite généralement un messageparamètre)? N'aurions-nous pas alors besoin d'ajouter beaucoup de code passe-partout pour le faire de la manière AOP?
Pacerier

3
@Pacerier Mon exemple est simplifié car SO n'est pas un forum d'enseignement. Je répondais simplement à la question de l'intervenant, probablement beaucoup plus détaillée qu'il n'aurait été nécessaire. Si vous voulez en savoir plus sur AOP, essayez de lire la documentation du programmeur et si vous avez une question détaillée, pourquoi ne pas la poser ici? Non, pas dans un commentaire, allez créer une nouvelle question parce que c'est ça le SO. Je suis sûr que quelqu'un pourra dissiper vos doutes dans une réponse.
Mecki

2
@Pacerier Désolé, mais je ne vois pas votre point. Voir ici: stackoverflow.com/a/8843713/15809 Ce code enregistre chaque appel à chaque méthode publique, y compris tous les types et valeurs d'argument de méthode. Vous écrivez cela une seule fois et il n'y a aucun code passe-partout ajouté à n'importe quelle méthode, c'est juste le code affiché dans la réponse.
Mecki

29

la pogrammation orientée aspect offre un bon moyen de mettre en œuvre des préoccupations transversales telles que la journalisation, la sécurité. Ces concessions transversales sont des éléments de logique qui doivent être appliqués à de nombreux endroits, mais qui n'ont en réalité rien à voir avec la logique métier.

Vous ne devriez pas voir l'AOP comme un remplacement de l'OOP, plutôt comme un bel ajout, qui rend votre code plus propre, couplé de manière lâche et axé sur la logique métier. Donc, en appliquant l'AOP, vous bénéficierez de 2 avantages majeurs:

  1. La logique de chaque préoccupation est maintenant au même endroit, au lieu d'être dispersée partout dans la base de code.

  2. les classes sont plus propres car elles ne contiennent que du code pour leur préoccupation principale (ou fonctionnalité principale) et les préoccupations secondaires ont été déplacées vers les aspects.


27

OOP et AOP ne s'excluent pas mutuellement. L'AOP peut être un bon ajout à l'OOP. AOP est particulièrement pratique pour ajouter du code standard comme la journalisation, le suivi des performances, etc. aux méthodes sans obstruer le code de méthode avec ce code standard.


10

Je pense qu'il n'y a pas de réponse générale à cette question, mais une chose à noter est que l'AOP ne remplace pas l' OOP mais ajoute certaines caractéristiques de décomposition qui répondent à la soi-disant tyrannie de la composition dominante ( 1 ) (ou aux préoccupations transversales).

Cela aide sûrement dans certains cas tant que vous contrôlez les outils et les langues à utiliser pour un projet spécifique, mais ajoute également un nouveau niveau de complexité concernant l'interaction des aspects et la nécessité d'outils supplémentaires comme l' AJDT pour toujours comprendre votre programme.

Gregor Kiczales a une fois donné une introduction intéressante sur AOP lors de Google Tech Talks que je recommande de regarder: Programmation orientée aspect: Recherche radicale en modularité .


8

Tout d'abord, AOP ne remplacera pas OOP. AOP étend OOP. Les idées et les pratiques de la POO restent pertinentes. Une bonne conception d'objet facilitera probablement son extension avec des aspects.

Je pense que les idées que l'AOP apporte sont importantes. Nous devons trouver des moyens de mettre en œuvre des préoccupations transversales sur les différentes classes de votre programme sans avoir à changer les classes elles-mêmes. Mais je pense que l'AOP finira par devenir une partie des autres outils que nous utilisons et non un outil ou une technique séparée. Nous voyons déjà cela se produire.

Quelques langages dynamiques comme Ruby et Python ont des constructions de langage comme des mixins qui résolvent les mêmes problèmes. Cela ressemble beaucoup à AOP mais est mieux intégré dans la langue.

Spring and Castle et quelques autres frameworks d'injection de dépendances ont des options pour ajouter un comportement aux classes qu'ils injectent. C'est une façon de faire du tissage à l'exécution et je pense que cela a beaucoup de potentiel.

Je ne pense pas que vous devrez apprendre un tout nouveau paradigme pour utiliser AOP. Les idées sont intéressantes mais sont lentement absorbées par les outils et les langages existants. Restez simplement informé et essayez ces outils.



1

Je suis en retard pour répondre à cette question, mais c'est l'un de mes sujets préférés, alors laissez-moi partager mon point de vue.

OOP est principalement utilisé pour organiser votre logique métier tandis que AOP aide à organiser vos éléments non fonctionnels comme l'audit, la journalisation, la gestion des transactions, la sécurité, etc.

De cette façon, vous pouvez découpler votre logique métier avec une logique non fictive qui rend le code plus propre.

L'avantage Otter est que vous pouvez appliquer les conseils (exemple d'audit) de manière très cohérente sans implémenter d'interface, ce qui offre une grande flexibilité de modification sans toucher à la logique métier

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.