Dieser Beitrag zeigt, wie man mit clever platzierten Python Event-Hooks beliebigen Code in Subklassen ausführen kann, ohne die Eltern-Klasse zu modifizieren.
Was sind Event-Hooks?
Event Hooks erlauben das Ausführen von Code wenn bestimmte Ereignisse stattfinden. Der Code wird über einen Hook in der Elternklasse in das Ereignis “eingehakt”. Andere Begriffe hierfür sind Method-Overriding oder Polymorphie.
Ich nutze diese Technik, z.B. bei Woo2LX, wenn ein Kunde ein individuelle Anpassungen der Schnittstelle möchte:
Für den Kunden wird dann eine eigene Subklasse erzeugt, welche die Individualprogrammierung über Hooks implementiert. Die Subklasse wird dann über die Lizenz des Kunden aktiviert.
Python: Die Vorteile von Hooks
- Geschützter Programm-Kern: Die betreffenden Elternklassen werden niemals modifiziert. Fehler im Kern sind ausgeschlossen.
- Geschützter Custom-Code: Wird doch mal was an der Eltern-Klasse geändert, betrifft das in der Regel nicht den Code in den Hooks, denn die Events laufen getrennt von der eigentlichen Verarbeitung.
- Übersichtlicher Custom-Code: Alle individuellen Anpassungen befinden sich in einer einzigen, dem Kunden zugeordneten Subklasse. Kollisionen zwischen Anpassungen sind ausgeschlossen.
- Einfaches Debugging: Hat sich im Custom-Code ein Fehler eingeschlichen, beschränkt sich das Debugging auf die Subklasse.
- Nur ein einziger Installer: Alle Modifikationen aller Kunden befinden sich im gleichen Installationspaket. Es entsteht kein Mehraufwand für viele individuelle Installer.
Python Event-Hooks: Ein Beispiel
Event-Hooks sind in Python sehr einfach zu implementieren. Hier ein Beispiel für die Elternklasse:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class Woo2LX: ... def processOrder(self, orderID): self.onBeforeProcessOrder(orderID) # Hier findet die eigentliche Verarbeitung statt: ... self.onAfterProcessOrder(orderID) def onBeforeProcessOrder(self, orderID): pass def onAfterProcessOrder(self, orderID): pass ... |
- Die Funktion processOrder() verarbeitet die Bestellung mit der ID “orderID”.
- Bevor es jedoch losgeht, wird die Funktion onBeforeProcessOrder() aufgerufen.
- Am Ende der Verarbeitung wird onAfterProcessOrder() aufgerufen.
Wir haben also 2 Events, einen vor der Verarbeitung und einen am Ende. Die beiden Funktionen, in die bei den Events verzweigt wird, sind leer (pass). Es handelt sich hierbei um die eigentlichen EventHooks.
Die Subklasse sieht dann wie folgt aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class CustomCode(Woo2LX): def __init__(self): super().__init__() ... def onBeforeProcessOrder(self, orderID): # Kundenspezifischer Code hier: ... def onAfterProcessOrder(self, orderID): # Kundenspezifischer Code hier: ... |
Die Klasse CustomCode erbt alles aus der Klasse Woo2LX, außer den beiden Hooks, welche durch die individuellen Anpassungen überschrieben werden.
So bleiben die individuellen Anpassungen alle schön in einer einzigen Klasse und der Programmkern bleibt geschützt.
Die Technik lässt sich auf jede objektorientierte Sprache anwenden.
Daten über Hooks durchreichen
Auch das Durchreichen von Daten kann je nach Situation Sinn machen. In dem Fall sieht der Hook in der Elternklasse so aus:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
class Parent: ... def process(self, data): data = self.onBeforeProcessData(data) # Eigentliche Verarbeitung hier: ... def onBeforeProcessData(self, data): return data ... |
Der Hook ist nicht leer, sondern gibt die Daten an die aufrufende Funktion zurück.
Die Subklasse schaut dann so aus:
1 2 3 4 5 6 7 8 9 |
class Subclass(Parent): def __init__(self): super().__init__() ... def onBeforeProcessData(self, data): # Kundenspezifischer Code hier: ... return(data) |
Diese Technik erlaubt das Modifizieren der Daten über eine Subklasse. Danach gelangt das Datenpaket wieder in den Programmfluss des Eltern-Objekts.