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
:
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:
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:
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:
Selbstverständlich können nun auch noch weitere Funktionalität dazu dekoriert werden:
Und genauso selbstverständlich kann ein anderer Actor (Mahnungswesen, Dunning) den InvoiceService
mit einem anderen Satz von Decorators benutzen:
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:
Dieser kann selbstverständlich auch wieder dekoriert werden:
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!
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.