Christian Kruse: Konfigurations- und Plugin-Konzept

Hallo zusammen,

ich schreibe gerade eine groessere Web-Applikation in C. Diese Applikation
besitzt ein recht umfangreiches Plugin-Konzept: ein Plugin (ein Filter) wird
durch ein "AddFilter" in der Konfiguration beim Startup geladen. Das Modul/der
Filter registriert dann seine Konfigurations-Direktiven im Konfigurations-Parser
und definiert, an welcher Stelle eine bestimmte Funktion aus dem Modul
ausgefuehrt werden soll.
Soweit, sogut
Jetzt muss die Applikation aber ueber ein Web-Interface konfigurierbar sein. Und
ich wuerde ungern das Konzept aufgeben und die Konfigurations-Direktiven alle
hart hineinkodieren, in das Konfigurations-Script. Wie also kann man sowas
moeglichst dynamisch gestalten?
Ein Ansatz, den ich angedacht habe, ist der, dass jedes Modul einen weiteren
"Konfigurations-Handler" enthaelt, dass entsprechend ein Template-Schnippsel
ausgibt und die CGI-Parameter, die es braucht, auswertet und einen String zurueck
gibt, der in die Konfigurations-Datei geschrieben wird. Aber irgendwie erscheint
mir das wenig praktikabel...

Was meint ihr dazu?

Gruesse,
 CK

  1. Hallo,

    Jetzt muss die Applikation aber ueber ein Web-Interface konfigurierbar sein. Und
    ich wuerde ungern das Konzept aufgeben und die Konfigurations-Direktiven alle
    hart hineinkodieren, in das Konfigurations-Script. Wie also kann man sowas
    moeglichst dynamisch gestalten?

    Und wenn Du für jedes Modul/Plugin/Filter eine Art DTD führst, welche beschreibt, welche Konfigurationsdirektiven wie behandelt werden? Bei der Registrierung wird diese Information dem Konfigurations-Parser zur Verfügung gestellt, womit auch gleich dieser die komplette Konfiguration validieren kann.

    Das Webinterface muß nun auch nur mehr in der Lage sein, diese Datei zu prüfen, und die entsprechenden Webseiten generieren.

    Grüße
      Klaus

    1. Hoi Klaus,

      Und wenn Du für jedes Modul/Plugin/Filter eine Art DTD führst, welche
      beschreibt, welche Konfigurationsdirektiven wie behandelt werden?

      Ich glaube, ich mache das so: jedes Modul/Plugin/Filter wird einen weiteren
      Handler definieren muessen, der nur eines macht: einen Pfad zu einer Datei
      zurueck geben, die genau definiert, welche Direktiven inwieweit konfigurierbar
      sind und welche Werte gueltig sind. Dann kann ich mehr oder weniger automatisch
      ein Formular daraus entwickeln und das ganze auch automatisch validieren lassen.
      Ich glaube, XML winkt :)

      Danke fuer dein Feedback.

      Gruesse,
       CK

      1. Hallo CK,

        Ich glaube, ich mache das so: jedes Modul/Plugin/Filter wird einen weiteren
        Handler definieren muessen, der nur eines macht: einen Pfad zu einer Datei
        zurueck geben, die genau definiert, welche Direktiven inwieweit konfigurierbar
        sind und welche Werte gueltig sind.

        Dabei sehe ich allerdings das Problem, daß das Modul wissen muß, wie es installiert wurde, bzw. wo die Datei liegen darf. D.h. wenn Du das nicht hart verdrahten willst, muß die Datei entweder an einen berechenbaren Ort sein oder es muß wieder eine Konfigurationsdatei her, die dem Modul sagt, wo die andere Datei liegt. Im ersten Fall könnte also auch die Hauptapplikation bzw. auch die Konfigurationsapplikation diesen Pfad berechnen, wodurch der Handler keine Notwendigkeit mehr hat. Und zweiterer Fall ist IMHO nicht gerade elegant, da das Problem ja nur verlagert wird.

        Ich würde die Direktiven-Informationen beim Registrieren der Applikation übergeben, wodurch diese sie dann an einen von der Applikation bestimmten Ort ablegt, dmait auch die Konfigurationsanwendung darauf zugreifen kann.

        Interessant wäre es m.E., wenn Du es schaffen würdest, die Plugins so zu schreiben, daß sie quasi selbstbeschreibend werden. Irgendwie muß ja das Plugin die für sie vorgesehenen Direktiven auch verarbeiten können. Dafür sind, so denke ich, interne Datenstrukturen notwendig, um die Einstellungen zur Laufzeit verfügbar zu halten. Was wenn diese Datenstrukturen so gestaltet sind, daß eine funktion deren möglichen Inhalt auslesen und in Form einer Direktiven-Definition ausgibt.

        Ich habe vor kurzem noch einen anderen Weg beschritten. Es ging dabei um eine Dateninterface für eine C++-Anwendung. Dafür habe ich die Datenstrukturbeschreibung (inklusive UI-Interface-Definition) in einer Konfigurationsdatei abgelegt, und dann mittels Perl-Script den notwendigen C++-Code generiert. Für das dann noch notwendige HTTP-Interface, über das die Daten Synchronisiert werden, wird die Konfigurationsdatei auch gleich mit verwendet.

        Ich glaube, XML winkt :)

        Wobei mir die Idee mit einer DTD für die Beschreibung der Direktiven recht gut gefällt. Und es hat ja keiner gesagt, dßa eine DTD nicht auch dynamisch generiert werden darf, oder?

        Daß sich dann für die Konfigurationsdirektiven XML praktisch aufdrängt, ist ja eine andere Geschichte.

        Viel Erfolg bei Deiner Anwendung
          Klaus

        1. Hallo Klaus,

          Im ersten Fall könnte also auch die
          Hauptapplikation bzw. auch die Konfigurationsapplikation diesen Pfad
          berechnen, wodurch der Handler keine Notwendigkeit mehr hat.

          Da hast du natuerlich recht :)

          Interessant wäre es m.E., wenn Du es schaffen würdest, die Plugins so zu
          schreiben, daß sie quasi selbstbeschreibend werden. Irgendwie muß ja das
          Plugin die für sie vorgesehenen Direktiven auch verarbeiten können. Dafür
          sind, so denke ich, interne Datenstrukturen notwendig, um die Einstellungen
          zur Laufzeit verfügbar zu halten. Was wenn diese Datenstrukturen so
          gestaltet sind, daß eine funktion deren möglichen Inhalt auslesen und in
          Form einer Direktiven-Definition ausgibt.

          Ich glaube, das waere etwas kompliziert. Nicht nur ich will ja Plugins
          schreiben, sondern auch fremde Leute. Und man muss die API ja auch verstehen
          und moeglichst einfach anwenden koennen.

          Ich habe vor kurzem noch einen anderen Weg beschritten. Es ging dabei um
          eine Dateninterface für eine C++-Anwendung. Dafür habe ich die
          Datenstrukturbeschreibung (inklusive UI-Interface-Definition) in einer
          Konfigurationsdatei abgelegt, und dann mittels Perl-Script den notwendigen
          C++-Code generiert. Für das dann noch notwendige HTTP-Interface, über das
          die Daten Synchronisiert werden, wird die Konfigurationsdatei auch gleich
          mit verwendet.

          Das kann ich so nicht machen. Ich muss Plugins registrieren koennen, ohne
          gleich die ganze Applikation neu zu uebersetzen. Sie hat eh schon etwa 10k
          Zeilen. Nein, ich denke, der Momentane Mechanismus ist ganz iO so, wie er ist.

          Ich glaube, XML winkt :)

          Wobei mir die Idee mit einer DTD für die Beschreibung der Direktiven recht
          gut gefällt. Und es hat ja keiner gesagt, dßa eine DTD nicht auch dynamisch
          generiert werden darf, oder?

          Oh, das muss sie gar nicht. Wenn ein Modul sich aendert, muss eben die
          XML-Datei geaendert werden.

          Daß sich dann für die Konfigurationsdirektiven XML praktisch aufdrängt, ist
          ja eine andere Geschichte.

          Fuer die Konfigurations-Direktiven benutze ich ein eigenes, Apache-aehnliches
          Format mit einem selbst geschriebenen Konfigurations-Parser :) Im Moment sieht
          eine typische "Beschreibungs-Datei" (wie koennte man sie sonst nennen?) so
          aus:

          <?xml version="1.0" encoding="iso-8859-1"?>
          <!DOCTYPE modcfg SYSTEM "modcfg.dtd">

          <modcfg name="modul_name">
            <directive name="Direktiven-Name" arguments="1"> <!-- mit arguments kann man die Anzahl der Argumente, die eine Direktive erwartet, festlegen -->
              <validate>^(?:yes|no)$</validate>  <!-- regex zum validieren der Eingabe -->
              <question>Frage</question> <!-- Das wird in der Datei gefragt -->
              <formvalues type="radio"> <!-- Im Formular eine Radio-Box -->
                <value val="yes">Geöffnet</value> <!-- mit den Werten 'Geöffnet' -->
                <value val="no">Geschlossen</value> <!-- und 'Geschlossen' -->
              </formvalues>
            </directive>
          </modcfg>

          Viel Erfolg bei Deiner Anwendung

          Danke sehr!

          Gruesse,
           CK