
Konzept zum Verwalten von Konfigurationsinformationen

Das Modul "Conf.pm" lst das allgemeine Problem, dass Programme in
der Regel Konstanten (Zahlen, Dateinamen, Zeichenketten, usw.)
bentigen, die von Installation zu Installation oder sogar von
Aufruf zu Aufruf variieren knnen und deshalb nicht im Programm
selbst "hart verdrahtet" werden drfen.

Zudem gibt es einerseits oft Einstellungen, die projektweit (oder
fr ein Teilprojekt) gltig sind, und andererseits aber auch
solche, die jeder Benutzer individuell festlegen knnen muss.

Auch kann es in diesem Zusammenhang sehr praktisch und
arbeitssparend sein, projektweite Default-Einstellungen
anzubieten, die bei Bedarf vom Benutzer durch eigene Einstellungen
"berstimmt" werden knnen.

bliche Lsungen fr dieses Problem durchsuchen z.B. eine (fest
vorgegebene) Liste von Dateien in verschiedenen Verzeichnissen,
wobei die erste gefundene (d.h. existierende) Datei aus dieser
Liste dann zur Initialisierung des jeweiligen Programms verwendet
wird. Dies ist das Standard-Vorgehen der meisten Unix-Tools, die
jeweils nach einer (oder mehreren verschiedenen) sogenannten
"rc"-Datei(en) zuerst im Home-Verzeichnis des Benutzers und dann
an einer zentralen Stelle (z.B. im Verzeichnis "/etc") suchen.

Manchmal wird nicht ausschliesslich die erste der gefundenen
Dateien verwendet, sondern alle gefundenen Dateien, wobei die
Einstellungen in den zuerst gefundenen Dateien gewhnlich Vorrang
gegenber den spter gefundenen Dateien haben.

Das problematische an diesem Ansatz ist, dass die Liste der zu
durchsuchenden Verzeichnisse dabei im wesentlichen im Programm
festgelegt, also "hart verdrahtet" ist.

Ausserdem lassen sich so in der Regel nur individuelle und globale
Einstellungen vornehmen, eine feinere Abstufung und Unterteilung
in Projekte und Teilprojekte (mit jeweils eigenen
Default-Einstellungen) ist normalerweise nicht mglich, oder wenn
doch, ist die Anzahl der Hierarchie-Stufen und Gruppierungen in
der Regel fest vorgegeben (fest verdrahtet).

Alternativ knnte man natrlich eine Liste von Benutzern und
Gruppen in einer zentralen Konfigurationsdatei ablegen, aber dann
bentigt man einen Administrator, der diese Benutzer- und
Gruppenlisten pflegt. Es wre nicht von vorneherein mglich, dass
sich jede Gruppe (d.h. jedes Teilprojekt) ihre eigenen
Konfigurationsdateien selbst erstellt, ohne dass dies zentral
irgendwo festgehalten und "freigeschaltet" werden muss.

Im folgenden Bild wird ein solcher konventioneller Ansatz
dargestellt:

  [Abbildung 1]  (= "Bild1.jpg")

Das vorliegende Modul "Conf.pm" beseitigt alle diese
Einschrnkungen, indem es einem anderen, neuen und in gewisser
Weise entgegengesetzten, Ansatz folgt. Statt "Top Down" von einer
zentralen Liste von Benutzern und Gruppenzugehrigkeiten
auszugehen, wird vielmehr "Bottom Up" von den
Benutzer-spezifischen zu den Gruppen- und Teilprojekt-spezifischen
zu den globalen Einstellungen vorangeschritten:

Anstatt also zentral eine Liste von Benutzern und
Gruppenzugehrigkeiten pflegen zu mssen, gibt es bei diesem Modul
nur eine (in der Regel minimale) "Anker"-Datei, die an einer
festen Stelle im Dateisystem stehen muss (dies ist jedoch die
einzige fest verdrahtete Konstante des ganzen Moduls!), und in der
generisch per Konfiguration festgelegt wird, wie die
Benutzer-spezifischen Konfigurationsdateien heissen und wo sie
liegen (dazu kann auf Umgebungsvariablen wie z.B. das
Home-Verzeichnis und Login-Krzel des Aufrufers zurckgegriffen
werden).

Diese "Anker"-Datei heisst fr das vorliegende Modul "Conf.ini"
und muss im selben Verzeichnis liegen wie das (installierte!)
Modul "Conf.pm" selbst. Durch eine Installation der Tools und
Module mit Hilfe des Standard-Installationsverfahrens fr
Perl-Module (perl Makefile.PL; make; make test; make install) kann
dies automatisch sichergestellt werden.

Nach dem Einlesen der Benutzer-spezifischen Konfigurationsdatei
des Aufrufers springt das Modul "Conf.pm" anschliessend in eine
weitere Konfigurationsdatei, deren Name und Pfad in der
Benutzer-spezifischen Konfigurationsdatei des Aufrufers angegeben
sein muss (falls diese Angabe fehlt, ist das Einlesen der
Konfigurationsinformationen nach dem Einlesen der
Benutzer-spezifischen Konfigurationsdatei beendet). Dies ist in
der Regel die Konfigurationsdatei mit den Default-Einstellungen
einer bergeordneten Organisationseinheit, also z.B. einer
Arbeitsgruppe oder eines Teilprojekts, oder auch nur eine Datei
mit allen globalen Einstellungen. Es knnte sich aber zum Beispiel
auch um eine Konfigurationsdatei mit maschinenabhngigen
Einstellungen handeln, d.h. es ist mglich, Benutzer-spezifische
Einstellungen von maschinenabhngigen Einstellungen zu trennen, so
dass z.B. jeder Benutzer an jedem beliebigen Rechner ber seine
individuellen Einstellungen verfgt, maschinenabhngige
Einstellungen (wie z.B. IP-Adressen o..) jedoch immer automatisch
richtig nur fr den jeweiligen Rechner vorgenommen werden.

Jede Konfigurationsdatei kann dabei festlegen, in welche andere
Konfigurationsdatei als nchstes gesprungen werden soll. Fehlt
diese Angabe, ist die Kette der einzulesenden
Konfigurationsdateien zuende. Da jeder Benutzer bzw. jede Gruppe
die jeweils eigene(n) Konfigurationsdatei(en) editieren
darf/drfen, kann jeder Benutzer selbst festlegen, zu welcher
Gruppe er gehrt (das ist wichtig, wenn er z.B. in mehreren
Teilprojekten arbeitet!), und jede Arbeitsgruppe (oder jedes
Teilprojekt) kann ihrerseits beliebige weitere Unterteilungen in
Teilgruppen vornehmen, jederzeit (ohne Wartezeiten auf eine
Zentraladministration) und ganz nach den jeweiligen
Erfordernissen. Das bedeutet auch, dass die Anzahl der
Hierarchiestufen nicht von vornherein festgelegt ist, dass die
Anzahl der Hierarchiestufen fr unterschiedliche Teilprojekte oder
-gruppen unterschiedlich sein kann und dass diese Anzahl jederzeit
(je nach den Erfordernissen der Projektorganisation) verndert
werden kann mit anderen Worten, jedes hierarchische Organigramm
kann jederzeit in der Struktur der entsprechenden
Konfigurationsdateien abgebildet werden.

Das folgende Bild illustriert diese Vorgehensweise:

  [Abbildung 2]  (= "Bild2.jpg")

Beim Einlesen der Konfigurationsdaten nach diesem Verfahren gilt:
Zuerst eingelesene Konstanten haben Vorrang gegenber spter
eingelesenen.

Dies fhrt zu dem blichen und intuitiv erwarteten Verhalten, dass
Benutzer globale Einstellungen "berschreiben" knnen.

Dies ist jedoch nur die halbe Wahrheit. Tatschlich ist es so,
dass aufgrund dieser Regel alle Einstellungen in der "Anker"-Datei
fr alle Werkzeuge und alle Teilprojekte verbindlich sind, whrend
alle Einstellungen aus der Datei mit den "globalen Einstellungen"
optionale, d.h. unverbindliche Defaults darstellen.

Dies bietet sogar noch grssere Flexibilitt gegenber
konventionellen Methoden zur Behandlung von
Konfigurationsinformationen, da sowohl verbindliche als auch
unverbindliche Defaults festgelegt werden knnen.

Im obigen Bild werden darber hinaus auch noch zwei weitere
wesentliche Features des "Conf.pm"-Moduls gezeigt:

Zum einen ist es mglich, fr unterschiedliche "Stze" von
Werkzeugen, nennen wir sie knftig "Werkzeugksten", vollkommen
unterschiedliche und voneinander vllig unabhngige Ketten von
Konfigurationsdateien zu haben. Solche "Werkzeugksten" knnten
z.B. verschiede Erzeugnisklassen sein, oder verschiedene
Entwicklungsumgebungen, o..

Die Zugehrigkeit eines Werkzeugs zu einem bestimmten
Werkzeugkasten (im folgenden "scope" genannt) kann dabei z.B.
durch eine "package"-Deklaration am Anfang des Skripts automatisch
gesteuert werden. Ein expliziter Aufruf mit der bergabe des
gewnschten "scope" als Parameter ist natrlich auch realisierbar.

Zum anderen ist es mglich, sensible personenbezogene Daten in
eigene Dateien auszulagern, die durch Mittel des Betriebssystems
so geschtzt werden knnen, dass sie nur vom jeweiligen Benutzer
gelesen und beschrieben werden knnen.

Diese mssen stets am Ende der Kette von einzulesenden
Konfigurationsdateien stehen. Dies hngt damit zusammen, dass es
mglich sein muss, die wesentlichen Konfigurationsinformationen
auch eines vom Aufrufer des Tools verschiedenen Benutzers
einzulesen (wichtig z.B. fr den Betreuer der Tools, wenn er
Fehler in der Konfiguration eines Benutzers aufspren soll und
sich diese daher auflisten lassen knnen muss, oder zur Ausfhrung
von Tools unter der Kennung eines "Projekt-Users"). Gleichzeitig
drfen aber die Dateien mit den sensiblen Daten fr andere
Benutzer nicht lesbar sein ein Versuch sie trotzdem zu lesen
fhrt zu einem Fehler des Betriebssystems. Das Modul "Conf.pm"
geht nun so vor, dass es bei den speziellen "privaten"
Konfigurationsdateien diesen Fehler einfach ignoriert. Da das aber
dazu fhrt, dass die Angabe, welche Konfigurationsdatei als
nchstes eingelesen werden soll, nicht ausgewertet werden kann,
die Kette der Konfigurationsdateien an dieser Stelle also
abbricht, muss die "private" Konfigurationsdatei stets die letzte
Datei der Kette sein. Damit das Modul "Conf.pm" einen Lesefehler
ignoriert, muss der Name der entsprechenden speziellen
Konfigurationsdatei mit "PRIVAT.ini" oder "PRIVATE.ini" aufhren.

Ein weiteres Feature des "Conf.pm"-Moduls, das bisher noch
gnzlich unerwhnt geblieben ist, ist die Mglichkeit, innerhalb
der Definition einer Konfigurationskonstanten auf andere
Konfigurationskonstanten zuzugreifen (was auch als
"String-Interpolation" bezeichnet wird), und zwar vllig
unabhngig davon, ob die referenzierte Konfigurationskonstante in
derselben Datei definiert ist oder in einer anderen Datei, und
unabhngig davon, ob es sich um eine Konfigurationsdatei handelt,
die vor oder nach der aktuellen Konfigurationsdatei eingelesen
wird.

Dies wird dadurch ermglicht, dass zuerst alle
Konfigurationsdateien eingelesen werden, bevor irgendwelche
Definitionen von Konfigurationskonstanten ausgewertet werden (mit
Ausnahme der Verweise auf die jeweils nchste einzulesende
Konfigurationsdatei in der Kette). Tatschlich ist es sogar so,
dass jede Konfigurationskonstante erst dann ausgewertet (und ab
diesem Zeitpunkt in einem Cache gepuffert) wird, wenn sie
tatschlich angefordert wird (dies wird als "Lazy Evaluation"
bezeichnet), d.h. Konfigurationskonstanten, die vom Programm nicht
bentigt werden, mssen auch nicht ausgewertet werden, was zu
einer deutlichen Performance-Steigerung fhrt.

Diese String-Interpolation benutzt dabei eine Syntax, die stark an
Shell- und Perl-Programme angelehnt ist (whrend der Aufbau der
Dateien selbst von Windows inspiriert ist):

    [DEFAULT]
    # $[SPECIAL]{OS} enthlt den Namen des aktuellen Betriebssystems:
    Home-Dir     = $[$[SPECIAL]{OS}]{Home-Dir}
    Group-Dir    = $[$[SPECIAL]{OS}]{Group-Dir}
    Group-User   = $[$[SPECIAL]{OS}]{Group-User}
    TEMPDIRPATH  = $[$[SPECIAL]{OS}]{TEMPDIRPATH}
    LOGFILEPATH  = ${Group-Dir}/Tools/Logfiles
    CONFIGPATH   = ${Group-Dir}/Tools/Config
    GLOBALCONF   = ${CONFIGPATH}/Global/DEFAULT.ini

    [MSWin32]
    Home-Dir     = U:
    Group-Dir    = G:
    Group-User   = Administrator
    TEMPDIRPATH  = C:/Temp

    [freebsd]
    Base-Dir     = /u
    Home-Dir     = $[UNIX]{Home-Dir}
    Group-Dir    = $[UNIX]{Group-Dir}
    Group-User   = projadmin
    TEMPDIRPATH  = /tmp

    [UNIX]
    # Die folgende Zeile holt das Home-Dir des aktuellen Benutzers aus /etc/passwd:
    Home-Dir     = $[SPECIAL]{HOME}
    Group-Dir    = $[$[SPECIAL]{OS}]{Base-Dir}/$[$[SPECIAL]{OS}]{Group-User}

    [Manager]
    GROUPCONF    = $[DEFAULT]{CONFIGPATH}/Group/GROUP.ini
    NEXTCONF     = $[DEFAULT]{Home-Dir}/Config/USER.ini

Zustzlich zur String-Interpolation besteht ausserdem die
Mglichkeit zur sogenannten "Indirektion", d.h. eine
Konfigurationskonstante kann ihrerseits den symbolischen Namen
einer anderen Konfigurationskonstanten (oder einer
"Section"-berschrift) enthalten, deren Inhalt dann (per
String-Interpolation) eingefgt werden soll.

Hinweis: Der Inhalt der Konfigurationsdateien lsst sich ganz
wie bei "INI"-Dateien unter Windows mit Hilfe von "Section"-
(also "Kapitel"-) berschriften in virtuelle Abschnitte einteilen.
Virtuell deshalb, weil dieselbe "Section"-berschrift mehrmals
vorkommen darf sowohl in derselben Konfigurationsdatei als auch
in verschiedenen Konfigurationsdateien. Die Gesamtheit aller
Eintrge, die zur selben "Section"-berschrift gehren, bildet
dann zusammengenommen den virtuellen Abschnitt. Die Verwendung von
"Section"-berschriften ist jedoch keineswegs verpflichtend, und
alle Eintrge ohne vorherige "Section"-berschrift gehren
automatisch zum Abschnitt "DEFAULT". Doppelte Eintrge im selben
virtuellen Abschnitt (nicht notwendigerweise jedoch "physikalisch"
unterhalb derselben "Section"-berschrift, d.h. innerhalb
desselben Blocks) innerhalb derselben Konfigurationsdatei sind
brigens verboten (jedoch nicht in unterschiedlichen
Konfigurationsdateien, denn ein Benutzer muss ja z.B. globale
Defaults "berschreiben" knnen).

Zusammen mit gewissen eingebauten Spezial-Variablen sowie der
Mglichkeit des Zugriffs auf smtliche Umgebungsvariablen lassen
sich mit Hilfe der String-Interpolation und der Indirektion z.B.
betriebssystemabhngige Einstellungen ohne Programmierung, allein
durch Konfiguration, vor dem Werkzeug "verbergen". Auch ist es auf
diese Weise beispielsweise mglich, von "dem" Benutzerpasswort fr
"das" Server-Account zu sprechen (und es auch so zu verwenden),
unabhngig davon, um welchen von mehreren Servern es sich gerade
handelt, bzw. welche Zielumgebung gerade eingestellt ist.

D.h. mit anderen Worten, dem Programm bleibt es erspart, zuerst in
der Konfiguration nachzusehen, welche Zielumgebung eingestellt
ist, um daraufhin (abhngig von der eingestellten Umgebung) sich
das Login und Benutzerpasswort des Aufrufers fr diese Umgebung
herauszusuchen. Dies lagert einen bedeutenden (und immer
wiederkehrenden, aber nie identischen) Teil der Programmierung in
eine einfache, leicht zu handhabende Konfigurationssyntax aus, und
hilft so einen erheblichen Programmieraufwand einzusparen.

Nhere Details zur genauen Syntax und den Spezial- und
Umgebungsvariablen sind in der Man-Page dieses Moduls (die mit
Hilfe von "perldoc" angezeigt werden kann, unter Unix auch mittels
"man") zu finden.

Mit Hilfe eines weiteren Moduls ("Base.pm") besteht ausserdem die
Mglichkeit, einzelnen Konfigurationskonstanten ber die
Kommandozeile (fr die Dauer des jeweiligen Tool-Aufrufs) einen
anderen Wert zuzuweisen. Vereinzelt sind im Modul "Base.pm" zu
diesem Zweck fr manche, hufig bentigte Konfigurationskonstanten
auch besonders handliche Abkrzungen definiert. In einigen Fllen
gibt es zudem die Mglichkeit, bestimmte Konfigurationskonstanten
per Umgebungsvariable zu berschreiben (genaueres hierzu ist in
der Man-Page dieses Moduls nachzulesen).

Aufgrund des Caching-Mechanismus bleiben Konfigurationskonstanten,
die von einer per Kommandozeile oder Umgebungsvariable temporr
berschriebenen Konfigurationskonstanten abhngen, aber schon zur
Startup-Zeit des Programms bentigt und daher ausgewertet wurden
(z.B. Name und Pfad einer Log-Datei), von solchen nderungen
unberhrt, d.h. die Reihenfolge der Auswertung (Anforderung) von
Konfigurationskonstanten ist im Zusammenhang mit nderungen ber
die Kommandozeile oder Umgebungsvariablen von Bedeutung (whrend
das bei "normalen" Konfigurationskonstanten keine Rolle spielt).

