it-swarm.com.de

Aspektorientierte Programmierung vs. Objektorientierte Programmierung

Wie die meisten Entwickler hier und auf der ganzen Welt habe ich seit vielen Jahren Softwaresysteme entwickelt, die objektorientierte Programmiertechniken (OOP) verwenden. Wenn ich also lese, dass aspektorientierte Programmierung (AOP) viele der Probleme anspricht, die herkömmliches OOP nicht vollständig oder direkt löst, halte ich inne und denke, ist es real?

Ich habe viele Informationen gelesen, um die Schlüssel dieses AOP-Paradigmas zu erlernen, und bin an der gleichen Stelle. Deshalb wollte ich seine Vorteile bei der Entwicklung realer Anwendungen besser verstehen.

Hat jemand die Antwort?

186
yeradis

Warum "vs"? Es ist nicht "vs". Sie können die aspektorientierte Programmierung in Kombination mit der funktionalen Programmierung, aber auch in Kombination mit der objektorientierten Programmierung verwenden. Es ist nicht "vs", es ist "Aspektorientierte Programmierung mit objektorientierter Programmierung".

Für mich ist AOP eine Art "Meta-Programmierung". Alles, was AOP tut, kann auch ohne AOP ausgeführt werden, indem einfach mehr Code hinzugefügt wird. AOP erspart Ihnen nur das Schreiben dieses Codes.

Wikipedia hat eines der besten Beispiele für diese Metaprogrammierung. Angenommen, Sie haben eine Grafikklasse mit vielen "set ... ()" - Methoden. Nach jeder eingestellten Methode haben sich die Daten der Grafiken geändert, sodass sich die Grafiken geändert haben und die Grafiken auf dem Bildschirm aktualisiert werden müssen. Angenommen, Sie möchten die Grafiken neu zeichnen und müssen "Display.update ()" aufrufen. Der klassische Ansatz besteht darin, dies durch Hinzufügen von mehr Code zu lösen. Am Ende jeder eingestellten Methode schreiben Sie

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

Wenn Sie 3 Set-Methoden haben, ist das kein Problem. Wenn Sie 200 haben (hypothetisch), wird es sehr schmerzhaft, dies überall hinzuzufügen. Auch wenn Sie eine neue set-Methode hinzufügen, dürfen Sie nicht vergessen, diese am Ende einzufügen, da Sie sonst gerade einen Fehler erzeugt haben.

AOP löst dies, ohne jede Menge Code hinzuzufügen. Stattdessen fügen Sie einen Aspekt hinzu:

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

Und das ist es! Anstatt den Aktualisierungscode selbst zu schreiben, teilen Sie dem System lediglich mit, dass nach Erreichen eines set () -Punkts dieser Code ausgeführt werden muss und dieser Code ausgeführt wird. Keine Notwendigkeit, 200 Methoden zu aktualisieren, keine Notwendigkeit, sicherzustellen, dass Sie nicht vergessen, diesen Code einer neuen set-Methode hinzuzufügen. Zusätzlich benötigen Sie nur einen Punkteschnitt:

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

Was bedeutet das? Das heißt, wenn eine Methode den Namen "set *" hat (* bedeutet, dass nach set ein beliebiger Name folgt), unabhängig davon, was die Methode zurückgibt (erstes Sternchen) oder welche Parameter sie benötigt (drittes Sternchen) und = es ist eine Methode von MyGraphicsClass und diese Klasse ist Teil des Pakets "com.company. *", dann ist dies ein set () pointcut. Und unser erster Code lautet: " after Wenn Sie eine Methode ausführen, die ein Set-Point-Cut ist, führen Sie den folgenden Code aus.".

Sehen Sie hier, wie AOP das Problem elegant löst? Eigentlich kann alles, was hier beschrieben wird, zur Kompilierungszeit ausgeführt werden. Ein AOP-Präprozessor kann einfach Ihre Quelle ändern (z. B. Display.update () am Ende jeder Set-Point-Cut-Methode hinzufügen), bevor er die Klasse selbst kompiliert.

Dieses Beispiel zeigt jedoch auch einen der großen Nachteile von AOP. AOP tut tatsächlich etwas, das viele Programmierer als "Anti-Pattern" betrachten. Das genaue Muster heißt " Fernwirkung ".

Fernwirkung ist ein Antimuster (ein erkannter häufiger Fehler), bei dem das Verhalten in einem Teil eines Programms stark variiert, je nachdem, ob es schwierig oder unmöglich ist, Operationen in einem anderen Teil des Programms zu identifizieren.

Als Neuling in einem Projekt kann es sein, dass ich einfach den Code einer Set-Methode lese und ihn als fehlerhaft betrachte, da die Anzeige scheinbar nicht aktualisiert wird. Ich sehe nicht , wenn ich mir nur den Code einer set-Methode ansehe, dass ein anderer Code "magisch" ausgeführt wird, nachdem er ausgeführt wurde um die Anzeige zu aktualisieren. Ich halte das für einen ernsthaften Nachteil! Durch Änderungen an einer Methode können seltsame Fehler verursacht werden. Ein besseres Verständnis des Code-Flusses von Code, in dem bestimmte Dinge korrekt zu funktionieren scheinen, aber nicht offensichtlich sind (wie gesagt, sie funktionieren auf magische Weise ... irgendwie), ist wirklich schwierig.

Aktualisieren

Nur um das zu verdeutlichen: Einige Leute könnten den Eindruck haben, dass AOP etwas Schlechtes ist und nicht verwendet werden sollte. Das sage ich nicht! AOP ist eigentlich ein großartiges Feature. Ich sage nur "Benutze es vorsichtig". AOP verursacht nur dann Probleme, wenn Sie normalen Code und AOP für dasselbe verwechseln Aspekt. Im obigen Beispiel haben wir den Aspekt, die Werte eines grafischen Objekts zu aktualisieren und das aktualisierte Objekt zu zeichnen. Das ist in der Tat ein einzelner Aspekt. Die Hälfte davon als normalen Code und die andere Hälfte als Aspekt zu codieren, ist das, was das Problem hinzufügt.

Wenn Sie AOP für einen völlig anderen Aspekt verwenden, z. Bei der Protokollierung tritt das Problem mit der Musterabwehr nicht auf. In diesem Fall könnte sich ein Neuling im Projekt fragen: "Woher kommen all diese Protokollnachrichten? Ich sehe keine Protokollausgabe im Code", aber das ist kein großes Problem. Änderungen, die er an der Programmlogik vornimmt, werden die Protokollfunktion kaum beeinträchtigen, und Änderungen, die an der Protokollfunktion vorgenommen werden, werden seine Programmlogik kaum beeinträchtigen - diese Aspekte sind völlig voneinander getrennt. Die Verwendung von AOP für die Protokollierung hat den Vorteil, dass sich Ihr Programmcode voll und ganz auf das konzentrieren kann, was er tun soll, und Sie trotzdem über eine ausgefeilte Protokollierung verfügen können, ohne dass Ihr Code überall durch Hunderte von Protokollnachrichten überfüllt ist. Auch wenn neuer Code eingeführt wird, werden magische Protokollmeldungen zur richtigen Zeit mit dem richtigen Inhalt angezeigt. Der neue Programmierer versteht möglicherweise nicht, warum er dort ist oder woher er kommt, aber da er das "Richtige" zur "richtigen Zeit" aufzeichnet, kann er die Tatsache, dass er dort ist, einfach glücklich akzeptieren und zu etwas anderem übergehen .

Eine gute Verwendung von AOP in meinem Beispiel wäre also, immer zu protokollieren, wenn ein Wert über eine festgelegte Methode aktualisiert wurde. Dies erzeugt kein Anti-Pattern und ist kaum die Ursache für ein Problem.

Man könnte sagen, wenn Sie AOP leicht missbrauchen können, um so viele Probleme zu verursachen, ist es eine schlechte Idee, alles zu verwenden. Welche Technologie kann jedoch nicht missbraucht werden? Sie können die Datenkapselung missbrauchen, Sie können die Vererbung missbrauchen. So gut wie jede nützliche Programmiertechnologie kann missbraucht werden. Stellen Sie sich eine so eingeschränkte Programmiersprache vor, dass sie nur Funktionen enthält, die nicht missbraucht werden können. Eine Sprache, in der Features nur so verwendet werden können, wie sie ursprünglich verwendet werden sollten. Eine solche Sprache wäre so begrenzt, dass es fraglich ist, ob sie überhaupt für die Programmierung in der realen Welt verwendet werden kann.

302
Mecki

OOP und AOP schließen sich nicht aus. AOP kann eine gute Ergänzung zu OOP sein. AOP ist besonders praktisch, um Methoden Standardcode wie Protokollierung, Leistungsüberwachung usw. hinzuzufügen, ohne den Methodencode mit diesem Standardcode zu verstopfen.

27
norbertB

aspektorientierte Programmierung bietet eine gute Möglichkeit, übergreifende Aspekte wie Protokollierung und Sicherheit zu implementieren. Diese Querschnittsthemen sind Teile der Logik, die an vielen Stellen angewendet werden müssen, aber eigentlich nichts mit der Geschäftslogik zu tun haben.

Sie sollten AOP nicht als Ersatz für OOP sehen, sondern eher als nettes Add-On, das Ihren Code sauberer, lose gekoppelter und auf die Geschäftslogik fokussierter macht. Wenn Sie AOP anwenden, erhalten Sie zwei wesentliche Vorteile:

  1. Die Logik für jedes Anliegen befindet sich jetzt an einem Ort und ist nicht mehr über die gesamte Codebasis verteilt.

  2. klassen sind übersichtlicher, da sie nur Code für ihr Hauptanliegen (oder ihre Kernfunktionalität) enthalten und sekundäre Anliegen auf Aspekte verschoben wurden.

27
nkr1pt

Ich denke, es gibt keine generelle Antwort auf diese Frage, aber eines ist zu beachten: AOP ersetzt nicht OOP = fügt aber bestimmte Zerlegungsmerkmale hinzu, die die sogenannte Tyrannei der dominanten Komposition ansprechen ( 1 ) (oder übergreifende Bedenken) .

In bestimmten Fällen ist dies sicherlich hilfreich, solange Sie die Kontrolle über die für ein bestimmtes Projekt verwendeten Tools und Sprachen haben. Gleichzeitig wird die Komplexität hinsichtlich der Interaktion der Aspekte und des Bedarfs an zusätzlichen Tools wie AJDT um dein Programm noch zu verstehen.

Gregor Kiczales hat einmal einen interessanten Einführungsvortrag zu AOP bei Google Tech Talks gehalten, den ich empfehlen möchte: Aspektorientierte Programmierung: Radikale Forschung in Modularität .

10
fhe

Erstens wird AOP OOP nicht ersetzen. AOP erweitert OOP. Die Ideen und Praktiken von OOP bleiben relevant. Ein gutes Objektdesign wird es wahrscheinlich einfacher machen, es mit Aspekten zu erweitern.

Ich denke, die Ideen, die AOP mitbringt, sind wichtig. Wir müssen Möglichkeiten ausarbeiten, um übergreifende Belange für verschiedene Klassen in Ihrem Programm zu implementieren, ohne die Klassen selbst ändern zu müssen. Aber ich denke, das AOP wird irgendwann nur noch Teil anderer Tools, die wir verwenden, und nicht mehr eines separaten Tools oder einer separaten Technik. Wir sehen dies bereits.

Einige dynamische Sprachen wie Ruby und Python) haben Sprachkonstrukte wie Mixins, die die gleichen Probleme lösen. Dies ähnelt AOP, ist aber besser in das Sprache.

Spring and Castle und einige andere Frameworks zur Abhängigkeitsinjektion bieten Optionen, um den Klassen, die sie injizieren, Verhalten hinzuzufügen. Dies ist eine Möglichkeit, das Runtime-Weben durchzuführen, und ich denke, das hat viel Potenzial.

Ich glaube nicht, dass Sie ein völlig neues Paradigma erlernen müssen, um AOP zu verwenden. Die Ideen sind interessant, werden aber langsam von vorhandenen Tools und Sprachen aufgegriffen. Bleiben Sie einfach auf dem Laufenden und probieren Sie diese Tools aus.

8
Mendelt

Ich bin spät dran, um diese Frage zu beantworten, aber sie ist eines meiner Lieblingsthemen. Lassen Sie mich meine Ansicht teilen.

[~ # ~] oop [~ # ~] wird hauptsächlich zum Organisieren Ihrer Geschäftslogik verwendet while [~ # ~] aop [~ # ~] hilft Ihnen dabei, Ihre nicht funktionale Dinge wie Auditing, Logging, Transaction Management, Sicherheit etc

Auf diese Weise können Sie Ihre Geschäftslogik mit einer nicht fiktiven Logik entkoppeln, die den Code übersichtlicher macht.

Ein weiterer Vorteil ist, dass Sie die Empfehlungen (Beispielprüfung) sehr konsequent anwenden können, ohne eine Schnittstelle zu implementieren, die eine große Flexibilität für Änderungen bietet, ohne die Geschäftslogik zu berühren

1
Gaurang Popat

AOP ist ein neues Programmierparadigma, das sich mit diesem Konzept befasst. Ein Aspekt ist eine Software-Entität, die einen bestimmten nicht funktionalen Teil der Anwendung implementiert.

Ich halte diesen Artikel für einen guten Einstieg in die aspektorientierte Programmierung: http://www.jaftalks.com/wp/index.php/introduction-to-aspect-oriented-programming/

1
JafTalks