Ereignis (Programmierung)

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche

Ein Ereignis (engl. event) dient in der Softwaretechnik – bei Entwicklung nach dem ereignisorientieren Programmierparadigma – zur Steuerung des Programmflusses. Das Programm wird nicht linear durchlaufen, sondern es werden spezielle Ereignisbehandlungsroutinen (engl. listener, observer, event handler) immer dann ausgeführt, wenn ein bestimmtes Ereignis auftritt. Ereignisorientierte Programmierung gehört zu den parallelen Programmiertechniken, hat also deren Vor- und Nachteile.

Motivation[Bearbeiten]

In Programmen ist ein häufiger Fall, dass auf Ressourcenanforderungen eine nicht-deterministische Zeit gewartet werden muss (z. B. bei Speicherallokierung oder Hardwarezugriff) oder Ereignisse spontan auftreten können (z.B. Benutzer-Mausklick). Letztendlicher Grund für diesen Nicht-Determinismus ist, dass diese Ereignisse nicht der Kontrolle des Programms unterliegen, also weder vom Programmierer noch vom Programm zur Laufzeit vorhergesagt werden können. Bei konventioneller Programmierung mit einem einzigen, sequentiellen Kontrollfluss wird dieses „Warten“ auf das Eintreten des Ereignis (z. B. die erfolgreiche Ressourcenzuweisung) über ein aktives, beobachtendes Warten, das sogenannte Polling, durchgeführt.

Polling besitzt einige nachteilige Eigenschaften: da die Programmausführung solange gestoppt ist, bis das Ereignis eintritt, ist die Programm-Leistungsfähigkeit schlechter und nicht-deterministisch. Auch kann auf andere Ereignisse gar nicht reagiert werden, d. h. diese gehen eventuell verloren. Auch ist die Effizienz von Polling schlecht, es wird wiederholt eine unnötige Handlung durchgeführt, die Prüfung, ob das Ereignis nun eingetreten ist.

Ereignisorientierte Programmierung[Bearbeiten]

Ein Ansatz, um diese Problemsituation effizienter zu lösen, ist die Ereignisorientierte Programmierung, die auf einer Inversion of Control basiert. D.h. es wird nicht mehr im Haupt-Kontrollfluss auf das Eintreten des Ereignis gewartet (der Hauptkontrollfluss hat die Kontrolle), sondern dem Ereignis wird ein eigener Kontrollfluss zugeordnet (häufig realisiert als Thread), der eigenständig beim Eintreten des Ereignisses aktiv wird und Einfluss auf den Hauptkontrollfluss nehmen kann. (siehe parallele Programmierung)

Technische Umsetzungen dieser Idee seit den 1960ern sind die Rückruffunktion (mit Event-spezifischem Unterprogramm) und (Hardware-)Interrupts, welche die Nachteile des Pollings vermeiden, dafür jedoch zwangsläufig die potentiellen Probleme des parallelen Programmierens hervorrufen.

Beschrieben werden können Ereignisbehandlungstechniken in Entwurfsmuster-Terminologie auch als Beobachter (Observer).

Verwendung[Bearbeiten]

Das Konzept der Ereignisorientierten Programmierung eignet sich auch gut zur Implementierung von grafischen Benutzeroberflächen, wobei hier die Ereignisse meist Aktionen des Benutzers sind, wie zum Beispiel das Drücken einer Taste oder das Anklicken einer Schaltfläche. Ein anderes wichtiges Anwendungsfeld sind Computersimulationen, die so aufgebaut werden, dass Zustandsänderungen nur von Ereignissen ausgelöst werden, und ihrerseits Ereignisse auslösen (siehe ereignisorientierte Simulation).

Ereignisorientierte Programmierung lässt sich gut mit den Konzepten der objektorientierten Programmierung (OOP) kombinieren: Objekte definieren dann nicht mehr nur Eigenschaften und Methoden, sondern sind auch Ereignisquellen und bieten die Möglichkeit, die Ereignisbehandlung zu beeinflussen. Auch die Ereignisbehandlungsroutinen (engl. event handler, eingedeutscht der Event-Handler, etwa „Ereignisverarbeiter“ oder „Ereignisbehandler“) und die Ereignisse selbst werden dann als Objekte modelliert. Es kann jedoch argumentiert werden, dass über die Idee des entkoppelten Messagings zwischen Objektentitäten, Ereignisorientierte Programmierung schon immer implizit ein Teilkonzept von OOP war.[1]

Ereignisse können je nach Programmierumgebung entweder nur eine Ereignisbehandlungsroutine (wie z. B. in Object Pascal) oder beliebig viele Ereignisbehandlungsroutinen (wie beim Signal-Slot-Konzept) aufrufen.

Es besteht die Möglichkeit, ein Ereignis als „verarbeitet“ zu kennzeichnen (consume). Nachfolgende Ereignisbehandler können dies abfragen und verzichten dann auf eine weitere Verarbeitung.

Beispiele[Bearbeiten]

Beispiel zu MS Access[Bearbeiten]

Der Benutzer kann u. a. Formulare und Berichte mit jeweils darin enthaltenen Feldern entwerfen. Zusätzlich gibt es 'Bereiche' wie Formularkopf, Berichtskopf, Gruppenkopf und Gruppenfuß (je Gruppenstufe) und Detailbereich, die selbst wiederum Einzelfelder enthalten. Alle diese Begriffe sind Objekte.

Die Verarbeitung für Objekte ist aufgeteilt in funktionale Teileinheiten, deren Ausführung vom Eintritt bestimmter Ereignisse („ereignisorientiert“) abhängig ist:

Definieren von Ereignissen in MS Access (2003)

In Formularen treten die Ereignisse im Wesentlichen durch Aktionen der Benutzeroberfläche auf: Mausaktionen, Eingaben etc. - die von der Access Engine erkannt und behandelt werden. Mögliche Ereignisse sind (zum Beispiel):

  • bei Formularen: Öffnen, Anzeigen, vor Eingabe, geändert, Löschen, Schließen ...
  • bei Formular-Eingabefeldern: wenn geändert, beim Berühren mit Mauszeiger, beim Klicken, beim Doppelklicken, bei Taste UP
  • bei Befehlsschaltflächen: beim Hingehen, beim Klicken, beim Doppelklicken

Bei Berichten initiiert die Engine die Ereignisse datenabhängig, ähnlich den Steuerungsprinzipien der normierten Programmierung. Mögliche Ereignisse sind (zum Beispiel):

  • für den ganzen Bericht: Beim Öffnen / Schließen, bei Seitenanfang, bei leeren Daten
  • für Berichtsbereiche wie Gruppenkopf und -fuß: beim Drucken, beim Formatieren

Zusätzlich zur Standardverarbeitung je Ereignistyp durch MS Access kann der Programmierer für jedes Objekt und für jeden Ereignistyp festlegen, ob etwas Individuelles zu tun ist – und was. Zum Beispiel kann nach dem Ändern eines Eingabefelds eine bestimmte Prüfung vorgenommen werden; beim Öffnen eines Berichts im Fall 'leerer Daten' kann ein Fehlerhinweis angezeigt werden; ein Gruppenfuß kann bei nur 1 Einzelzeile je Gruppe 'unsichtbar' gemacht werden; Datenfelder können sichtbar / unsichtbar gemacht oder mit bestimmten Inhalten ausgegeben werden.

Für solche Zusatzfunktionen legt der Programmierer, ggf. von einem Software-„Assistenten“ unterstützt, eine Prozedur an, in der für das jeweilige Objekt und den jeweiligen Ereignistyp ein passender Code (in VBA) hinterlegt wird; siehe Grafikbeispiel. Bei Eintreten des Ereignisses wird die entsprechende Prozedur ausgeführt. Ist keine Prozedur angelegt, wird das Ereignis in der definierten Grundform verarbeitet oder es erfolgt keine Verarbeitung (z. B. bei Berühren des Objekts mit dem Mauszeiger).

Implementierung eines Ereignissystems[Bearbeiten]

Der folgende Pseudocode soll eine einfache Implementierung eines Ereignissystems zeigen:

Function Event
  listener = []
  call = function()
    for each parallel (l in listener)
      l()

Anwendungsbeispiel:

Klick = new Event
Klick.listener.add(regenGeräusch)
Klick.listener.add(regenBild)
Klick()

Dieses einfache Ereignissystem bietet eine linear ablaufende Ereignisbehandlung und ermöglicht das An- und Abmelden von Ereignisbehandlungsroutinen. Für parallele Ausführung plant das W3C sogenannte Web Workers. Das dargestellte Ereignissystem kann wie folgt verwendet werden:

Formular = function() {
  this.abschicken = new Event();}
 
function zumServerSenden() {}
 
function DankeSagen() {
  alert("Vielen Dank für das Ausfüllen des Formulars.");
}
 
var umfrage=new Formular();
umfrage.abschicken.addListener(this, "zumServerSenden");
umfrage.abschicken.addListener(this, "DankeSagen");
umfrage.abschicken();

Siehe auch[Bearbeiten]

Einzelnachweise[Bearbeiten]

  1. Stefan Ram: Dr. Alan Kay on the Meaning of Object-Oriented Programming (englisch) fu-berlin.de. 23. Juli 2003. Abgerufen am 4. Juni 2012: „OOP to me means only messaging, local retention and protection and hiding of state-process, and extreme late-binding of all things.