Diese Frage ist zwar sehr interessant, aber ohne weitere Details wohl kaum zu beantworten. Um welche Art von Anwendung handelt es sich? Hat sie eine grafische Benutzeroberfläche? Ist es ein Befehlszeilentool? Eine Reihe von Skripten? Ein Programm mit einem eindeutigen Einstiegspunkt, usw...
Angesichts der wenigen Informationen, die mir vorliegen, werde ich sehr allgemein antworten.
Welche Mittel müssen Sie einsetzen, um Plugins hinzuzufügen?
- Wahrscheinlich müssen Sie eine Konfigurationsdatei hinzufügen, in der die zu ladenden Pfade/Verzeichnisse aufgeführt sind.
- Eine andere Möglichkeit wäre, zu sagen "alle Dateien in diesem Plugin/Verzeichnis werden geladen", aber das hat den Nachteil, dass die Benutzer Dateien verschieben müssen.
- Eine letzte Zwischenlösung wäre, dass alle Plugins im gleichen Plugin/Ordner liegen müssen und dann über relative Pfade in einer Konfigurationsdatei aktiviert/deaktiviert werden.
In der reinen Code-/Design-Praxis müssen Sie eindeutig festlegen, welches Verhalten bzw. welche spezifischen Aktionen Ihre Benutzer ausführen sollen. Bestimmen Sie den gemeinsamen Einstiegspunkt bzw. eine Reihe von Funktionen, die immer überschrieben werden sollen, und legen Sie Gruppen innerhalb dieser Aktionen fest. Sobald dies geschehen ist, sollte es einfach sein, Ihre Anwendung zu erweitern,
Beispiel mit Häkchen Die Sprache ist von MediaWiki inspiriert (PHP, aber ist die Sprache wirklich wichtig?):
import hooks
# In your core code, on key points, you allow user to run actions:
def compute(...):
try:
hooks.runHook(hooks.registered.beforeCompute)
except hooks.hookException:
print('Error while executing plugin')
# [compute main code] ...
try:
hooks.runHook(hooks.registered.afterCompute)
except hooks.hookException:
print('Error while executing plugin')
# The idea is to insert possibilities for users to extend the behavior
# where it matters.
# If you need to, pass context parameters to runHook. Remember that
# runHook can be defined as a runHook(*args, **kwargs) function, not
# requiring you to define a common interface for *all* hooks. Quite flexible :)
# --------------------
# And in the plugin code:
# [...] plugin magic
def doStuff():
# ....
# and register the functionalities in hooks
# doStuff will be called at the end of each core.compute() call
hooks.registered.afterCompute.append(doStuff)
Ein weiteres Beispiel, inspiriert von mercurial. Hier fügen die Erweiterungen nur Befehle zum hg Kommandozeilenprogramm, das das Verhalten erweitert.
def doStuff(ui, repo, *args, **kwargs):
# when called, a extension function always receives:
# * an ui object (user interface, prints, warnings, etc)
# * a repository object (main object from which most operations are doable)
# * command-line arguments that were not used by the core program
doMoreMagicStuff()
obj = maybeCreateSomeObjects()
# each extension defines a commands dictionary in the main extension file
commands = { 'newcommand': doStuff }
Für beide Ansätze benötigen Sie möglicherweise gemeinsame initialisieren y finalisieren für Ihre Erweiterung. Sie können entweder eine gemeinsame Schnittstelle verwenden, die alle Ihre Erweiterungen implementieren müssen (passt besser zum zweiten Ansatz; Mercurial verwendet ein reposetup(ui, repo), das für alle Erweiterungen aufgerufen wird), oder einen hakenartigen Ansatz mit einem hooks.setup-Haken verwenden.
Aber auch hier gilt: Wenn du brauchbare Antworten willst, musst du deine Frage eingrenzen ;)