Lade...
 

Extern

Extern

Signatur
Extern(name, File(fileName) [, overwrites(overName)] [, triggeredBy(msg1, msg2, ..., msgn)] [, provides(provider_tag) ]) [: inheritName]
Parameter
Parameter Beschreibung
name Modulname
overName Name eines Moduls, das bereits per Extern-Statement deklariert wurde,
und dessen Extern-Statement nun überschrieben werden soll. (s.u.)
fileName Name des nachzuladenden Files
msg1 Message löst Nachladen aus
. . . . . .
msgn Message löst Nachladen aus
provider_tag Modul exportiert Procedures
inheritName Name des Moduls, von dem geerbt wird

Mit Extern wird ein Modul deklariert, dessen vollständige Definition in einer anderen Datei liegt. Diese soll erst dann geladen werden (Lazy Loading), wenn
- eine der triggeredBy() Messages gesendet wurde. Die Message erreicht natürlich auch noch das neu geladene Modul (siehe Beispiel)
- eine exportierte Procedure über ein Provider Tag aufgerufen wird.

Wenn das nachzuladende Modul von einem anderen Modul abgeleitet ist, bestehen folgende Möglichkeiten:

  • Alt: Ableitung und Basismodul sind im gleichen Source-File definiert bzw. mit #include-Anweisungen wird dafür gesorgt, dass sie zusammen nachgeladen werden.
  • Neu: Auch die Vererbungsrelation wird mit Anweisung Extern beschrieben, sodass InstantView® die benötigten Basismodule automatisch nachladen kann. Diese Vorgehensweise ist besser, da sie flexibler ist, da die Vererbungshierarhie über die Extern()-Anweisungen einfach an zentraler Stelle geändert werden kann.

Die Extern-Anweisungen für letzteren Fall:

  Extern(name, File(fileName1), triggeredBy(msg1, msg2, ..., msgn)) : baseModName
  Extern(baseModName, File(fileName2))

// oder

  Extern(baseModName, File(fileName2))
  Extern(name, File(fileName1), triggeredBy(msg1, msg2, ..., msgn)) : baseModName

Achtung: Für Basis-Module darf keine Liste auslösender Messages (triggeredBy) angegeben werden, dies ist ein Fehler, denn das System müsste dann versuchen ein Basismodul zu öffnen, was nicht erlaubt ist, solange ein anderes Modul davon abgeleitet ist.

Es gibt keine zwingend vorgegebene Reihenfolge der Extern-Anweisungen: Die externe Deklaration eines Basismoduls darf auch nach der Extern-Anweisung für die abgeleiteten Module erscheinen, da die Module erst dann aufgelöst werden, wenn der Parser das tatsächliche Modul (Module(...)) parsed und nachdem die .ext-Datei vollständig geparsed wurde (falls sie per --extern_file angegeben wurde). Spätestens dann müssen die Basismodule auch alle bekannt sein.

Extern Deklarationen sind das Hilfsmittel, um Anwendungen aus vorgefertigten Modulen des AppsWarehouse® zusammenzustellen!

Was zu einer bestimmten Anwendung A gehört, wird durch eine Folge von Extern-Anweisungen definiert.
Eine kundenspezifische Variante von A = Anwendung A' würde durch eine andere Folge von Extern-Anweisungen beschrieben, die sich nur an wenigen Stellen unterscheidet.
Statt die Extern-Definitionen für die Kunden-Variante A' ganz neu zu schreiben, kann die Definition für A benutzt und ergänzt werden.
Zwei Features unterstützen diese Möglichkeit:

- Die Extern-Anweisungen bestimmen die Modulhierarchie. Sobald für ein Modul eine Extern()-Anweisung existiert, gilt die Angabe des Basismoduls innerhalb der Moduldatei (Module(...) : ...) nicht mehr. Damit kann mittels Extern-Anweisung die Ableitungsfolge beliebig modifiziert werden. (Zyklen sind nicht erlaubt)
- Vorher deklarierte Extern-Statements können mit overwrites umdefiniert werden.
 

Parameter overwrites - detaillierte Beschreibung

Der Parameter overwrites() hat unterschiedliche Bedeutung, je nachdem, ob das eigene Modul überschrieben wird, oder ein anderes Modul.

Code-Beispiel:

Extern(a, File(a.mod), triggeredBy(LIST_A), provides(a)) // 1. Remove provides(a), change file and add SELECT_A as trigger Extern(a, File(a2.mod), overwrites(a), triggeredBy(LIST_A, SELECT_A)) // 2. Insert new base module for a Extern(base, File(base.mod)) Extern(a, File(a3.mod), overwrites(a), triggeredBy(LIST_A), provides(a)) : base // 3. Module b takes over the LIST_A trigger and is the new provider for (a) Extern(b, File(b.mod), overwrites(a), triggeredBy(LIST_A), provides(a)) // 4. Disable module b by removing the trigger message and provider role Extern(b, File(b.mod), overwrites(b)) // 5. Restore old inheritance with no base module and readd the LIST_A trigger Extern(a, File(a.mod), triggeredBy(LIST_A), overwrites(a)) // 6. Just for demonstration: overwrite would remove the LIST_A trigger from a // even though c doesn't define the trigger Extern(c, File(c.mod), overwrites(a))

 

Immer dann, wenn eine zweite Extern()-Anweisung für ein Modul geschrieben wird, dann muss diese auch ein overwrites() für dieses Modul enthalten, ansonsten wird dies als Fehler erkannt, damit nicht versehentlich Module überschrieben werden. Ein Extern(a, overwrites(a), ...) wird als Fehler erkannt, falls es vorher keine Extern(a, ...)-Anweisung gibt.

Innerhalb eines Extern(a, overwrites(a), ...) müssen alle Angaben der Extern()-Anweisung wiederholt werden, die für das Modul gelten sollen. Extern() arbeitet hier nicht additiv. Extern(a, overwrites(a), ...) löscht effektiv die vorherige Extern()-Definition für a. Dadurch ist es auch möglich, das Basismodul für a zu ändern oder ganz zu entfernen. Dieser Mechanismus wird auch verwendet, um Module zu "deaktivieren", indem kein triggeredBy und kein provides angegeben wird, ist das Modul von außen nicht mehr erreichbar (außer durch Vererbung).

Extern(a, overwrites(b), ...) hat eine andere Semantik, denn hier ist die Absicht des Entwicklers, mit dem Modul a die Aufgaben von Modul b zu übernehmen. Hierzu wird das Modul b nicht gänzlich durch ersetzt, damit Module, die vorher von b abgeleitet waren, das auch nach wie vor sind. Stattdessen werden alle triggeredBy()-Messages und die provides()-Angabe aus Modul b entfernt. Gibt Modul nun die gleichen triggeredBy()-Messages an und das gleiche provides(), dann wird nun überall, wo vorher eine Message oder ein Provideraufruf Modul b geliefert hat, nun Modul geliefert.

Da nur eine overwrites()-Angabe pro Extern()-Anweisung erlaubt ist, können die beiden Verhaltensweisen aktuell nicht kombiniert werden.

 

Mit diesem Mechanismus wird das Zusammenstellen größerer Anwendungen erleichtert (siehe Beispiel). Damit können an beliebiger Stelle innerhalb einer vorgegebenen Modulhierarchie eigene Module eingefügt und Module ausgetauscht werden.

Das in der overwrites()-Klasuel angegebene Modul darf noch nicht geladen sein.