Grundlagen aspektorientierter Programmierung

Avatar von Diana Hartmann

Aspektorientierte Programmierung – schonmal gehört? Was jedem Java-Entwickler schon lange ein Begriff ist, zieht in die PHP-Welt nur langsam ein. Mit TYPO3 Flow kam 2011 das vielleicht erste PHP-Framework heraus, das dieses Programmierparadigma unterstützt. Aber was genau versteht man darunter? Wikipedias einleitende Begriffsdefinition lautet folgendermaßen:

“Aspektorientierte Programmierung (AOP) ist ein Programmierparadigma für die objektorientierte Programmierung, um generische Funktionalitäten über mehrere Klassen hinweg zu verwenden (Cross-Cutting Concern).”

 

Das ist nun erst einmal sehr allgemein gehalten. Deshalb stellt sich die Frage: Wie kann man AOP am besten greifen? Das möchte ich versuchen mit dem vorliegenden Artikel zu beantworten.

Wozu AOP?

Zunächst einmal stellt sich die Frage, wozu man aspektorientierte Programmierung überhaupt braucht. Es gibt zum Beispiel bei der Programmierung einer Anwendung immer wieder Stellen an denen man bestimmte, nicht zur eigentlichen Programmlogik gehörende, wiederkehrende Funktionalitäten braucht. Ein Klassiker hierfür ist das Logging, wie etwa zum Mitprotokollieren von Fehlern und anderer Daten. Dieses wird an vielen Stellen immer wieder eingebunden und durchsetzt den Code damit mit “unnötigem”, nicht direkt zur Funktionalität gehörendem Code, was zu schlechterer Lesbarkeit der eigentlichen Anwendung führt. Deshalb werden derartige Anforderungen als cross-cutting concerns bezeichnet, weil sie die Kernfunktionalität durchschneiden. (Im Gegensatz hierzu nennt man die Module der Kernfunktionalitäten core concerns.)
Weitere Beispiele für solche – nicht die eigentliche Kernfunktionalität betreffenden – Anforderungen sind Sicherheit, Authentisierung, Tracing und Profiling.
Die modulare Implementierung solcher cross-cutting concerns macht die aspektorientierte Programmierung aus und die Module werden Aspekte (aspects) genannt. Diese werden zur Laufzeit hinzugefügt.

Das ABC der aspektorientierten Programmierung

Da man im Zusammenhang mit AOP immer wieder mit einer Menge von Fachausdrücken konfrontiert wird, hier ein kurzer Überblick mit den Begriffsklärungen wichtiger Buzzwords:

Target
Zielklasse, in der die Verwendung von Aspekten benötigt wird.

Join Point
Ein Punkt bei der Programmausführung an dem man eine bestimmte Methode eines Aspekts ausführen möchte. Join Points sind implizit vor jeder Methode vorhanden.

Advice
Methode in einem Aspekt, die an einem oder mehreren Join Points mit in den Programmablauf eingebunden wird.

Pointcut
Ein Ausdruck zur Auswahl von Join Points.

Pointcut expression
Schreibweise eines Pointcuts, mit Hilfe der Pointcut Expression Language (PEL).

Introduction
Durch eine Introduction kann man eine Zielklasse um zusätzliche Interfaces und deren Methoden als auch Eigenschaften erweitern, ohne den Code der Zielklasse selbst anpassen zu müssen.

Einbindung von Advices

Ein Advice kann auf verschiedenste Art aufgerufen werden:

  • vor der Zielmethode (before).
  • nach der Zielmethode (after). Dieser Aufruf erfolgt auf jeden Fall, egal ob eine Exception geworfen wurde oder die Methode erfolgreich war.
  • nach der Zielmethode, wenn diese erfolgreich und ohne Exception beendet wurde (after returning). Der zurückgegebene Wert kann vom Advice gelesen, jedoch nicht verändert werden.
  • nach der Zielmethode, wenn diese eine Exception geworfen hat (after throwing).
  • vor und nach der Zielmethode (around), wenn Logik vor und nach der Zielmethode ausgeführt werden muss. Hierbei kann auch der Rückgabewert verändert werden!
  • statt der Zielmethode, indem diese unterdrückt wird.

Es gibt also viele einfache Möglichkeiten Advices einzubauen. Es sollte jedoch darauf geachtet werden, dass immer die einfachst mögliche Einbindung erfolgt, um die Komplexität nicht unnötig zu erhöhen.

Ein kleiner Vorgeschmack

Um nicht ganz ohne Praxisbezug zu enden, hier nur ein ganz kleiner Ausblick wie so etwas aussehen kann:

  • ohne AOP
namespace Path\To\Package\Blog\Domain\Model;

class Blog {

    /**
     * @var \Path\To\Package\Blog\Logger
     */
    protected $logger;

    /**
     * Create a blog entry with logging
     *
     * @param \Path\To\Package\Blog\Domain\Model\Entry $entry
     *
     * @return void
     */
    public function createEntry(Entry $entry) {

        $this->entries->create($entry);
        $this->logger->log('Created entry ' . $entry->getId(), LOG_INFO);
    }

    /**
     * Delete a blog entry with logging
     *
     * @param \Path\To\Package\Blog\Domain\Model\Entry $entry
     *
     * @return void
     */
    public function deleteEntry(Entry $entry) {

        $this->logger->log('Deleted entry ' . $entry->getId(), LOG_INFO);
        $this->entries->delete($entry);
    }

}
  •  mit AOP (Hier fällt das gesamte Logging heraus und es bleibt die eigentliche Business Logik.)
namespace Path\To\Package\Blog\Domain\Model;

class Blog {

    /**
     * Create a blog entry
     *
     * @param \Path\To\Package\Blog\Domain\Model\Entry $entry
     *
     * @return void
     */
    public function createEntry(Entry $entry) {
        $this->entries->create($entry);
    }

    /**
     * Delete a blog entry
     *
     * @param \Path\To\Package\Blog\Domain\Model\Entry $entry
     *
     * @return void
     */
    public function deleteEntry(Entry $entry) {
        $this->entries->delete($entry);
    }

}

Stattdessen gibt es das Logging schön gekapselt in einer Aspektklasse, wie etwa hier (mit TYPO3 Flow) umgesetzt. Hierbei ist beispielhaft ein Advice before und ein Advice after umgesetzt (siehe Zeilen 31 und 17).

namespace Path\To\Package\Blog\Logging;

/**
 * @Flow\Aspect
 */
class LoggingAspect {

    /**
     * @var \Path\To\Package\Blog\Logger
     */
    protected $logger;

    /**
     * Do logging after an entry is created
     *     
     * @param \TYPO3\Flow\AOP\JoinPointInterface $joinPoint
     * @Flow\After("method(Path\To\Package\Blog\Domain\Model\Blog->createEntry())")
     *
     * @return void
     */
    public function logEntryCreated(\TYPO3\Flow\AOP\JoinPointInterface $joinPoint) {

        $entry = $joinPoint->getMethodArgument('entry');
        $this->logger->log('Created entry ' . $entry->getId(), LOG_INFO);
    }

    /**
     * Do logging before an entry is deleted
     *     
     * @param \TYPO3\Flow\AOP\JoinPointInterface $joinPoint
     * @Flow\Before("method(Path\To\Package\Blog\Domain\Model\Blog->deleteEntry())")
     *
     * @return void
     */
    public function logEntryDeleted(\TYPO3\Flow\AOP\JoinPointInterface $joinPoint) {

        $entry = $joinPoint->getMethodArgument('entry');
        $this->logger->log('Deleted entry ' . $entry->getId(), LOG_INFO);
    }
}

 

Vor- und Nachteile von AOP

Das schöne bei der aspektorientierten Programmierung ist, dass man – unter Berücksichtigung entsprechender Syntax – einfach und schnell Aspekte einbauen und auch wieder ausbauen kann. Beim Profiling zum Beispiel, bei dem etwa Ausführungszeiten einzelner Methoden zum Debugging gemessen werden können, ist das eine prima Sache. Vor allem können die Stellen über die Pointcuts ganz schnell angepasst, vergröbert oder verfeinert werden. Der Einsatz kann simpel auf ganze Packages ausgeweitet oder bis auf einzelne Methoden in bestimmten Klassen heruntergebrochen werden. Ebenso schnell kann die Funktionalität anschließend auch wieder ausgebaut werden!
Allerdings muss man, wenn man AOP anwenden möchte, meiner Meinung nach genau verstanden haben was das ist, wozu es da ist und demnach genau wissen was man tut! Denn sonst kann man auch schnell den Überblick verlieren! Abhängigkeiten sind schwerer aufzuspüren, da sie nicht direkt im Code erkennbar sind, was ein Debugging sehr erschweren kann. Ebenso können Seiteneffekte, wie unerwünschte Wechselwirkungen zwischen verschiedenen Aspekten, auftreten.

Deshalb hoffe ich dass dieser Artikel für den einen oder anderen ein bisschen mehr Klarheit schaffen konnte in Bezug auf das was und wozu der Aspektorientierten Programmierung.
In einem zukünftigen Blogartikel möchte ich darauf eingehen was TYPO3 Flow für die aspektorientierte Programmierung mitbringt und wie man sie dort genau einsetzt.

Quellen/Links:

http://de.wikipedia.org/wiki/Aspektorientierte_Programmierung
http://t3n.de/magazin/aspektorientierte-programmierung-flow3-enterprise-feature-221181/
http://www.binaris-informatik.de/?p=628

Avatar von Diana Hartmann

Kommentare

Eine Antwort zu „Grundlagen aspektorientierter Programmierung“

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert


Für das Handling unseres Newsletters nutzen wir den Dienst HubSpot. Mehr Informationen, insbesondere auch zu Deinem Widerrufsrecht, kannst Du jederzeit unserer Datenschutzerklärung entnehmen.