Begriffe der Aspektorientierten Programmierung

Die Begriffe der Aspektorientierte Programmierung

Das AOP-Konzept wurde in einem vorherigen Artikel vorgestellt. Darin wurden Aspekte an Hand von Querschnittsfunktionen eingeführt, die auf Schnittstellen-Ebene vorhandene Implementierungen erweitern. AOP verfeinert dieses Vorgehen jedoch noch deutlich. Die zum detaillierten Verständnis notwendigen Begriffe der Aspektorientierten Programmierung werden im Folgenden definiert.

Joinpoints

Ein Joinpoint ist eine identifizierbare Stelle innerhalb eines compilierten Programms. Prinzipiell ist damit jegliche native Bytecode-Anweisung ein Joinpoint. AOP schränkt diese Möglichkeiten jedoch drastisch ein und definiert als mögliche Joinpoints Funktionsaufrufe (call), Funktionsausführungen (execution), aber auch eine Zugriffe auf Attribute einer Datenstruktur (get, set), Exception Handler (handler) oder Konstruktoraufrufe. Schleifen oder Abfragen sind zwar auch „identifizierbare Stellen“, werden aber von AOP nicht unterstützt. Es fällt auch schwer, für Kontrollstrukturen allgemeine Aspekte zu finden.

Zwei Hinweise seien hier noch gegeben:

  • Joinpoints werden in der Literatur auch als „primitive Pointcuts“ bezeichnet.
  • Ein „Jointpoint“ wie der Münchner Monopteros ist natürlich etwas vollkommen anderes. Allerdings liefert eine Recherche nach den Begriffen „AOP + Jointpoint“ erfreulich viele Treffer…

Pointcuts

Ein Pointcut ist eine logische Oder-Verknüpfung einzelner Joinpoints. Um die Formulierung von Pointcuts zu erleichtern verwendet AOP eine Selektionssprache mit Jokerzeichen. So könnte beispielsweise ein Pointcut definieren, dass alle Funktionen find* selektiert werden sollen.

Advices

Ein Advice ist die eigentliche Aspekt-Logik von Anweisungen, die an einem Pointcut ausgeführt werden soll. Advices können vor (before), nach (after) sowie den Pointcut klammernd (around) ausgeführt werden.

Aspect

Ein Aspect schließlich dient als Klammerung für einen Pointcut und einen Advice.

Arbeitsweise eines AOP-Frameworks

Mit diesen Begriffen kann die Arbeitsweise eines AOP-Frameworks folgendermaßen beschrieben werden:

  1.  Ausgangspunkt ist der Bytecode der Anwendung. Dieser enthält keine Aspekt-Logik.
  2. Der im Aspekt definierte Pointcut selektiert im Bytecode die Stellen der Anwendung, an denen das Framework die Aspekt-Logik hinzufügen soll.
  3. An Hand der gegebenen Aspekt-Logik wird Bytecode generiert und nach den Regeln des Advices an die selektierten Pointcuts „eingewebt“. Damit wird effektiv die Aspekt-Logik an verschiedene Stellen dupliziert eingetragen. Dies ist jedoch keine unzulässige Code-Replikation, der Quellcode der Anwendung bleibt „sauber“.

Dieser Ablauf muss selbstverständlich bei jeder Änderung und Compilierung der Sourcen wiederholt werden. Diese erreicht man durch eine Integration des Frameworks in eine Entwicklungumgebung oder einen automatisierten Buildprozess.

Realisierung von Aspekten

Mit den eben definierten Begriffen ist es möglich, Aspekte abstrakt zu definieren. Für die konkrete Umsetzung muss die verwendete Plattform Werkzeuge und Verfahren zur Verfügung stellen. Dies ist in dynamischen Skript-Sprachen wie JavaScript oder Ruby trivial. Komplizierter wird es in statisch typisierten Sprachen wie Java. Dies wird im dritten Teil dieser Serie behandelt.

Seminare zum Thema

Weiterlesen

Aspektorientierte Programmierung

Grundlagen der Aspektorientierten Programmierung

Aspektorientierte Programmierung (AOP) wird in praktisch allen modernen Software-Projekten eingesetzt. Grundelement dieses Ansatzes ist der Aspekt, welcher eine Querschnittsfunktion, englisch: ein Cross-cutting concern, realisiert. Querschnittsfunktionen werden im Modell der Anwendung dadurch erkannt, dass Schnittstellen-übergreifende gemeinsame Abläufe identifiziert werden. Diese gemeinsamen Sequenzen sollen nun aber natürlich nicht durch Code-Replikation umgesetzt werden; dies würde ja zu schlecht wartbaren Anwendungen führen. AOP vermeidet diese Duplikation und steigert damit die Qualität des Codes.

Beispiele für Aspekte sind schnell gefunden:

  • Authentifizierung und Autorisierung von Geschäftsprozessen
  • Deklarative Transaktionssteuerung beispielsweise in einem Applikationsserver
  • Tracing und Profiling
  • Kapselung des Netzwerk-Protokolls bei Remote-Zugriffen

Im Folgenden wird an einem einfachen Beispiel erläutert, wie Aspekte in eigenen Anwendungen identifiziert werden können.

Identifikation von Aspekten

Ausgangspunkt ist eine sehr einfache Anwendung, bei der einem Actor eine Service-Implementierung zur Verfügung gestellt wird. Hier benutzt das Rechnungswesen (Accounting) einen InvoiceService:

Der Invoice-Service

Nun wird die fachliche Anforderung erweitert: Sämtliche Aufrufe des InvoiceService sollen in einer Audit-Datei gespeichert werden. Darin enthalten sind beispielsweise Informationen über den Zeitpunkt des Aufrufs sowie die aufgerufene Funktion. Nachdem es sicherlich nicht sinnvoll ist, diese Zusatz-Funktion innerhalb der Implementierung zu realisieren (das Programm wird sonst sehr schnell unangenehm groß) ist eine naheliegende Lösung eine Vererbung:

Auditing mit Vererbung

Diese Lösung wird funktionieren, ist aber auf Dauer nicht wirklich stabil, da eine Vererbungshierarchie nur statisch ist. Besser ist ein Baukastensystem durch eine Dekoration:

Auditing mit Decorator

Das obige Klassendiagramm ist zwar formal korrekt, jedoch wenig einprägsam: Eigentlich erfolgt die Dekoration der Implementierung für den Actor, deshalb wird im nächsten Diagramm der AuditingInvoiceDecorator an die Assoziation zwischen Actor und Implementierung gehängt:

Der Decorator als Assoziationsklasse

Selbstverständlich können nun auch noch weitere Funktionalität dazu dekoriert werden:

Weitere Decorators

Und genauso selbstverständlich kann ein anderer Actor (Mahnungswesen, Dunning) den InvoiceService mit einem anderen Satz von Decorators benutzen:

Ein zweiter Actor für den InvoiceService

Dieses Modell der Anwendung ist übersichtlich und aussagekräftig. Allerdings ist noch kein Aspekt erkennbar. Dazu führen wir noch eine zweite Anwendung hinzu, Ordering:

Ordering: Ein zweiter Service

Dieser kann selbstverständlich auch wieder dekoriert werden:

Der zweite Service wird ebenfalls dekoriert

Nun kommt der entscheidende Schritt: Die Audit-Funktionalität soll auch dem OrderService hinzugefügt werden. Damit haben wir nun ein Modell, in dem ein Decorator an zwei Assoziationen zu unterschiedlichen Interfaces hängt. Und damit wird der Decorator zum Aspekt!

Der Auditing Aspekt

Formulierung von Aspekten

Die Identifikation von Aspekten in einem Klassendiagramm ist einfach. Allerdings müssen diese natürlich auch noch konkret formuliert werden. Dazu müssen einige neue Begriffe definiert werden. Dies wird im zweiten Teil dieser Serie behandelt.

Seminare zum Thema

Weiterlesen