Exploring PHP

Ereignisgesteuerte Programmierung in PHP
Kommentare

Nicht nur die Programmiersprache PHP selbst entwickelt sich ständig weiter, sondern auch die Applikationen, die mit PHP entwickelt werden, werden immer komplexer und unternehmenskritischer. Enterprise-Anwendungen haben andere Anforderungen an die Architektur der Software als ein Gästebuch oder ein einfaches Content-Management-System. Anwendungen, die in unternehmenskritischen Bereichen eingesetzt werden, müssen einigen Kriterien standhalten. Natürlich muss sichergestellt werden, dass die Software keine Fehler enthält. Weiterhin muss die Anwendung leicht um neue Funktionen erweitert werden können, um bei veränderten Anforderungen kurze Reaktionszeiten sicherzustellen. Um Fehler, die durch Änderungen an bestehendem Code entstehen, zu vermeiden, sollte dieser so wenig wie möglich verändert werden müssen. Änderungen, die dies verursachen, können die verschiedensten Bereiche der Software betreffen und zum Beispiel durch die Anbindungen neuer Schnittstellen oder zusätzlicher Prüfungen von Daten nötig werden.

Mit der prozeduralen Art der Programmierung, wie sie in vielen PHP-4-Anwendungen angetroffen wird, sind solche Anforderungen nicht abzudecken, weshalb derart komplexe Applikationen immer mit Hilfe von Klassen und Objekten entworfen und umgesetzt werden sollten. Dank des überarbeiteten Objektmodells in PHP 5 können nun in PHP endlich auch ähnliche Architekturen, wie man sie zum Beispiel aus der Java-Welt kennt, verwendet werden. Aber nur alleine durch den Einsatz von Interfaces, Klassen und Objekten ensteht noch keine flexible Architektur, die den Anforderungen der Enterprise-Welt genügt. Auch mit objektorientierten Mitteln können starre Applikationen entworfen werden, die es nicht erlauben, einzelne Komponenten zu modifizieren oder gar auszutauschen. Klassische Entwurfsmuster wie Fabriken, Dekorierer oder Adapter versuchen deshalb Software-Entwicklern Lösungen für flexible Architekturen anzubieten. Diese konzentrieren sich jedoch immer nur auf Teile der Anwendung, anstatt die Applikation als Ganzes zu betrachten. Ereignis- oder Eventgesteuerte Programmierung geht hier einen Schritt weiter und gibt der Applikation einen Rahmen, in den die verschiedenen Komponenten integriert werden können. Auf den folgenden Seiten werden Sie das Konzept der eventgesteuerten Software-Entwicklung kennen lernen und dieses in PHP umsetzen.

Eventgesteuerte Programmierung vs. feste Kopplung der Komponenten

Bei der herkömmlichen Art der Programmierung stehen Aktion und Reaktion in festem Zusammenhang. Eine Aktion wird meistens durch den Benutzer der Website ausgelöst und Ihre PHP-Anwendung reagiert darauf. Die beiden Aktionen sind über in PHP implementierte Programmlogik fest miteinander verknüpft, wozu in den meisten Fällen if/else– oder switch/case-Konstrukte verwendet werden. Um nun die Reaktion der Applikation zu verändern, müssen Sie den Code innerhalb der if/else-Blöcke verändern oder sogar neue Blöcke hinzufügen. Stellen Sie sich zum Beispiel vor, Sie implementieren eine Benutzerauthentifizierung für eine Website. Dabei werden im HTTP-Request der Name sowie das Passwort des Benutzers, der sich anmelden möchte, an Ihre Anwendung übertragen. Diese versucht dann die beiden Parameter mit den Kundendaten, die zum Beispiel in einer Datenbank gespeichert sind, zu vergleichen. Stimmen die Daten überein, so ist der Kunde authentifiziert und kann die Applikation verwenden, wurde das Passwort falsch übergeben, so zeigen Sie dem Kunden eine Fehlermeldung an. Auf dem klassischen Weg haben Sie diesen Code sicher schon in mehreren Anwendungen implementiert. Was aber nun, wenn eine neue Anforderung besagt, dass bei Fehlversuchen ein Log geschrieben werden soll, um später analysieren zu können, ob jemand versucht, unberechtigten Zugriff auf Ihre Anwendung zu erhalten? In diesem Fall würden Sie sicher einfach in dem Block der if/else-Anweisung, der ausgeführt  wird, wenn die Daten nicht übereinstimmen, den zusätzlichen Code einfügen, der den Logeintrag erzeugt. Sie müssen also funktionierenden Code erneut anpassen, was zu Fehlern führen kann. Eine Woche später stellen Ihre Auftraggeber fest, dass sie auch gerne eine Logdatei mit den erfolgreichen Logins hätten, um eine Verteilung der erfolgreichen zu erfolglosen Versuchen erstellen zu können. Diese Funktion integrieren Sie auf dieselbe Art und Weise und schon wieder müssen Sie funktionierenden Quellcode verändern. Dieser Kreislauf könnte immer so weiter gehen, denn Ihre Auftraggeber könnten noch weitere Anforderungen an das System haben, wie zum Beispiel:
  • Bei erfolgreichem Login soll ein Cookie gesetzt werden, mit dem der Kunde bei einem späteren Besuch erkannt werden kann.
  • Von jeder IP-Adresse sollen innerhalb von 10 Minuten nur drei erfolglose Login-Versuche erlaubt werden.
  • Es soll möglich sein, für ausgewählte Kunden den Login komplett zu sperren.
Jede dieser Anforderungen zieht Änderungen an bestehendem Code nach sich, was jedes Mal dazu führt, dass die Applikation komplett getestet werden muss. Weiterhin wird der Login-Code immer weiter wachsen und die einzelnen Anforderungen verschmelzen langsam zu einer großen Methode. Wenn zu einem späteren Zeitpunkt eine Funktionalität nicht mehr benötigt wird, so müssen Sie erneut den existierenden Quellcode verändern und alle Zeilen und Anweisungen entfernen, die für die nicht mehr benötigte Funktionalität zuständig wären. Eine schönere Lösung wäre es, die einzelnen Anforderungen als kleine Komponenten zu implementieren, die einfach an die Basisfunktionalität angehängt werden können. Bei der Basisfunktionalität handelt es sich nur um die Möglichkeit, eingegebene Daten aus dem Request zu extrahieren und diese mit gespeicherten Benutzerdaten zu vergleichen. Die zusätzlichen Funktionalitäten werden dann nur noch darüber informiert, ob der Login erfolgreich war oder nicht.

Das Subject/Observer-Pattern

Wenn Sie bereits schon einmal mit dem Subject/Observer-Pattern gearbeitet haben, so kommt Ihnen dieser Wunsch vielleicht bekannt vor. Bei diesem Entwurfsmuster übernimmt ein Objekt die Rolle des Subjekts und steht im Zentrum des Interesses. An diesem Objekt können sich weitere Objekte als so genannte Observer registrieren. Ändert sich der Status des Subjektes, so informiert dies alle Observer über den neuen Status. Für die Login-Funktionalität bedeutet dies, dass die Klasse, die sich um die eigentliche Authentifizierung kümmert, als Subjekt agiert, das nur drei Stati kennt: keine Authentifizierung versucht, Authentifizierung erfolgreich und Authentifizierung fehlgeschlagen. Die Observer sind dann die neuen zusätzlichen Funktionen wie das Schreiben der Log-Dateien. Sobald nun ein Login-Versuch durchgeführt wurde, ändert sich der Status des Authentifizierungs-Objektes und es informiert die weiteren Funktionen über den erfolgreichen oder erfolglosen Login-Versuch. Abbildung 1 zeigt den vereinfachten Aufbau der Applikation.
Abb. 1: Architektur auf Basis des Subject/Observer-Musters

Abb. 1: Architektur auf Basis des Subject/Observer-Musters

 
Das Subject/Observer-Pattern hat allerdings zwei Nachteile:
Streng genommen ist die Kommunikation einseitig gedacht, d.h. das Subjekt informiert die Observer, diese sollen den Status des Subjektes nicht verändern. Diese Funktion wird allerdings benötigt, um den Login zu verbieten, wenn der Benutzer auf der Blacklist steht und der Login für ihn komplett verboten ist. Das Subject/Observer-Pattern setzt wie die meisten Entwurfsmuster darauf, dass die beteiligten Klassen bestimmte Interfaces implementieren oder von einer Basisklasse abgeleitet werden. Das Subjekt muss dabei Methoden liefern, mit denen sich die einzelnen Observer registrieren können, die eigentlich nicht Teil der zur Authentifizierung benötigten Funktionalität darstellen. Die Standard PHP Library bietet für das Subject/Observer-Pattern bereits Interfaces mit an, die Sie implementieren müssten. Dieses Entwurfsmuster wäre also bereits ein Ansatz, um eine flexiblere Lösung zu erarbeiten, hat jedoch auch Nachteile, die Sie nach Möglichkeit nicht in Kauf nehmen möchten Weiter mit: Teil 2 Alle Teile: Teil 1, Teil 2, Teil 3
Unsere Redaktion empfiehlt:

Relevante Beiträge

Meinungen zu diesem Beitrag

X
- Gib Deinen Standort ein -
- or -