Hook (Informatik)
Hook (englisch für Haken, auch Einschubmethode genannt) bezeichnet in der Programmierung eine Schnittstelle, mit der fremder Programmcode in eine bestehende Anwendung integriert werden kann, um diese zu erweitern, deren Ablauf zu verändern oder um bestimmte Ereignisse abzufangen. Dies kann entweder im Quelltext geschehen, der entsprechend modifiziert wird, über Konfigurationsdateien, die den Ablauf eines fertigen Programms verändern, oder über Aufruf von Funktionen, denen der auszuführende Programmcode in irgendeiner Form mitgegeben wird. In der Regel ist das Standardverhalten von Einschubmethoden, gar nichts zu tun.[1]
Hooks können auch vom Betriebssystem zum Abfangen von Nachrichten zur Verfügung gestellt werden. Damit lassen sich z. B. systemweite Hotkeys implementieren. So können zum Beispiel über einen Hook die Tastatur-Nachrichten unabhängig von dem Programm, welches aktuell den Fokus hat, empfangen werden.
Implementierung
Es gibt mehrere Möglichkeiten, Hooks zu implementieren.
Wenn der Quelltext des zu erweiternden Programms vorliegt, lassen sich prinzipiell immer Erweiterungen vornehmen. Sofern der Code jedoch nicht genau bekannt ist, ist dieses aufwendig, weil diese Erweiterung eventuell umfangreiche Veränderungen erfordert, die obendrein unerwünschte Nebenwirkungen haben können und zudem mit jeder neuen Version neu eingepflegt werden müssten.
Daher definieren manche Programme bestimmte Stellen, die explizit dazu vorgesehen sind, von anderen erweitert zu werden. Dies kann dadurch geschehen, dass eine Funktion aufgerufen wird, die im ursprünglichen Programm leer implementiert ist, also nichts bewirkt. Diese kann dann gefahrlos auf eine fremdimplementierte Funktion umgelenkt werden. Die ursprünglich leere Funktion ist dann der Hook.
In der objektorientierten Programmierung geschieht dies durch Vererbung oder durch Delegation:
- Im Falle der Vererbung sind die Hooks leere Methoden, die in Unterklassen ausimplementiert werden können. Ein Beispiel ist das Entwurfsmuster der Schablonenmethode; hier werden mehrere Methoden hintereinander als Hooks aufgerufen, um Algorithmen mit festem Ablaufrahmen spezialisieren zu können.
- Im Falle der Delegation wird ein Hook in Form eines Objektes als Attribut an den Aufrufer übergeben. Dieses Objekt muss eine bestimmte Schnittstelle implementieren. Ein Beispiel stellt das Strategie-Entwurfsmuster dar. Wenn zu erwarten ist, dass der Hook von mehreren unterschiedlichen Dienstleistern genutzt werden wird, kann der Aufrufer den Hook in Form einer Liste anstelle eines einfachen Attributs implementieren, sodass mehrere Implementierungen des Hooks der Reihe nach aufgerufen werden können. Dieses geschieht zum Beispiel im Falle eines Listeners, um Benutzerinteraktionen abzufangen. Wenn die Liste nur soweit abgearbeitet wird, bis der erste implementierte Hook ein bestimmtes Ergebnis zurückliefert, hat man eine Zuständigkeitskette.
Betriebssystem-Hooks unter Windows werden in einer eigenen DLL implementiert, welche vom Betriebssystem ohne einen Programmkontext aufgerufen wird. Somit muss ein Programm, welches einen Hook (z. B. zur Benachrichtigung über ein Ereignis) implementiert, seine Ergebnisse über andere Mechanismen von dem in der DLL enthaltenen Code erfahren (z. B. mittels Interprozesskommunikation).
Konfiguration
Es bleibt die Frage, wie das aufrufende Programm Kenntnis von den Programmteilen erlangt, die die bereitgestellten Hooks nutzen wollen.
Im einfachsten Fall wird der Programmcode direkt verändert, um Zugriff auf die Hooks zu erlangen.
Oder es wird Programmcode über Konfigurationen eingebunden. Dies kann in der prozeduralen Programmierung über Funktionszeiger geschehen, indem eine aufzurufende Unterroutine mit ihrer Startadresse eingetragen wird. In der objektorientierten Programmierung wird dagegen eine Klasse über ihren Namen dynamisch geladen; diese Klasse implementiert dann als Unterklasse oder als Delegationsobjekt den vom Hook aufgerufenen Code. Wird Dependency Injection verwendet, so lassen sich hierüber ebenfalls einfach Hooks konfigurieren.
Eine dritte Möglichkeit besteht darin, ein Objekt oder eine Funktion, welche vom Hook aufgerufen werden soll, über eine Zugriffsfunktion zu setzen. Dies wird dann gemacht, wenn der Hook von einer Programmbibliothek bereitgestellt wird, das vom selben Programmteil verwendet wird, welches auch die Hooks nutzen wird. Genutzt wird das beispielsweise beim Listener für Benutzerinteraktionen, welcher oben bereits genannt wurde.
Siehe auch
Einzelnachweise
- Erich Gamma, Richard Helm, Ralph Johnson, John Vlissides: Entwurfsmuster. Addison-Wesley, München 2011, ISBN 978-3-8273-3043-7, S. 370 (Was ist eine Einschubmethode? „Einschubmethoden, die ein Defaultverhalten anbieten, das von Unterklassen bei Bedarf erweitert werden kann. Eine Einschubmethode macht oftmals per Default gar nichts.“ – englisch: Design Patterns. Übersetzt von Dirk Riehle).