-
GEBIET DER ERFINDUNG
-
Die Erfindung betrifft Quellcodegenerierung,
genauer gesagt Quellcode, der im Zusammenhang mit komponentenberuhender
Programmierung generiert wird. Insbesondere unter Verwendung eines
Satzes von Generierbefehlen und Parametern erzeugt der Generator
fast repetitiven und repetitiven Quellcode, der von einem Entwickler
gleich eingesetzt werden kann.
-
HINTERGRÜNDE DER
ERFINDUNG
-
Software-Entwicklungsverfahren haben
sich in den letzten Jahren durch den zunehmenden Einsatz von Objekt-orientierten
Modellen für
Programmierung, Projektmanagement und Systemintegration drastisch verändert.
-
Enterprise-Applikationen sind große, komplexe
Systeme, die abstrakte Geschäftspraktiken
in spezifische Prozesse und ereignisbestimmte Wechselwirkungen verwandeln.
Diese Applikationen bilden das Kernstück für die Methoden einer Organisation.
-
Firmen können diese "besten Praktiken"
auf eine verschiedene Art und Weise erfassen und destillieren. In
vielen Fällen
ist die Erzeugung von Benutzer-spezifischer Software für die ganze
Organisation sowohl unrentabel und übersteigt auch die Fähigkeiten
eines Unternehmens. Diese Unternehmen wenden sich daher an Lieferanten
für Enterprise-Applikationen-Software
als Lösungen.
Diese Systeme, die unter Bezeichnungen wie Enterprise Resource Planning
(ERP von Lieferanten wie Peoplesoft und SAP), Customer Relationship
Management (Vantive, Clarify, Siebel) und Professional Services
Automation (Niku, Visto) lieferbar sind, führen einfach ausgedruckt die
Geschäfte.
-
Aber jedes Unternehmen ist anders
und durch diese Unterschiede wird es wettbewerbsfähig. Um
ihre spezifischen Fahigkeiten in elektronische Verfahren zu verwandeln,
müssen
Firmen ihre Unternehmensanwendungen auf die Art und Weise zuschneiden,
in der sie arbeiten. Das bedeutet, Anpassen, Ändern und die Applikationen
im Laufe der Zeit wachsen lassen.
-
Eine Lösung in dieser Richtung ist
"Parametrisierung". Bei der Parametrisierung konfigurieren ausgebildete
ERP-Fachleute viele Parameter und Variable, um das Verhalten der
Applikation auf die Art des Geschäfts zuzuschneiden.
-
Eine zweite Lösung besteht aus der Änderung
existierender Enterprise-Applikationen, beruhend auf existierenden
generischen Applikationen und direktem Ändern des Quellcode. Bis vor
kurzem sah sich ein Unternehmen, das wegen seiner einzigartigen
Geschäftspraktiken
eine hochgradig spezialisierte Applikation benötigte, der Tatsache gegenüber, dass
eine Lizenzgebühr
zu zahlen und ein riesiges Codevolumen anhand einer dieser generischen
Applikationen neu zu schreiben war.
-
Firmen verwenden Quellcode-Personalisierung
wegen der mangelnden Kontrolle und Personalisierung, die ihnen von
handelsüblichen
Applikationen geboten werden. In ähnlicher Weise verwenden sie
parametrisierte ERP als Reaktion auf die schlechte Wartungsfähigkeit
und komplizierte Codierung von lizensierter Software oder intern
entwickelter Systeme. Eine leistungsstarke Alternative zu diesen
beiden Ansätzen
ist die Objekt-orientierte Gerüstlösung (Framework-Vorgehensweise).
-
Die Applikationsentwicklung beginnt
stets mit einem. Satz unvollständiger,
ungenauer und manchmal widersprüchlicher
oder unlogischer Anforderungen. Für die Entwickler und Analytiker
eines komplizierten Systems ist es eine schwierige Aufgabe, von
Anfang an genau zu bestimmen, was gebaut wird.
-
Objekt-orientierte Programmiermethodiken
sind bestrebt, diesen Eindruck durch genauere Modellierung der realen
Welt zu korrigieren. Als Nachfolger von Verfahrensmodellen für die Codierung
entstehen durch Objekt-orientierte Techniken ein gemeinsames Vokabular
und genau umrissene Grenzen um die Integration ungleicher Objekte
zu erleichtern. Das unterstützt
den Entwickler bei der Definition von Umfang und Wechselwirkungen
einer Applikation als einen Satz diskreter Komponenten, durch Verbesserung
der Entwicklung und Erleichterung von Änderungen an der Software.
-
Entwickler und Systemplaner verwenden
problemorientierte Entwicklungswerkzeuge, auch Modellier-Werkzeuge
genannt, um den geschäftlichen
Zweck einer Applikation in logischer Weise zu beschreiben, die von
der absoluten Implementation der spezifischen Programmiersprache,
dem Betriebsystem und der Hardware, auf der die Applikation betrieben
wird, abstrahiert ist.
-
Eine abstrahierte Beschreibung der
Applikation mindert die Last, während
ihrer Brauchbarkeitsdauer verschiedene Softwareiterationen erstellen
und unterhalten zu müssen.
Wenn die Aufgabe daraus besteht, ein Stück Funktionalität in einem
Programm von einer Million Zeilen zu finden, wird die Orientierung,
die ein Modell bieten kann, unbezahlbar.
-
Um eine gleichbleibende Methodik
unter modellierenden Lieferanten zu unterstützen, hat die Branche die Universal
Modeling Language (UML) entwickelt, um die während der Analyse und Entwicklung
von Applikationen verwendeten Elemente zu standardisieren. Die breite
Akzeptanz der UML und das Auftauchen von komponentenberuhenden Entwicklungen
machten den Einsatz von Modellier-Werkzeugen zum Ausgangspunkt jeder
Objekt-orientierten Entwicklung.
-
Anstatt eine Applikation von Anfang
an zu entwickeln, entwickeln Firmen mehrschihtige E-Commerce-Applikationen,
um von Lösungen
auf Gerüstbasis
Gebrauch zu machen, die Leistungen wie Nachhaltigkeit, Sicherheit
und Transaktionen anbieten. Ein spezifisches Gerüst (Framework) ist Objekt-orientierte
Abstrahierung, die eine erweiterbare Bibliothek kooperierender Klassen
anbietet, aus denen eine wiederverwendbare Entwicklungslösung für einen
spezifischen Problembereich besteht. Grundsätzlich bietet ein Gerüst eine
generische Lösung,
bei der der Entwickler einen spezialisierten Code implementiert,
der in jeder Komponente als Integrationscode zwischen Komponenten
und Gerüst
funktioniert, um seinen spezifischen Prozess im Gerüst vorzuschreiben.
-
Die Gerüstlösung ist eine drastische Verbesserung
im Vergleich zur informellen Änderung
von lizensiertem verfahrensorientiertem Quellcode. Gerüste haben
eine Hebelwirkung auf kapitalintensive Softwareinvestitionen durch
Wiederverwendung und bieten eine Applikationsprogrammier-Schnittstelle
einer viel hoheren Stufe, so dass Applikationen weitaus schneller
entwickelt werden können.
-
Wenn ein kommerzielles Gerüst personalisiert
wird oder ein firmeneigenes Gerüst
eine neue Funktionalität
erhält,
sind häufig Änderungen
im Komponenten-Gerüst-Integrationscode
für alle
beteiligten Komponenten erforderlich. Die Aufrechterhaltung des
Code im Verlauf derartiger Änderungen
ist ein mühevoller
Vorgang, der mit Fehlern behaftet sein kann. Durch die Beliebtheit
von Lösungen,
die auf Gerüsten
beruhen, ist dies auch im wachsenden Maße ein großer Teil der Arbeit eines Entwicklers.
Selbst wenn dieser Code von einem Codegenerator produziert wird,
muss der Entwickler noch manuell den generierten Integrationscode
in jeder Komponente ändern,
der Teil eines benutzten Gerüsts
ist, weil Codegeneratoren nicht in einem Maß personalisiert werden können, dass
die Erfordernisse eines Unternehmens richtig innerhalb des Gerüsts implementiert
werden. Ferner gestatten es die meisten Gerüste nicht, dass ein Unternehmen
seine firmeneigenen Speicherdaten zentralisiert und erfasst, denn
typische Codegeneratoren werden selten gut mit einem Modellier-Werkzeug integriert.
-
Gerüste werden nicht nur benutzt,
um integrierte Geschäftsanwendungen
in einer Branche aufzubauen, sondern auch zur Entwicklung von: Benutzerschnittstellen,
Grafikbibliotheken, Text- und
Sprachsystemen und Drucklösungen,
niedrigestufigen Dienstleistungen wie Treiber und Netzwerkprotokolle,
gemeinsamen Infrastruktur-Leistungen wie die des Enterprise JavaBeansTM Component Models und CORBA-Objektleistungen (Abkürzung für Common
Object Request Broker Architecture) sowie Entwicklungswerkzeugen,
die das Erzeugen einer Applikation noch mehr beschleunigen.
-
Weil ein Gerüst Softwarekomponenten mit
einer problemorientierten generischen Lösung verbindet, ist es ein
Muss, dass das Gerüst
und die Komponenten synchronisiert bleiben. Das wird allgemein durch
manuelles Ändern
von Gerüst
und Komponenten erreicht.
-
In einigen spezifischen Fällen können die
Informationen im Modellier-Werkzeug jedoch benutzt werden, um Teile
des Integrationscode ohne manuelle Intervention zu generieren. Das
nennt man Codegenerierung. Systeme für die Codegenerierung versprechen eine
rationelle Applikationsentwicklung, da sie es den Entwicklern ermöglichen,
auf einem absoluteren Niveau in ihrer Entwicklung zu arbeiten.
-
Bedauerlicherweise neigen typische
Codegeneratoren dazu, unvollständigen
Code zu generieren, der manuell zu ändern oder sogar ganz auszurangieren
ist.
-
Die beiden zeitraubendsten Aufgaben
für einen
Entwickler, die sich ständig
wiederholen, sind: repetitive Codierverfahren wie das Schreiben
von spezialisierten Softwaremethoden, die mit jeder Eigenschaft
einer Komponente verknüpft
sind, die als "get"- oder "set"-Selektoren bekannt sind, und das
fast repetitive Codieren spezifischer Methoden, die das Gerüst fordert.
Wenn ein Entwickler die Funktionalität innerhalb eines Gerüsts erweitert,
geschieht dies durch Unterklassierung einer der existierenden Komponenten
und Erweiterung ihrer Funktionalität. Um diese Veränderungen
im Komponenten-Gerüst-Integrationscode
zu reflektieren, müssen Entwickler
entsprechend der neuen Funktionalität Änderungen von Hand vornehmen.
In fast repetitiver Codierung entstehen leicht Fehler und ihr monotoner
Charakter mindert die Befriedigung und Produktivität der Entwickler.
-
Typische Lösungen für die Codegenerierung, die
Modellier-Werkzeuge,
Nachhaltigkeitswerkzeuge und die Lieferanten integrierter Entwicklungsumgebungen
bieten, sind darauf gerichtet, die Auswirkungen von repetitivem
oder fast repetitivem Codieren zu mindern, wobei sie jedoch die
Flexibilität
senken, die eine Gerüstlösung dem
Entwickler bietet. Aus diesem Grund kann der Entwickler nicht: den
Namen der generierten Methode ändern,
den generierten Code für
eine spezifische Methode modifizieren, einen anderen Inhalt für die gleiche
Methodenbezeichnung beruhend auf Kontextinformationen generieren,
einen personalisierten Code für
im eigenen Unternehmen entwickelte Gerüste generieren, einen Methodennamen
generieren, der mehrere Komponenten umspannt, wenn diese nicht in
einem Modellier-Werkzeug für
alle betroffenen Komponenten vordefiniert sind und abgeleitete Komponenten
mit dem damit verbundenen erforderlichen Code für Standardlösungen wie das Enterprise JavaBeansTM Component Model generieren.
-
Es gibt mehrere Möglichkeiten zum Generieren
des Code, um die Integration zwischen einem Gerüst und seinen Komponenten aufrecht
zu erhalten.
-
MANUELLES CODIEREN
-
Das einfachste Verfahren zur Aufrechterhaltung
einer Applikation ist manuelles Codieren der repetitiven und fast
repetitiven Teile der Applikation. Obgleich dies zu einer größeren Kontrolle über die
sich ergebende Software führt
als bei typischen Codegeneratoren, ist dies eine kostspielige, fehleranfallige,
monotone Technik, die Projekte gefährdet und zur Unzufriedenheit
von Entwicklern führt.
-
TYPISCHE INTEGRIERTE
CODEGENERATOREN
-
Viele Modellier-Werkzeuge enthalten
integrierte Codegeneratoren, die kleine Mengen repetitiven oder fast
repetitiven Code generieren, bei denen es sich im Wesentlichen um
Skelette für
jede beabsichtigte Methode handelt, die den Entwicklern Hinweise
auf das Format oder den Methodeninhalt geben. Bedauerlicherweise wird
der entstehende Code selten generiert, ohne dass ein zuvor manuell
eingesetzter Code verloren geht, der in den meisten Fällen noch
erforderlich ist, um die vollständige
Funktionalität
der Applikation zu erfüllen.
-
Die Kontrolle des Codegenerierungsverfahrens
mit derartigen Codierwerkzeugen ist eine mögliche Umgehung dieser Beschränkungen.
Einige Anbieter von Modellier-Werkzeugen enthüllen ihre Code-Generieralgorithmen
in Form von Script-Sprache.
-
Wenn diese Scripts jedoch geändert werden,
wird das Entwicklungsverfahren noch komplizierter, denn das Entwicklerteam
muss nun diese Scripts aufrechterhalten, um nutzlichen Code zu generieren
und dazu benötigt
man ein weitaus tieferes Verständnis
der spezifischen Applikationen und des Modellier-Werkzeuges als diese für Objekt-orientierte
Entwicklungsbedingungen erforderlich sind. Durch Änderung
der Scripts trennt sich die Organisation ferner von unterstützenden
Codegenerator-Spezialisten der Lieferanten und unterminiert somit
Bemühungen
für die
Aktualisierung, wenn der Modellierlieferant neue Software-Versionen
freigibt.
-
SCRIPTING
-
In einigen Fällen und sogar ohne dass sie
Zugriff auf Codegenerier-Algorithmen haben, kann ein Entwickler
trotzdem Script-Sprache zum Aufbau eines personalisierten Quellcodegenerators
für eine
spezifische Zielsprache benutzen.
-
Für
diese Losung sind erfahrene Entwicklungsteams erforderlich, was
die Entwicklungs- und Wartungsbelastungen erhöht. Anstatt Code manuell zu
warten, haben die Entwickler nun die Scripts zu warten, die den
Code generieren. Bedauerlicherweise ist der sich ergebende Code
schwierig zu verwenden, kompliziert zu warten und zu entwickeln,
weil der Zielquellcode in gebrochenen Stücken in Script-Sprache gefunden
wird und in der richtigen Reihenfolge zu modifizieren ist. Das ist
ein Problem, das weit über
die Fähigkeiten
dieser Werkzeuge hinaus geht. Ferner ist die Änderung der Scripts, um eine
neue Sprache oder neue Entwicklungsbedingungen zu erzielen, eine
furchterregende Herausforderung.
-
4GL (Fourth-generation
Language)
-
Sprachen der vierten Generation (4GL)
gestatten es dem Entwickler, ausschließlich auf abstraktem Niveau
zu arbeiten anstatt direkt in der Ziel-Programmiersprache zu codieren.
4GL-Systeme stützen sich
entweder auf die UML-Schreibweise, eine entsprechende Sprache oder
eine visuelle Programmierumgebung, um die Spezifikationen für Generieranwendungen
zu liefern. Bedauerlicherweise zahlt der 4GL-Entwickler einen Preis
hinsichtlich der Code-Effizienz und der sich ergebenden Leistung,
da der generierte Code nicht auf die spezifischen Bedürfnisse
eines bestimmten Algorithmus zugeschnitten ist und daher nicht optimiert
werden kann.
-
Von 4GL generierter Code neigt dazu,
wegen der schlechten Integration in existierende Systeme schwer
zu warten zu sein und wegen der Verwendung der generierten numerischen
Variablen. Der generierte Code enthält zum Beispiel generisch benannte
Variable (label1, label2 usw.) an Stelle von bedeutungsvollen Namen
wie 'Name' und 'Kundennummer'.
-
STATISCHE GENERIERBEFEHLE
-
Die statische Lösung beginnt mit dem Erzeugen
von statischen Sätzen
von Generierbefehlen als Teil des parametrisierten Zielquellcode.
Der Generator ersetzt dann alle Variablen, die in den statischen
Sätzen von
Generierbefehlen gefunden werden, durch Informationen, die sich
im Modellier-Werkzeug befinden. Diese statischen Sätze von
Generierbefehlen sind statisch, weil sie nur Zugriff auf die gleiche
Informationsart nehmen (z. B. spezifische Methodeneigenschaften),
die im Modellier-Werkzeug enthalten sind.
-
Die auf statischen Sätzen von
Generierbefehlen beruhende Lösung
passt sich der Generierung von Komponenten-Gerüst-Integrationsmethoden nicht
besonders gut an, weil sie normalerweise Informationen benötigt, die
entweder in der Klasse, im Attribut oder in der Rolle zu finden
sind. Statische Sätze
von Generierbefehlen werden häufig
zur Entwicklung von Methodenskeletten benutzt, die die damit verbundenen
Eigenschaften wie Vor- und Nachbedingungen aus dem Modell extrahieren.
Auf diese Art und Weise generierte Methoden benötigen manuelle Intervention
seitens des Entwicklers, um den Methodeninhalt zu vervollständigen.
-
Generatoren, die statische Sätze von
Generierbefehlen benutzen, können
auch Programmieranweisungen von Objektorientiertem Quellcode (z.
B. C++) in einen nicht Objekt-orientierten Quellcode (z. B. C) unter
Verwendung der in US-Patent 5,675,801, das Lindsay am 7. Oktober
1997 gewährt
wurde, beschriebenen Systeme übersetzen.
-
Die gegenwärtigen Generationen von Technologien
können
mit der Prinzip-Blockdarstellung von 1 erklärt werden.
Ein Entwickler benutzt bekannte Eingabemittel wie eine Tastatur 36,
eine Maus 37 oder eine andere Benutzerschnittstelle 38,
die in textlicher oder grafischer Wechselbeziehung zum visuellen
Modellier-Werkzeug oder zur integrierten Entwicklungsumgebung 30 stehen,
und um die Komponenten zu beschreiben, die sich in diesem Applikationsdomänen-Modell
befinden. Das Werkzeug 30 generiert seine eigene interne
Repräsentation
der Modell-Deklarationen 31. Die meisten syntaktischen
Analyse-/Generierprozessoren 33 produzieren generierten
Code durch Umsetzung von Modell-Deklarationen 31 unter
Verwendung ihres entsprechenden Teilsatzes vorbestimmter statischer
Generierbefehle 32, direkt in Zielcode 35 oder
unter Verwendung einer Zwischendarstellung wie eines abstrahierten
Syntaxbaumes 34. Unter Verwendung dieser Lösung initiali siert
der Generator in einem bestimmten Schritt von mehreren Sätzen von
Generierbefehlen seinen Generierkontext mit dem gegenwärtigen Querknoten
des Syntaxbaumes. Der Generator verarbeitet die mit dem Knoten verbundenen
Anweisungen. Obgleich beim Generierprozess der Generierkontext mit
allen nicht verarbeiteten Knoten, die den auszuführenden Prozess darstellen,
zu andern ist, ist der Generierkontext statisch, weil er sich während der
Ausführung
der Generierbefehle, die mit dem Knoten verbunden sind, nicht ändert.
-
Eine Modell-Deklaration 31 würde eine
Liste von Klassen einschließen,
die potentiell nach Paketname, Beschreibung von Vorgangen und Attributen
für jede
Klasse, den Beziehungen der Klassen untereinander und potentiell
den Attributmerkmalen gruppiert wird, die mit einem spezifischen
Gerüst
verbunden sind.
-
Die statischen Generierbefehle 32 wurden
in die Codegenerierung einbezogen um zu übersetzen, was vom Entwickler
geliefert und in einer anderen Darstellung oder Abstraktion ausgedrückt wurde
als im Zielcode 35. Entwickler haben nicht ohne weiteres
Zugriff auf die Bibliothek vordefinierter Schablonen 32 um
sie zu modifizieren, weil sie nicht benutzt werden um zu diktieren,
welcher Code zu generieren ist, jedoch sind sie indirekt einbezogen,
bedingt durch ihre Beziehungen zu den Modell-Deklarationen 31,
die übersetzt
werden.
-
Einige Applikationsentwicklungswerkzeuge
wie die mit der so genannten SmallTalk-Programmiersprache entwickelten,
liefern ein Gerüst
für die
Quellcodegenerierung, wobei der Zielquellcode 35 durch
Binden von parametrisiertem Zielquellcode, der in eine oder mehrere
SmallTalk-Operationen eingebettet ist, an Werte entsteht, die einen
Teilsatz der Modell-Deklarationen 31 darstellen, die vom
Werkzeug geliefert werden und die als Eingabe für das Applikationsentwicklungswerkzeug
benutzt werden. Diese Art Quellcodegenerierung kann vom Entwickler
nicht ohne weiteres geändert
werden, weil er feststellen muss, wo er seine Änderungen vornehmen muss. Ferner
könnte
dieser auch nicht vom Werkzeuglieferanten unterstützt werden,
weil er den internen Quellcode des Werkzeuges geändert hat.
-
Eine gegenwärtige Technologie, die auf
Gerüsten
beruht, generiert Quellcode unter Verwendung des Konzepts einer
automatisierten Montagelinie, die Softwaremodule produziert. Ein
Softwaremodul ist eine Komponente und wird mit einer Gerüsthierarchie
assembliert. Die Gerüste
enthalten Datenelemente bzw. Methoden, die in jeder Sprache ausgedrückt werden
können
und die Parametrisierung könnte
mit Gerüstparametern erfolgen.
Gerüstparameter
befinden sich in der Nähe
des Gerüsts,
das zuerst ihre Werte festlegt. Ein Gerüst initialisiert typisch (alle
Parameter) auf die vorgegebenen Werte, die es benutzt um Ahnengerüste zu erhalten, die
die Parameter festlegen, die durch Stringwerte geändert werden
müssen,
die den Zielquellcode darstellen. Durch diese Technik wird die Codegenerierung
schwer zu erreichen, weil der Benutzer im voraus die Teile des repetitiven
Code im generierten Code kennen muss um die Gerüsthierarchien zu entwickeln.
-
2 ist
eine Darstellung der Abläufe,
die erforderlich sind, wenn ein bekanntes System benutzt wird. In
einem Werkzeug wird ein Modell
40 generiert. Code
41 wird
generiert, der eine geringe Nutzbarkeit hat, wie bereits erklärt. Bedeutende
manuelle Codierung
42 ist erforderlich, um diese Codeausgabe
41 nützlich zu
machen. Die Namen von Operationen könnten zum Beispiel geändert werden,
um deutlich auszudrücken,
was sie sind. Nachdem diese manuellen Modifikationen
42 vorgenommen
wurden, ist der endgültige
Code
43 im System anwendungsbereit. Ein Beispiel für ein derartig
bekanntes System wird in
EP 0,219,993 beschrieben, d.
h. ein System zum Erzeugen der Komponenten von Software-Quellcode.
-
ZUSAMMENFASSUNG DER ERFINDUNG
-
Daher ist es ein Ziel der vorliegenden
Erfindung, ein System zum Automatisieren repetitiver Entwicklungsaufgaben
zu liefern, das mit der Komponentenentwicklung und Quellcodegenerierung
verbunden ist und ein Mindestmaß an
Entwicklerintervention benötigt,
um die gewünschten
Funktionen zu erhalten.
-
Ein weiteres Ziel der vorliegenden
Erfindung ist es, einen Quellcode-Generator zu liefern, der mit
der Komponentenentwicklung verküpft
ist, durch den Quellcode-Dateien entstehen, die vollständiger und
genauer passend hinsichtlich der gewünschten Funktionen sind als
diejenigen, die mit den zuvor erwähnten Generatoren entstehen.
-
Ein weiteres Ziel ist die Reduzierung
der Code-Wartungsarbeiten durch Regenerieroperationen. Durch Erzielen
eines höheren
Prozentsatzes von generiertem Code wird ferner das Codevolumen,
das zu warten ist, reduziert, weil der generierte Code nie manuell
zu ändern
ist. Die tatsächlichen Änderungen,
die in einem Befehlssatz für
die Generierung erforderlich sind, sind bedeutend weniger.
-
Ein weiteres Ziel der vorliegenden
Erfindung ist, dass sie die in der Lage ist, in alle bedeutenden
visuellen Modellier-Werkzeuge
oder bedeutenden integrierten Entwicklungsumgebungen integriert
werden zu können,
um die Erfassung der gleichen Informationen in mehr als einem Werkzeug
zu vermeiden.
-
Ein weiteres Ziel der vorliegenden
Erfindung ist die Lieferung eines Benutzerschnittstellen-Werkzeuges,
das es dem Entwickler gestattet, durch die Verwendung von Sätzen von
Generierbefehlen das, was zu generieren ist, textlich und grafisch
zu definieren und durch das er die Quellcode-Generieroptionen personalisieren kann,
nachdem die Ziel-Programmiersprache
für das
Werkzeug bestimmt wurde. Wenn der Entwickler einmal einen Satz von
Generierbefehlen und Generieroptionen in einer Datei gespeichert
hat, könnte
das Quellcodegenerator-Werkzeug, das mit der Komponentenentwicklung
verbunden ist, im Stapelbetrieb vom Modellier-Werkzeug oder einer
integrierten Umgebung, uns zwar ohne Einmischung des Entwicklers
aufgerufen werden.
-
Wiederum ein weiteres Ziel der vorliegenden
Erfindung die Lieferung eines Quellcodegenerator-Werkzeuges, der
Code für
eine beliebige Objekt-orientierte Programmiersprache oder unterstützende Komponenten
einer Programmiersprache generiert.
-
Noch ein weiteres Ziel der vorliegenden
Erfindung ist die Lieferung einer Schnittstelle zum Generieren eines
Quellcode, der in jedem Satz von Generierbefehlen zu finden ist,
wobei die minimale Einmischung des Entwicklers erforderlich ist,
um den gewünschten
Satz von Generierbefehlen zu erhalten.
-
Noch ein weiteres Ziel der vorliegenden
Erfindung ist das Vorsehen von Verfolgbarkeit zwischen einem Codeblock
und seinem Satz von Generierbefehlen.
-
Wiederum ein weiteres Ziel der vorliegenden
Erfindung ist die Lieferung eines Editors für Generierbefehle, der die
Bedürfnisse
für die
Korrektur des Quellcode in einem Satz von Generierbefehlen erfüllt, die
unter beliebigen Entwicklungsbedingungen einsetzbar sind wie Webservern,
Gerüstumgebungen,
Codegenerierwerkzeugen oder anderen.
-
Sätze
von Generierbefehlen verbinden die konzeptionellen Komponenten im
problemorientierten Modell mit ihrer entsprechenden Codierimplementation
und ihre Integration mit gegebenen Gerüsten durch Festlegen eines
Bezugspunktes zu verschiedenen Merkmalen.
-
Die Sätze von Generierbefehlen stellen
Zielquellcode dar, der mit Kontextvariablen parametrisiert wird. Jede
Kontextvariable gibt den Bezugsknoten an (wie Klasse und Attribut)
und den Bezeichner (wie Superklasse-Namen, Namen oder Typ): Der
Superklasse-Namenbezeichner könnte
nur benutzt werden, wenn der Bezugsknoten eine Klasse ist und der
Typenbezeichner kann nur benutzt werden, wenn der Bezugsknoten ein Attribut
ist. Der Namenbezeichner würde
ferner verschiedene Ergebnisse haben, abhängig davon, ob der Bezugsknoten
eine Klasse oder ein Attribut ist. Mit anderen Worten kann der Bezugsknoten
unterschiedlich sein, da der Kontext des Codegenerators dynamisch
ist.
-
Wenn der Generierkontext ein Attribut
einer Klasse enthält,
kann der Satz von Generierbefehlen trotzdem Bezug auf seine Klasse
nehmen. Der Bezeichner "Name" wurde dann den Klassennamen oder den
Attributnamen bezeichnen, je nachdem, ob der Bezugsknoten als Klasse
oder Attribut angezeigt wird.
-
Mit dynamischen, kontextempfindichen
Code-Generiertechniken werden größere Mengen
nützlicher Code
während
des Generierprozesses generiert, weil sie Informationen im Modell
aushebeln. Wenn ein Entwickler den Code während der Wartung ändern will,
kann er einfach den Satz von Generierbefehlen oder den im Klassendiagramm
eines Modellier-Werkzeuges erfassten Inhalt ändern.
-
Nach einem ersten Aspekt der vorliegenden
Erfindung wird ein Verfahren zum Generieren von Computer-Quellcode
in einer Objekt-orientierten Programmiersprache oder einer Programmiersprache
geliefert, die Komponenten unterstützt. Das Verfahren umfasst
die folgenden Schritte die Lieferung eines Satzes von Generierbefehlen,
wobei der Satz von Generierbefehlen Definitionen mit mindestens
zwei Knoten umfasst und mindestens zwei entsprechende Knotenbezeichner;
Zielquellcode, der mit mindestens zwei Kontextvariablen parametrisiert
ist, wobei jeder der mindestens zwei Kontextvariable auf einen der
Knoten und die entsprechenden Knotenbezeichner zeigen und wobei
die mindestens zwei Kontextvariablen auf mindestens zwei verschiedene
Knoten zeigen, wobei der Zielquellcode eine gültige Syntaxanweisung für die Programmiersprache
ist; mindestens zwei Filterbefehle, die je ein Auswahlkriterium
für die
Wahl von mindestens einem der Knoten entsprechend den Definitionen
umfassen; und den Schritt der automatischen Generierung als Reaktion
auf die mindestens zwei Filterbefehle, eine Vielzahl von Codesegmenten
in der Programmiersprache durch Ersatz der mindestens zwei Kontextvariablen
im parametrisiertem Zielquellcode mit einem Wert der gewählten Knotenbezeichnern.
-
Vorzugsweise werden die Schritte
wiederholt, bis ein Satz von Codesegmenten erhalten wurde, der eine
Vielzahl von Komponenten bestimmt.
-
Vorzugsweise enthält das Verfahren auch einen
Schritt zur Auswahl der mindestens einen Kontextvariablen aus einer
Liste von Kontextvariablen.
-
Vorzugsweise enthält das Verfahren auch automatisch
generierte Zeigerdaten für
jedes Codesegment, die auf Stellen im Satz von Generierbefehlen
zeigen, die im Generierschritt für
das Codesegment verwendet werden. Vorzugsweise werden die Zeigerdaten
in einer getrennten Datei von mehreren Codesegmenten oder als Anmerkungszeilen
in allen Codesegmenten gespeichert.
-
Vorzugsweise-umfasst das Verfahren
ferner das Finden von mindestens einem Teil des Quellcode, der eine Änderung
benötigt.
Dazu werden die Zeigerdaten aus dem Teil benutzt, um die Stellen
im Satz von Generierbefehlen zu finden, die eine entsprechende Änderung
benötigen;
die Änderung
des Satzes von Generierbefehlen mindestens an einigen Stellen und
Wiederholen des automatischen Generierschrittes mehrerer Codesegmente
unter Verwendung des Satzes von Generierbefehlen, der im vorhergehenden
Schritt geändert wurde.
-
Vorzugsweise enthält das Verfahren mindestes
einen Schritt zum Erstellen, Ordnen und Personalisieren des Satzes
von Generierbefehlen.
-
Vorzugsweise enthält das Verfahren einen Schritt,
bei dem der Programmierer den mindestens einen Satz von Generierbefehlen übersetzt,
der in einer ersten Programmiersprache geschrieben wurde, in eine zweite
Programmiersprache, wobei die Vielzahl von Codesegmenten in einer
zweiten Programmiersprache generiert wird.
-
Nach einem anderen Aspekt der vorliegenden
Erfindung wird ein Computerprogramm geliefert, das Codemittel enthält, die
so angepasst sind, dass sie alle Schritte des Verfahrens ausführen, das
in einem computerlesbaren Medium verkörpert sind.
-
Nach einem anderen Aspekt der vorliegenden
Erfindung wird ein Computerprogramm geliefert, das Codemittel enthält, die
so angepasst sind, dass sie alle Schritte des Verfahrens ausführen können, das
als ein elektrisches oder elektromagnetisches Signal verkörpert.
-
Eine Vielzahl von Codesegmenten,
die nach den Schritten des beanspruchten Verfahrens generiert wurden,
können
als ein Computer-Datensignal bereitgestellt werden, das auf einer
Trägerwelle
verkörpert
ist.
-
Es versteht sich, dass der Satz von
Schablonen das Erstellen von Komponenten (sowie on Operationen oder
Attributen) vorschreiben kann, die ursprünglich nicht beabsichtigt waren,
in den Modell-Deklarationsdaten vorgeschrieben zu werden. Dies wird
durch Vorschrift des Erzeugens von Komponenten im Satz von Schablonen
erzielt, die sich auf Komponenten beziehen, die in den Modell-Deklarationsdaten
enthalten sind. Auf diese Art und Weise können gewisse Sätze von
Schablonen benutzt werden, um auf die Bedürfnisse bestimmter Programmiergerüste zu reagieren.
-
Eine Vorrichtung zum Generieren von
Computer-Quellcode in einer komponentenberuhenden Sprache wird ebenfalls
vorgesehen, wobei die Vorrichtung aus einem Schabloneneditor zum
Erzeugen oder Personalisieren von Sätzen von Generierbefehlen enthält, einen
Schablonenmanager zur Auswahl und Ordnung von Sätzen von Generierbefehlen und
Einstell-Generierparametern, einen Quellcodegenerator und eine Quellcodeausgabe.
Die Vorrichtung kann ferner einen Zeiger-Datengenerator und Sprachdatenbanken
zur Wahl der Sprache umfassen, auf der die generierten Codesegmente
beruhen.
-
Eine weitere Vorrichtung wird zum
Modifizieren des generierten Computer-Quellcode geliefert, die einen
Quellcode-Editor zum Finden des Quellcode, einen Schablonenmanager,
einen Schabloneneditor, einen Quellcodegenerator und einer Quellcode-Ausgabe umfasst.
-
Zum Zweck der vorliegenden Erfindung
werden nachstehend folgende Ausdrücke definiert:
Der Ausdruck
"Schablone" bezieht sich auf den Zielquellcode, der mit mindestens
einer Filtervariablen und mit mindestens einer Kontextvariablen
parametrisiert wurde.
Der Ausdruck "Kontextvariable" bezieht
sich auf eine Variable, die einen Bezugsknoten und einen Bezeichner zeigt.
Der
Ausdruck "Filtervariable" bezieht sich auf eine Variable, die die
gewählten
Komponenten bestimmt, für
die der Code generiert werden soll.
Der Ausdruck "Objekt-orientierte
Programmierung" bezieht sich auf die Art der Programmiersprache,
mit der der Entwickler nicht nur die Datenart einer Datenstruktur
beschreibt sondern auch die Art der Operationen, die auf die Datenstruktur
angewandt werden können.
Ferner kann der Entwickler Verhältnisse
zwischen einem Objekt und einem anderen erzeugen.
Der Ausdruck
"Komponente" bezieht sich auf eine Einheit, die die Verkapselungs-
und Abstrahiermerkmale des Objekts aufweist. Ferner sind Komponenten
Teil des technischen Gerüsts,
das die Standards ihrer Struktur, Fähigkeiten und Wechselwirkung
beschreibt.
Der Ausdruck "Modell-Deklaration" bezieht sich
auf die Darstellung, die die statische Struktur eines Systems erfasst, indem
die Komponenten im System, die Beziehungen zwischen den Komponenten
und die Attribute und Operationen dargestellt werden, die jede Komponentenklasse
charakterisieren.
Der Ausdruck "Binden" bezieht sich auf eine
Verküpfung
zwischen einem Bezeichner oder einer Variablen und einem Wert für den Bezeichner
oder die Variable, die innerhalb eines vorgeschriebenen Umfangs
gilt.
Der Ausdruck "Satz von Generierbefehlen" bezieht sich
auf einen Satz von Anweisungen, der mindestens eine Schablone, Filtervariable
und Modell-Deklaration enthält.
-
KURZBESCHREIBUNG DER ZEICHNUNGEN
-
Diese und andere Merkmale, Aspekte
und Vorteile der vorliegenden Erfindung werden besser unter Bezugnahme
auf die folgende Beschreibung und die diese begleitenden Zeichnungen
verstanden, wobei
-
1 ein Übersichtsdiagramm
des Standes der Technik ist;
-
2 ein
Ablaufdiagramm des Standes der Technik ist;
-
3 ein
allgemeines Übersichtsdiagramm
der Erfindung im Hinblick auf ihre Umgebung ist;
-
4 ein
allgemeines Übersichtsdiagramm
der Erfindung ist;
-
5a ein
erstes Ablaufdiagramm eines Überblicks über die
Quellcodegenerierung ist;
-
5b ein
zweites Ablaufdiagramm eines Überblicks über die
Quellcodegenerierung ist;
-
5c ein
Ablaufdiagramm für
konstantes Erzeugen ist;
-
5d ein
Ablaufdiagramm für
variables Erzeugen ist;
-
5e ein
Ablaufdiagramm für
mehrfache codeString-Auflösung
ist;
-
5f ein
Ablaufdiagramm für
eine codeString-Auflösung
ist;
-
5g ein
Ablaufdiagramm für
eine parametrisierte codeString-Auflösung ist;
-
5h ein
Ablaufdiagramm für
eine repetitive parametrisierte codeString-Auflösung ist;
-
6 ein
Ablaufdiagramm für
die Generierung von Quellcode unter Verwendung von Sätzen von
Generierbefehlen ist;
-
7 ein
Ablaufdiagramm für
die Generierung von Quellcode unter Verwendung einer Modell-Deklaration
und von Sätze
von Schablonen ist;
-
8 ein
Ablaufdiagramm für
eine Ergänzung
des Quellcode durch Modifizieren der Sätze von Generierbefehlen ist;
-
9 ein Übersichtsdiagramm
ober den Quellcodegnerator ist;
-
10 ein Übersichtsdiagramm über das Änderungswerkzeug
ist;
-
11 eine
Darstellung einer Modell-Deklaration für eine Applikation im Bankwesen
ist;
-
12 eine
Darstellung von EJB-Klassen ist, die für VapAccount generiert wurden;
-
13 die
Abbildung einer spezifischen Syntax für die Modell-Deklaration im
Backus-Naur-Format ist, die zum Implementieren des bevorzugten Ausführungsbeispiels
benutzt werden konnte.
-
14 die
Abbildung einer spezifischen Syntax für den Satz von Generierbefehlen
im Backus-Naur-Format ist, die zum Implementieren des bevorzugten
Ausführungsbeispiels
benutzt werden konnte.
-
AUSFÜHRLICHE BESCHREIBUNG DES BEVORZUGTEN
AUSFÜHRUNGSBEISPIELS
-
Die Worte Komponente und Klasse werden
als Synonyme verwendet, weil alle Implementationssprachen, die in
den Beispielen besprochen werden (JAVATM,
C++ und SmallTalk), die gleiche Bedeutung für Komponente benutzen, d. h.
eine Komponente ist eine Klasse.
-
Die vorliegende Erfindung kann in
den verschiedensten bekannten Computerumgebungen eingesetzt werden
und könnte
in dem in der 3 dargestellten
System implementiert werden und Quellcode in einer Programmiersprache
generieren, die Komponenten unterstützt wie C++, JAVATM oder
SmallTalk. 5 bis 8 sind Ablaufdiagramme, die die Verfahren
laut dem bevorzugten Ausfüh rungsbeispiel
der vorliegenden Erfindung darstellen.
-
4 ist
ein Ablaufdiagramm der allgemeinen Schritte des Verfahrens. Mit
einem Modellier-Werkzeug 50 wird ein Modell 65 erzeugt.
An einen Codegenerator werden nach dem bevorzugten Ausführungsbeispiel Generierbefehle 66 erteilt.
Es wird eine Codeausgabe 67 erhalten. Diese Codeausgabe 67 ist
Benutzer-spezifisch
und vollständig.
Abhängig
von der Qualität
der Generierbefehle ist es möglich,
dass der endgültige Code 68 nicht
zu modifizieren oder zu vervollständigen ist, bevor ihn der Entwickler
benutzen kann. In anderen Fällen
muss der Programmierer eingreifen, um den Code vor Einsatz zu vervollständigen.
-
Ein Entwickler verwendet bekannte
Eingabemittel wie eine Tastatur 53, eine Maus 54 oder
eine Benutzerschnittstelle 55 für textliche oder grafische
Wechselbeziehungen zum visuellen Modellier-Werkzeug oder zur integrierten
Entwicklungsumgebung 50 und um die Komponenten zu beschreiben,
die es in einem spezifischen Domänemodell
(Schritt 75 von 5a)
und in seinem Klassendiagramm gibt. In den 11 und 12 sind zwei
Klassendiagramme dargestellt.
-
Die Diagramme von 5 zeigen
eine spezifische Implementierung eines bevorzugten Ausführungsbeispiels
der vorliegenden Erfindung. Sie sind eine Darstellung der Verarbeitung
der Sätze
von Generierbefehlen. 13 und 14 sind Backus-Naur-Diagramme, die die Syntax für die Sätze von
Generierbefehlen darstellen, die den Ablaufdiagrammen von 5 entsprechen. Die Syntax wird als spezifisches
Beispiel für
ein bevorzugtes Ausführungsbeispiel
der vorliegenden Erfindung angegeben. Es versteht sich, dass der
Fachmann zahlreiche Modifikationen zu diesen findet. Die Beschreibung
der Ablaufdiagramme und der Backus-Naur-Diagramme ist daher nur
als eine Darstellung der Erfindung und keine Beschränkung derselben
zu betrachten.
-
Wie in Schritt 76 von 5a dargestellt, erweitert
der Entwickler den Umfang der Informationen in einem typischen Modellier-Werkzeug
durch Definieren von Gruppen von externen Eigenschaftsnamen im Modell,
wodurch alle möglichen
Implementierungsdetails erfasst werden, die mit dem gegenwärtigen Modell verbunden
sind.
-
Wie in Schritt 77 dargestellt, bezieht
sich der Entwickler durch den Einsatz der codeString, die in einem Satz
von Generierbefehlen gefunden wird, auf die Zielsprache. Eine codeString
wird zum Beispiel direkt unter Verwendung eines Teilsatzes gültiger Konstrukte
der Implementierungszielsprache ausgedrückt, eingeschlossen in zwei
Ausrufezeichen "!", eins am Anfang und eins am Ende der codeString.
-
Obgleich die codeString in diesem
bevorzugten Ausführungsbeispiel
in einer leicht vom menschlichen Auge lesbaren Syntax beschrieben
wird, könnte
die Verwendung derartiger Symbole auf beliebige Symbole oder Zeichen
geändert
werden oder sogar grafische Implementationen, um die Verwendung
des Systems zu erleichtern.
-
Es gibt zwei verschiedene codeString-Arten:
konstante und parametrisierte codeStrings. Der Generierprozessor 52 löst jede
anders. Im ersten Fall muss der Generierprozessor 52 die
konstante codeString nicht manipulieren, nachdem sie von der Generierbefehl-Maschine 47 einer
syntaktischen Analyse unterzogen wurde. Die Lösung der konstanten codeString
durch den Generierprozessor 52 erfolgt, indem das erste
und letzte Ausrufezeichen entfernt wird und die Rückgabe der
codeString erfolgt. Mit anderen Worten: Der Generierprozessor 52 gibt
den Quellcode so zurück,
wie er vom Entwickler codiert wurde. Im zweiten Fall ist eine parametrisierte
codeString eine codeString, bei der der Generierprozessor 52 das
Vorkommen der Kette %n binden muss, wobei n eine ganze Zahl zwischen
1 und 9 mit den gelieferten Werten ist. Während der Bequemlichkeit halber
in diesem bevorzugten Ausführungsbeispiel
der vorliegenden Erfindung die codeString so konzipiert wurde, dass
sie das wiederholte Auftreten der Kette %n einschließt, wobei
n eine ganze Zahl zwischen 1 und 9 ist, könnte der Entwickler die Wahl
haben, das weitere Auftreten anderer Ziffern und Zeichen mit dem
gleichen Ergebnis zu integrieren. n könnte zum Beispiel zwischen
1 und 99 oder 1a und 9z sein.
-
Das Binden des Auftretens erfolgt
durch den Rekursionsbinder 48, der Teil des Generierprozessors 52 ist.
Wenn nur ein Wert für
die codeString zur Verfügung
steht, ersetzt der Generierprozessor 52 alle Vorkommen
von %1 durch den gelieferten Wert oder der Prozessor 52 generiert
einen Fehler, wenn in der codeString die Kette %n vorkommt, wobei
n eine ganze Zahl zwischen 2 und 9, und die Generierung von Code
stoppen. Wenn mit der codeString zwei Werte geliefert werden, ersetzt
der Generierprozessor 52 jedes Vorkommen von %1 durch den
zuerst gelieferten Wert und jedes Vorkommen von %2 durch den zweiten
gelieferten Wert oder er generiert einen Fehler, wenn in der codeString
die Kette %n vorkommt, wobei n eine ganze Zahl zwischen 3 und 9,
und die Generierung von Code Stoppen. Wenn daher eine Liste mit
Werten geliefert wird, ersetzt der Generierprozessor 52 die
Kette %n jedesmal, wenn sie auftritt, mit dem nten Wert aus der
gelieferten Liste. Der Wert n muss zwischen 1 und 9 liegen. Der
Generierprozessor 52 generiert einen Fehler, wenn in einem Teil
der parametrisierten codeString %k vorkommt, wobei k eine ganze
Zahl ist, die größer als
die Größe der gelieferten
Liste ist, jedoch kleiner als 10. Auch hier hat der Entwickler die
Wahl, einen anderen Satz von Werten für den %k zu liefern. Schließlich gibt
der Generierprozessor 52 den Quellcode zurück, der
aus dem Ersatz aller Ketten %n durch die gelieferten Werte entsteht,
die in der parametrisierten codeString gefunden werden. Wie die
konstante codeString, muss auch die gelöste parametrisierte codeString
einen syntaktisch gültigen Teilsatz
von Konstrukten der Implementierungszielsprache enthalten und der
Entwickler muss die parametrisierte codeString mit den gelieferten
Werten schreiben. Die Modell-Deklarationen 51 enthalten
streng konstante codeStrings, jedoch können Sätze von Generierbefehlen 56 beide
codeString-Arten enthalten.
-
Zwischen einer gelösten codeString
und dem Zielcode findet keine Übersetzung
statt. Mit anderen Worten: Der Entwickler ist für das Schreiben eines Teilsatzes
gültiger
Syntaxanweisungen für
die gewünschte Zielsprache
in einer codeString verantwortlich. Dies bietet den Vorteil, dass
mit dem Codierstil des Entwicklers ein effizienter Code entsteht.
-
Der Generierprozessor 52 besteht
daher aus einem Modell- Deklaration-Prozessor 46,
einem Generier-Deklaration-Prozessor 47 und einem Rekursionsbinder 48.
Der Generier-Deklaration-Prozessor 47 entnimmt
seinen Kontext aus dem abstrakten Syntaxbaum 58. Der Rekursivbinder 48 löst die codeString
rekursiv unter Verwendung des abstrakten Syntaxbaumes. Der Modell-Deklaration-Prozessor 46 analysiert
die Modell-Deklarationen 51 und liefert Informationen für den Aufbau
des abstrakten Syntaxbaumes 58.
-
Durch Einsatz des Werkzeuges 49 schließt der Entwickler
die Implementationsdetails (Schritt 76) ab, die mit der Entwicklungsdomäne und der
Implementationsprogrammiersprache verbunden sind, indem er einen
Teil oder alle der folgenden Informationen vorgibt.
-
In jedem Paket können folgende Details enthalten
sein: eine Bemerkung mit Beschreibung, Namen, dem Namen des enthaltenen
Pakets, wenn sich das gegenwärtige
Paket in einem anderen befindet und eine Liste der Beschreibungen
der einzelnen Klassen, die in dem gegenwärtigen Paket definiert sind.
-
Für
jede Klassen oder Schnittstelle kann eine Anmerkung mit Beschreibung,
den Wert der Schnittstellenart wie private, public, protected oder
package, den Namen, den Wert, der angibt, ob die Klasse konkret oder
abstrakt ist, den Superklassen-Namen und den Paketname, wenn die
Superklasse definiert ist, eine Liste mit den Beschreibungen der
einzelnen Attribute, die in der gegenwärtigen Klasse definiert werden,
eine Liste mit Beschreibungen der einzelnen externen Eigenschaften,
die mit dem gegenwärtigen
Modell verbunden sind, und eine Liste der Beschreibungen der einzelnen
Operationen, die in der gegenwärtigen
Klasse definiert wurden.
-
Für
jedes Attribut kann eine Bemerkung mit seiner Beschreibung, seinem
Schnittstellenart-Wert, (wie private oder public), protected oder
package, seiner Art, die besagt, ob es sich um ein Instanz- oder
Klassen-Attribut handelt, seinem Namen, dem Namen seiner Implementationsklasse
und dem Paketnamen, wenn die Implementationsklasse definiert ist,
seinem entsprechenden Typdef-Wert, der durch den Einsatz einer konstanten
codeString implementiert wird und der mit seiner Implementationsklasse
für Programmiersprachen
wie C++ verbunden ist, dem Namen der Attributklasse der Elemente,
die an sich eingeschlossen sind, wenn es wie eine Sammlung aussieht,
sein Vorgabewert, der durch die Verwendung einer konstanten codeString
implementiert wird, eine Liste mit Beschreibungen einer jeden externen
Eigenschaft, die mit dem gegenwärtigen
Attribut verbunden ist, angeben werden.
-
Für
jede Verbindung kann eine Bemerkung enthalten sein, ihre Beschreibung,
der Name, die Namen der Quellrolle und der Zielrolle, Präfixe und
Suffixe, Rollen-Schnittstellenarten, Werte, die angeben, ob die
Rollen transient, flüchtig
oder endgültig
sind.
-
Für
jede externe Eigenschaft kann der Name und eine Liste mit Definitionen
angegeben werden, die durch den Einsatz einer konstanten codeString
implementiert werden,
-
Für
jede Operation kann der Schnittstellenwert wie private oder public,
protected oder package angegeben werden, der Wert, der besagt, ob
es sich um eine Klasse- oder Instanz-Operation handelt, der Name, der
Name der Kategorie (der für
Programmiersprachen wie SmallTalk benutzt wird), der Anweisungscode
(der für
Programmiersprachen wie C++ für
die Anfangsdatei verwendet wird), die durch Verwendung einer konstanten
codeString mit einer Liste der betreffenden Klassen, die in der
codeString benutzt werden, implementiert wird, der Definitionscode,
der durch Verwendung der konstanten codeString mit einer Liste der
betreffenden Klassen, die in der codeString benutzt werden, implementiert
wird.
-
Wenn es sich um Gerüste handelt,
muss der Entwickler die Implementationsdetails in Definitionen der codeString
zerlegen und diese in externen Eigenschaften gruppieren. Mehr als
ein Name einer externen Eigenschaft ist möglicher Weise erforderlich,
um alle Definitionen zu implementieren, die für ein bestimmtes Gerüst benötigt werden
und eine externe Eigenschaft könnte
benutzt werden, um Mehrfachgerüste
zu implementieren. In den meisten Fällen enthält ein Eigenschaftswert streng
genommen nummerische oder alphanummerische Werte für konstante
codeStrings.
-
Der Entwickler generiert dann die
Modell-Deklaration 51 durch die Verwendung des Werkzeugs 50. Die
Modell-Deklaration kann entweder unabhängig von der Sprache sein oder
für den
Gebrauch mit eine spezifischen Sprache wie C++. JAVATM oder
SmallTalk angepasst werden. Wenn die erste Option benutzt wird, sind
die Sätze
von Generierbefehlen 56 zu schreiben, damit die allgemeinen
Modell-Deklarationen 51 benutzt werden können. Wenn
die zweite Option benutzt wird, unterscheiden sich die Modell-Deklarationen in
drei Hauptaspekten: Implementationsdetails, codeString und Kategoriename
sowie Typedef. Paketnamen, Klassennamen, Attributnamen und Operationsnamen
sind Implementationsdetails, die sich unterscheiden, weil die Benennungskonvention
zum Beispiel im Vergleich zu SmallTalk in C++ anders ist. Die codeString
ist anders, weil die Sprache nicht die gleiche Syntax der Programmiersprache
unterstützt.
Informationen wie Kategorienamen (in SmallTalk) und Bezugsklassen
(in C++ und JAVATM, um Anweisungen zu generieren
bzw. einzuschließen
und zu importieren) werden nur bei Bedarf benutzt.
-
Der Entwickler verwendet die Codegenerator-Benutzerschnittstelle 49 für die restlichen
Aufgaben. Wenn er sie aufruft, lädt
er die Datei, die die Modell-Deklarationen enthält und die Datei, die die Sätze von
Generierbefehlen 56 enthält, wenn sie bereits erledigt
sind. Beim bevorzugten Ausführungsbeispiel
erzeugt der Entwickler mehrere Sätze
von Generierbefehlen 56, die seinem eigenen Bedarf entsprechen
(Schritt 77). Die Sätze
von Generierbefehlen können
erzeugt, modifiziert, personalisiert oder geordnet werden, um den
Satz von geeigneten Sätzen
von Generierbefehlen für
die Generierung vorzubereiten.
-
Durch Verwendung der Codegenerator-Benutzerschnittstelle 49 wählt der
Entwickler die Programmiersprache des generierten Zielcode, bei
dem es sich entweder um den gleichen handeln kann, den der Entwickler
benutzt, wenn er alle codeStrings definiert, die im Modell gefunden
wurden und die Sätze
von Generierbefehlen oder einen anderen, wenn die Übersetzung
der Sätze
von Generierbefehlen gefordert wird. Dann überprüft er die Generieroptionen 57,
die sich nachteilig auf die Generierung von Code (Schritt 78) auswirken, durch
die Benutzung der Codegenerator-Benutzerschnittstelle 49 um
die Gültigkeit
der folgenden Einstellungen zu prüfen: das erste Zeichen eines
Attributs, einer Klasse, einer externen Eigenschaft, einer Operation oder
eines Paketnamens, das entweder in Kleinbuchstaben, Großbuchstaben
oder gemischt erscheinen kann; eine Liste der Sonderzeichen, die
in einem Attribut, einer Klasse, einer externen Eigenschaft, einer
Operation oder einem Paketnamen gefunden werden könnten; den
vorgegebenen Wert, der für
den Schnittstellenwert verwendet wird, der mit einer Klasse, einem
Attribut oder einer Operation verbunden ist, wenn nicht ausdrücklich in
der Modell-Deklaration angegeben; den Wert der gültigen Schnittstellenart, der
mit einer Klasse, einem Attribut oder einer Operation verbunden
ist; die Liste der gültigen
externen Bezeichner; einem Bole'schen Wert, der angibt, ob der Generator
diesen in die Liste der externen Bezeichner einreihen sollte, wenn
er einen neuen in der Modell-Deklaration findet.
-
Der Entwickler überprüft ferner die Extrahieroptionen 57.
Die Einstellungen für
drei komponentenberuhende Sprachen werden hier als Beispiel angegeben.
Als Teil der Generier-Untermenüs
"Präferenzen"
für die
Codegenerator-Benutzerschnittstelle 49, wenn C++ als Generator
benutzt wird, ändert
der Entwickler die folgenden Optionen zum Extrahieren des generierten
Code:
Das "Declaration code directory" wird benutzt, um das
Laufwerk und dessen Hauptverzeichnis-Namen anzugeben. Die Vorgabe
ist der Wert d:\include.
Das "Definition Code directory" wird
benutzt, um das Laufwerk und den Hauptverzeichnis-Namen anzugeben. Die
Vorgabe ist der Wert d:\source.
"File extension for declaration
mode" wird benutzt, um die Datei-Extension von jedem Namen anzugeben,
der mit einer Klasse verknüpft
ist, die zum gegenwärtigen
Paket gehört.
Die Vorgabe ist der Wert hpp.
"File extension for definition"
wird benutzt, um die Datei-Extension
für jeden
Dateinamen vorzuschreiben, die auf eine Klasse abgebildet ist, die
zum gegenwärtigen
Paket gehört.
Die Vorgabe ist der Wert cpp.
"One class per file" wird als
Vorgabe auf 'wahr' eingestellt, kann jedoch geändert werden.
-
Als Teil des Generierpräferenzen-Untermenüs des Frontend-Werkzeugs 49,
wenn JAVATM als Generator benutzt wird, ändert der
Entwickler die folgenden Optionen zum Extrahieren des generierten
Code:
"Root directory" wird benutzt, um das Laufwerk und den
Namen des Hauptverzeichnisses anzugeben. Als Vorgabe ist der Wert
d:\.
"Directories mapping package name" wird zum Erstellen
von Unterverzeichnis-Namen für
jede subString benutzt, die zwischen zwei Zeiten gefunden wird,
wenn die Einstellung auf 'wahr' erfolgt ist. Die Vorgabe ist 'wahr'.
"Class
extension" wird zur Angabe der Datei-Extension für jeden Dateinamen benutzt,
um die Datei-Extension von jedem Dateinnamen anzugeben, die auf
eine Klasse abgebildet ist, die zum gegenwärtigen Paket gehört. Die
Vorgabe ist der Wert JAVATM.
"One class
per file" wird als Vorgabe auf 'wahr' eingestellt, könnte jedoch
geändert
werden.
-
Als Teil des Generierpräferenzen-Untermenüs für das Front-end-Werkzeug 49,
wenn SmallTalk als Generator eingesetzt wird, ändert der Entwickler die folgenden
Optionen für
das Extrahierverfahren des generierten Codes:
Das "Definition
code directory" wird benutzt, um das Laufwerk und den Namen des
Hauptverzeichnisses anzugeben. Als Vorgabe ist dies d:\.
"File
extension for definition" wird benutzt, um die Datei-Extension für jeden
Dateinamen anzugeben, die mit einer Klasse verknüpft ist, die zum gegenwärtigen Paket
gehört.
Die Vorgabe ist der Wert app.
"One package per file" wird als
Vorgabe auf 'falsch' eingestellt, könnte jedoch geändert werden.
-
In Schritt 79 ruft der Entwickler
den Generierprozessor 52 auf und verwendet dazu das Frontend-Werkzeug 49.
Der Prozessor 52 beginnt mit der syntaktischen Analyse
der ersten Modell-Deklaration 51 (Schritt
80) und erzeugt ihre Repository-Daten (Schritt 81), die im abstrakten
Syntaxbaum 58 gespeichert werden. Mit anderen Worten erzeugt
der Generierprozessor 52 – unter Verwendung der einer
syntaktischen Analyse untergezogenen Infor- mationen mit dem Modell-Analysealgorithmus – Knoten
im abstrakten Syntaxbaum 58 für jedes Paket, jede Klasse,
jedes Attribute, jede externe Eigenschaft, Verbindung, Rolle und
Operation, die in der Modell-Deklaration 51 gefunden werden,
und für
alle Verhältnisse
zwischen diesen, wie bereits beschrieben (Schritt 81).
-
Jeder Knoten, der ein Paket, eine
Klasse, ein Attribut oder eine Operation darstellt, hat ein mit
definitionText bezeichnetes Attribut, das den damit verbundenen
generierten Definitionsquellcode enthält. Ein Klassen-, Attribut-
und in Operationsknoten haben ebenfalls ein mit declarationText
bezeichnetes Attribut, das den generierten Anweisungsquellcode enthält, der
damit für
Programmiersprachen wie C++ verbunden ist.
-
In Schritt 81 wird jede deklarierte
Operation oder jedes Attribut, die in den Modell-Deklarationen 51 gefunden
werden, zu einem Operations- oder Attributknoten, der mit seinem
deklarierten Klassen-Knoten verbunden ist. Bei diesem Schritt initialisiert
der Generierprozessor 52 die Attribute definitionText und
declarationText mit dem gelieferten Definitions- und Anweisungsquellcode
durch Extrahieren desselben von der entsprechenden konstanten codeString.
-
Bevor bestimmt wird, ob eine andere
Modell-Deklaration vom Generierprozessor 52 zu verarbeiten
ist (Schritt 82) und bevor eine syntaktische Analyse durchgeführt wird
(Schritt 83), hört
der Generierprozessor 52 mit der syntaktischen Analyse
auf, wenn der erste Fehler gefunden wird und bittet darum, dass
das Frontend-Werkzeug 49 den Fehler im Kontext in den Modell-Deklarationen mit
dem Zeichen für
den Fehler anzeigt. Ein Fehler tritt auf, wenn der Generierprozessor 52 die
Generier- und Extraktoroptionen 57 anhand der gegenwärtigen Modell-Deklaration überprüft oder
wenn er den gleichen Klassennamen als zweimal im gleichen Paket
definiert findet oder den gleichen Attributnamen, der zweimal für die gleiche
Klasse definiert ist (hauptsächlich
bedingt durch die Tatsache, dass der gleiche Attributname von einer
Superklasse geerbt wurde).
-
In Schritt 85 nimmt der Generierprozessor 52 die
syntaktische Analyse eines ersten Satzes von Generierbefehlen 56 vor um
die Zielklassen oder Pakete zu bestimmen, die er zum Generieren
von Code (für Schritt
86) benötigt
und die Art der Codegenerierung, die zu verarbeiten ist (Schritt
89).
-
Zielklassen (Schritt 86) sind ein
Teilsatz vom deklarierten Klassen, die im abstrakten Syntaxbaum 58 gefunden
werden oder sie werden von diesem Teilsatz abgleitet. Um den Teilsatz
der deklarierten Klassen im Empfänger-Anweisungsteil
des Satzes von Generierbefehlen 56 zu finden, schreibt
der Entwickler die Auswahlkriterien vor, die mit der Klasse selbst
oder ihren Attributen, Knoten oder externen Eigenschaften verbunden
sind. Zum Beispiel konnte ein Entwickler alle Klassen wählen, indem
er das Schlüsselwort &classes eingibt,
alle abstrakten Klassen durch Angabe des Schlüsselwortes &classes, gefolgt vom Schlüsselwort
abstract, alle konkreten durch Angabe des Schlüsselwortes &classes, gefolgt vom Schlüsselwort
concrete, alle Klassen, die Unterklassen eines bestimmten Klassennamens
sind, durch Angabe der Schlüsselworte &classes subclassOf,
gefolgt von einem bestimmten Klassennamen oder allen Klassen, die
Attribute einer bestimmten Art aufweisen, durch Angabe der Schlüsselworte &classes having
attribute of type, gefolgt von einem bestimmten Klassennamen.
-
Für
jede abgeleitete Klasse wird 99 dem abstrakten Syntaxbaum 58 zugerechnet,
sobald er erzeugt ist, um in Schritt 88 abgerufen zu werden.
-
Zielpakete (Schritt 86) beziehen
sich stets auf alle Pakete, indem das Schlüsselwort &packages angegeben wird, weil der
mit einem Paket verbundene, generierte Code indirekt verwendet wird,
wenn der generierte Code, der mit einer seiner enthaltenen Klassen
verbunden ist, extrahiert wird (weitere Einzelheiten siehe Schritt
97).
-
In Schritt 87 wird der erste Zielknoten
verarbeitet und zum gegenwärtigen
Klassenkontext oder dem gegenwärtigen
Paketkontext in Schritt 88, abhängig
davon, ob die Zielknoten streng Klassen bzw. Pakete enthalten. Die
Zielknoten stellen nur Pakete dar, wenn der gegenwärtige Satz
von Generierbefehlen 56 Code für die Paketdefinition generiert
und ein Schlüsselwort,
das einer syntaktischen Analyse unterzogen wurde, packageDefinition
ist, wie nachstehend erklärt.
-
In Schritt 89 unterscheidet der Generierprozessor 52 die
Code-Arten, die zu generieren sind, beruhend auf den folgenden syntaktisch
analysierten Schlüsselworten
von Sätzen
von Generierbefehlen 56.
-
Das Schlüsselwort Operation weist den
Generierprozessor 52 darauf hin, dass er den generierten Code
als eine oder mehrere Operationen für den gegenwärtigen Klassenkontext
verarbeiten muss. Der Generierprozessor 52 fügt den generierten
Code, der mit dem wahlweisen Schlüsselwort declaredAs verbunden
ist, dem Attribut declartionText des neu erzeugten Operationsknotens
zu. Der Generierprozessor 52 fügt den generierten Code, der
mit dem wahlweisen Schlüsselwort
declaredAs verbunden ist, dem Attribut definitionText des gleichen
neu generierten Operationsknotens zu.
-
Das Schlüsselwort classDeclaration zwingt
den Generierprozessor 52 zur Verarbeitung des generierten
Code als Klassen-Deklaration
für den
gegenwärtigen
Klassenkontext. Dieser wird für
Programmiersprachen wie C++ zum Packen des Code in der Kopfdatei
benutzt. Der Generierprozessor 52 fügt den generierten Code dem
Attribut declartionText zu, das mit dem gegenwärtigen Klassenkontext verbunden
ist (Schritt 92).
-
Das Schlüsselwort classDefinition weist
den Generierprozessor 52 an, den generierten Code als Klassendefinition
für den
gegenwärtigen
Klassenkontext zu verarbeiten. Dieser wird von jeder Programmiersprache
dazu benutzt, die Attribut- und Operationen-Definitionen zu gruppieren,
die zu der Klasse gehören
(wie in C++ und JAVATM). Einige Programmiersprachen
benutzen classDefinition nur zum Gruppieren des Namens ihrer Attribute
mit der damit verbundenen Klasse (wie in SmallTalk). Der Generierprozessor 52 fügt den generierten
Code dem Attribut definitionText zu, das mit dem gegenwärtigen Klassenkontext
verbunden ist (Schritt 92).
-
Das Schlüsselwort packageDefinition
weist den Generierprozessor 52 an, den generierten Code
als Paketdefinition für
den gegenwärtigen
Paketkontext zu verarbeiten. Programmiersprachen wie C++ verwenden
keine Paketdefinitionen, weil der Code in Dateien extrahiert wird,
die nur eine Klasse pro Datei benutzen. Programmiersprachen wie
JAVATM oder SmallTalk benutzen sie jedoch.
Der Generierprozessor 52 fügt den generierten Code dem
Attribut definitionText zu, das mit dem gegenwärtigen Paketkontext verbunden
ist (Schritt 92).
-
Der Entwickler muss seine Sätze von
Generierbefehlen 56 in der nachstehenden Folge schreiben. Erstens
könnten
die Sätze
von Generierbefehlen, die das Schlüsselwort classDeclaration oder
classDefinition benutzen, in beliebiger Reihenfolge vorgeschrieben
werden, jedoch müssen
sie sich vor solchen befinden, die das Schlüsselwort operation oder packageDefinition
aufweisen. Dann müssen
Sätze von
Generierbefehlen, die das Schlüsselwort
packageDefinition benutzen, denjenigen vorausgehen, die das Schlüsselwort
operation benutzen. Schließlich
werden Sätze
von Generierbefehlen, die das Schlüsselwort operation benutzen,
eingeschlossen.
-
Der Generierprozessor 52 generiert
einen Fehler, wenn eins der vorgenannten Schlüsselworte sich nicht in der
richtigen Reihenfolge befindet.
-
In Schritt 98 kontrolliert der Generator,
ob der Code zum Generieren eine neue Komponente generiert. Falls
ja, wird ein neuer Knoten 99 generiert. Drei verschiedene
Knoten können
generiert werden: ein neuer Knoten für eine abgeleitete Klasse,
ein neuer Knoten für
eine abgeleitete Schnittstelle und ein neuer Knoten für ein abgeleitetes
Attribut. Für
die neuen Knoten kann eine Beschreibung als Anmerkung eingeschlossen werden.
Eine Schnittstellenart, ein konkreter oder abstrakter Wert und ein
Endwert können
ebenfalls eingeschlossen werden. Bei einer abgeleiteten Klasse und
Schnittstelle kann eine Klassen-Positions- klausel, eine Superklassen-Positionsklausel,
eine Schnittstellenklausel definiert werden. Bei einem abgeleiteten
Attribut kann ein transienter Wert, ein flüchtiger Wert, eine Attributart,
eine Attribut-Inhaltsklausel und ein Attribut-Klasssenname eingeschlossen
werden.
-
Wenn der zu generierende Code keinen
neuen Knoten erzeugt, wird eine Kontrolle der zu generierenden Code-Art
in Schritt 90 durchgeführt.
Der Generierprozessor 52 unterscheidet die verschiedenen
Sätze von Generierbefehlen
beruhend auf dem syntaktisch analysierten Schlüsselwort.
-
Wenn Schritt 91 ausgeführt wird,
bestimmt der Generierprozessor 52, ob er eine oder nur
eine Operation pro Klasse erzeugen muss, beruhend auf der Abwesenheit
einer Operation-Namenvariablen.
Eine Operation-Namenvariable ist ähnlichen wie eine Klassen-Namenvariable,
weil jedes Vorkommen der Kette %1 in der Operation-Namenvariablen
von einem gelieferte Wert ersetzt wird. Der Einzel- und variable
Produktionsprozess wird genauer unter Bezugnahme auf 5c bzw. 5e beschrieben.
-
In Schritt 92 speichert der Generierprozessor 52 den
generierten Quellcode vom Cache-Speicher im gegenwärtigen Kontextknoten.
Das zum Generieren des Quellcode im Cache benutzte Verfahren wird
genauer mit der Auflösung
der variablen Operationen unter Verwendung von 5e beschrieben.
Wenn der gegenwärtigen
Satz von Generierbefehlen ein Schlüsselwort packageDefinition
aufweist, ist der gegenwärtige
Kontextknoten ein Paketknoten. Wenn der gegenwartige Satz von Generierbefehlen
ein Schlüsselwort
classDefinition oder classDeclaration aufweist, ist der gegenwärtige Kontextknoten
ein Klassen-Knoten.
-
In Schritt 93 bestimmt der Generierprozessor 52,
ob es einen anderen Zielknoten gibt, der mit dem gegenwärtigen Satz
von Generierbefehlen verarbeitet werden soll und verarbeitet ihn
in Schritt 95.
-
In Schritt 94 bestimmt der Generierprozessor 52,
ob ein weiterer Satz von Generierbefehlen zu verarbeiten ist und
verarbeitet ihn in Schritt 96.
-
Der Generierprozessor 52 hält die Codegenerierung
an, wenn der erste Fehler gefunden wird und bittet die Codegenerator-Benutzerschnittstelle,
den Fehler im Kontext in einem Satz von Generierbefehlen mit dem
Zeichen für
den Fehler anzuzeigen. Es tritt ferner ein Fehler auf, wenn der
Generierprozessor 52 die Generier- und Extraktoroptionen 57 anhand
des gegenwärtigen
Satzes von Generierbefehlen prüft
oder anhand eines der gelie ferten Werte und wenn das Ergebnis nicht
gültig
ist.
-
Nachdem der Generierprozessor 52 die
Codegenerierung erfolgreich abgeschlossen hat, ruft das Frontend-Werkzeug 49 den
Quellcode-Extraktor 59 auf, um den generierten Quellcode 60 anhand
der Knoten, die im abstrakten Syntaxbaum 58 definiert sind,
abzurufen. Jeder Quellcode-Extraktor 59 hat seine eigene
Art zum Exportieren von Code in eine Datei und liest die Generier-
und Extraktoroptionen 57, bevor mit dem Extrahierverfahren
begonnen wird (Schritt 97).
-
Die vom Generator ausgeführten Schritte
werden nachstehend anhand von drei Beispielen in C++, JAVATM und SmallTalk erklärt.
-
Der Quellcode-Extraktor 59 führt in C++
die folgenden Schritte aus, um den generierten Code zu extrahieren.
Zuerst erzeugt er das Include-Unterverzeichnis beruhend auf dem
in den Generier- und Extraktoroptionen 57 angegebenen Wert.
Das Verzeichnis enthält
die Kopfdateien (Dateinamen, die mit der Extension hpp enden). Zweitens
erzeugt es das Source-Unterverzeichnis beruhend auf dem Wert, der
für die
Generier- und Extraktoroptionen 60 angegeben wurde. Dieses
Verzeichnis enthält
die Definitionsdateien (Dateinamen, die mit der Extension cpp enden).
Dann erzeugt es für
jeden Klassencode, der im abstrakten Syntaxbaum 58 gefunden
wird, eine Datei mit der Bezeichnung <className>.hpp in dem Include-Verzeichnis nur, wenn
das Attribut declarationText nicht leer ist und schreibt seinen
Inhalt in die Datei. Es erzeugt eine Datei mit der Bezeichnung <className>.cpp nur dann im Source-Verzeichnis,
wenn ihr Attribut definitionText nicht leer ist und schreibt den
Inhalt in die Datei.
-
Der Quellcode-Extraktor 59 für JAVATM extrahiert den nicht leeren Inhalt des
Attributs definitionText von jeder Klasse und gibt ihn in die Datei
mit dem gleichen Namen wie die Klasse und mit einer .java-Datei-Extension
ein. Erstens generiert er das Unterverzeichnis, in dem die Klasse
definiert wird, beruhend auf einem Wert, der in Generier- und Extraktoroptionen 57 vorgeschrieben
ist. Zweitens extrahiert er den Inhalt des Attri- buts definitionText
seines Paketnamens und schreibt ihn in die Datei. Dann extrahiert
er den Inhalt der Attributs definitionText der Klasse und schreibt
ihn in die Datei.
-
Es ist wichtig zu wissen, dass die
SmallTalk-Umgebung die Definition von Klassen und Operationen unterstützt, indem
eine Textdatei gelesen wird, die ein spezifisches Format mit der
Bezeichnung file out hat und der SmallTalk-Extraktor benutzt sie
beim Extrahieren von Quellcode.
-
Der SmallTalk Quellcode-Extraktor 59 führt folgende
Schritt aus: Erstens erzeugt er ein Verzeichnis file out, beruhend
auf dem in den Generier- und Extraktoroptionen 57 angegebenen
Wert. Zweitens erzeugt er eine Datei pro Paket oder eine Gesamtdatei,
abhängig
von dem in den Generator- und Extraktoroptionen 57 angegebenen
Wert. Dann schreibt der Extraktor für jede Klasse den Inhalt des
Attributs definitionText seines Pakets, wenn er sich von der zuvor
verarbeiteten Klasse unterscheidet, schreibt die gefundene Klassen-Deklaration
in das Attribut declarationText der Klasse, iteriert jede Klasse
in der Reihenfolge ein zweites Mal, um den Inhalt jeder Operationengruppe
zu schreiben und schließlich
schreibt der SmallTalk-Extraktor das Ausrufezeichen "!", um den
SmallTalk-Code und einige Vorspanne abzugrenzen, um anzugeben, ob
eine Operation als eine Klasse oder eine Instanz sowie öffentlich
oder privat definiert ist.
-
Unter Bezugnahme auf die 5c wird nun nachstehend
die konstante Erzeugung beschrieben. Der Entwickler muss die folgenden
Informationen schreiben, wenn er eine Operation pro Zielklasse erstellen
will. Es ist ein Schnittstellenart-Wert für die Operation unter Verwendung
der folgenden Schlüsselwort-Werte
anzugeben: public, private, protected oder package, ein Operationsart-Wert
unter Verwendung eines der Schlüsselwortwerte &instance oder
class, ein Operationsname, ein Kategoriename nach Wahl, der für eine Programmiersprache
wie SmallTalk verwendet wird, eine Anweisungsklausel nach Wahl,
die für
eine Programmiersprache wie C++ verwendet wird und die vom Entwickler
unter Verwendung des Schlüsselwortes
declaredAs angegeben wurde und durch den Einsatz von nur einer codeString
mit einer wahlweisen Liste der Bezugsklassen angegeben wird, die
in der codeString benutzt werden und einer wahlweisen Definitionsklausel,
die vom Entwickler durch Verwendung des Schlüsselwortes definedAS angegeben
und durch die Verwendung von einer oder mehreren codeStrings implementiert
wird, mit einer wahlweisen Liste der Bezugsklassen, die mit jeder codeString
verbunden sind.
-
Der Generierprozessor 52 erhält die syntaktisch
analysierten Informationen (Schritt 100) und erzeugt einen neuen
Operationsknoten (Schritt 101), der dem gegenwärtigen Klassenkontext in Schritt
108 zugefügt wird.
Der Generierprozessor 52 signalisiert keinen Fehler, wenn
die Anweisungs- und Definitionsklausel ausgelassen wird. Eine von
ihnen ist jedoch zu liefern, wenn nutzlose Sätze von Generierbefehlen 56 unnötig sind. Meistens
wird die Anweisungsklausel nur für
Programmiersprachen wie C++ geliefert und die Definitionsklausel
wird stets geliefert.
-
Wenn die Anweisungsklausel geliefert
wird, löst
der Generierprozessor 52 in Schritt 102 die gelieferte codeString
auf, wie zur Beschreibung der mehrfachen codeString-Auflösung beschrieben,
die in der 5f dargestellt ist und
der Generierprozessor 52 erhält den generierten Quellcode
vom Cache und speichert ihn im Attribut declarationText der neu
erzeugten Operation (Schritt 104).
-
Wenn die Anweisungsklausel geliefert
wird, löst
der Generierprozessor 52 in Schritt 105 die gelieferte codeString
auf, wie zur Beschreibung der mehrfachen codeString-Auflösung beschrieben,
die in der 5e dargestellt ist und
der Generierprozessor 52 erhält den generierten Quellcode
vom Cache und speichert ihn im Attribut definitionText der neu erzeugten
Operation (Schritt 107).
-
Für
jeden Satz von Generierbefehlen 56, der sich mit dem Erzeugen
einer Operation befasst, erzeugt das System entsprechend dem syntaktischen
Analysenergebnis eine Operation für jede Zielklasse oder eine Operation
für jedes
qualifizierte Attribut einer jeden Zielklasse.
-
Der Generierprozessor 52 erhält die folgenden
syntaktisch analysierten Informationen (Schritt 111): Schnittstellenart-Wert der
Operation unter Verwendung der folgenden Schlüsselwort-Werte: public, private, protected oder
package, wobei der Operationsart-Wert einen der folgenden Schlüsselwort-Werte
benutzt: &instance
oder &class,
wobei der Name der Operation gefolgt wird von: dem Schlüsselwort
repeatForEach, gefolgt von seiner damit verbundenen Attributfilter-Variablen,
gefolgt vom Schlüsselwort
using, gefolgt von der Attributtext-Variablen (wie in Schritt 116
beschrieben), einem wahlweisen Kategorienamen zum Programmieren
von Sprachen wie SmallTalk, einer wahlweisen Anweisungsklausel zum
Programmieren von Sprachen wie C++, die vom Entwickler unter Verwendung
des Schlusselwortes declaredAs vorgeschrieben werden und durch die
Verwendung von nur einer codeString mit einer wahlweisen Liste der
Bezugsklassen, die im codeString benutzt werden und einer wahlweisen
Definitionsklausel, die vom Entwickler unter Verwendung des Schlüsselwortes
definedAs vorgeschrieben werden und die durch die Verwendung von
einer oder mehreren codeStrings mit einer wahlweisen Liste der Bezugsklassen,
die mit jeder codeString verbunden sind, implementiert werden.
-
Der Generierprozessor 52 erhält den Attribut-Teilsatz,
der den gegenwärtigen
Klassenkontextknoten verwendet und die gelieferten Attributfilter-Variablen
als Auswahlkriterien (Schritt 112). Eine Attributfilter-Variable
besteht aus einer Kombination der folgenden Schlüsselworte: dem Schlüsselwort &attribute, gefolgt
von einem Auswahlkriterien-Schlüsselwort,
beruhend auf dem gegenwärtigen
Wert der Schnittstellenart des Attributs wie der Wert all, private,
public, protected, package und gefolgt von einem Auswahlkriterien-Schlüsselwort beruhend
auf dem gegenwärtigen
Wert der Attributart, wie der Wert instance, class oder classAndInstance
und gefolgt von einem wahlweisen Auswahlkriterium unter Verwendung
eines der folgenden Schlüsselwortsätze: havingdefaultValue,
für ein
Attribut mit einem definierten Wert, der mit der wahlweisen Eigenschaft
defaultValue, havingtypedef verbunden ist, für ein Attribut mit einem definierten
Wert, der mit der wahlweisen Eigenschaft mit der Bezeichnung typedef,
of type verbunden ist, gefolgt von einem gelieferten Klassennamen.
-
Der sich ergebende Attribut-Teilsatz,
den der Generierprozessor 52 liefert, besteht aus null
oder mehr Attributen, die die gelieferten Auswahlkriterien erfüllen.
-
Der Generierprozessor 52 stellt
fest, ob der Attribut-Teilsatz
leer ist (Schritt 113) und falls er leer ist, wird keine Operation
für den
gegenwärtigen
Klassenkontext erzeugt. Wenn er nicht leer ist, wird der erste Attributknoten
(Schritt 114) als gegenwärtigen
Knotenkontext verarbeitet (Schritt 115).
-
In Schritt 116 erhält der Generierprozessor 52 den
Operationsnamen durch Ersatz aller Vorfälle der Kette %1 in der Operationsnamen-Variablen
mit dem Eigenschaftswert, der mit der gelieferten Attributkontextvariablen
und dem gegenwärtigen
Knotenkontext verbunden ist. Eine Attributkontextvariable wird durch
das Schlüsselwort &%attribute angezeigt,
gefolgt von einem der folgenden Schlüsselworte, die einen ihrer
Bezeichner beschreiben: Name ist eine Kette, die einen Attributnamen
darstellt, interfaceType ist eine Kette public, private, protected
oder package. attributeClassName oder className sind Synonyme und
sie sind eine Kette, die den Namen der Attributart darstellt. commentDescription
ist eine Kette, die die Beschreibung des Attributs darstellt. defaultValue
ist eine Kette, die die aufgelöste
codeString darstellt, die benutzt wird, um den vorgegebenen Wert
des Attributs zu implemtieren. nameAsClassName ist wie Name mit
einem großen
Anfangsbuchstaben. typedef ist eine Kette, die die aufgelöste codeString
darstellt, die zum Implementieren eines erforderlichen Konstrukts
typedef benutzt wird. defaultValueOrSpace ist wie defaultValue.
Wenn er jedoch eine Leerstelle darstellt, wird kein defaultValue
für das
Attribut definiert. attributeContentsClassName ist eine Kette, die
den className von Elementen im Attribut darstellt, wenn das Attribut
eine Sammlung ist. typeAsStaticOrSpace ist eine Kette, die den Wert
static darstellt, wenn das Attribut ein Klassen-Attribut ist und der Wert eine Leerstelle,
wenn es sich um ein Instanz-Attribut handelt. declaredClassName
ist eine Kette, die den Klassennamen darstellt, zu dem das Attribut
gehört.
-
Der Wert einer Attributkontextvariablen
wird gefunden, indem der Wert des Bezeichners des gegenwärtigen Attributknoten-Kontexts extrahiert
wird.
-
Offensichtlich werden alle reservierten
Worte als Beispiele angezeigt. Andere reservierte Worte könnten benutzt
werden, ohne die grundsätzliche
Operation dieses bevorzugten Ausführungsbeispiels der vorliegenden
Erfindung zu ändern.
-
Der Generierprozessor 52 benutzt
den vorherigen Knotenkontext als den gegenwärtigen Knotenkontext (Schritt
117). Der gegenwärtige
Knotenkontext ist jetzt der gegenwärtige Klassenkontext, der in
der b hergestellt wurde.
-
Zur besseren Lesbarkeit sind die
Schritte 118 bis 125 mit Schritt 101 bis 108 identisch, denn wenn
einmal die Operationsnamen-Variable vom Generierprozessor 52 verarbeitet
wurde (Schritt 116), entspricht sie einer konstanten Erzeugung.
-
In Schritt 125 stellt der Generierprozessor 52 fest,
ob es einen anderen Attributknoten vom Attribut-Teilsatz gibt. Falls
ja, wird der nächste
Attributknoten verarbeitet (Schritt 126). Falls nicht, kehrt er
zum Ausgangspunkt in der 5b zurück.
-
Der Generierprozessor 52 generiert
einen Quellcode, der mit dem Attribut definitionText eines Pakets, einer
Klasse oder einem Operationsknoten verbunden ist, wie in der 5e dargestellt.
-
In Schritt 130 erhält der Generierprozessor 52 die
erste codeString aus der codeString-Liste die vom gegenwärtigen syntaktisch
geprüften
Satz von Generierbefehlen vorgeschrieben wurde. Dann verarbeitet
er ihn wie eine einzige codeString-Auflösung,
wie in der 5f dargestellt.
-
Er fügt die aufgelöste codeString
dem Cache hinzu (Schritt 131) und stellt fest, ob eine weitere codeString
von der Liste zu verarbeiten ist (Schritt 132). Wenn es eine weitere
gibt, holt sie der Generierprozessor 52 (Schritt 133) und
verarbeitet sie wie eine einzelne codeString-Auflösung. Wenn
es keine gibt, gibt er den generierten Quellcode aus dem Cache zurück.
-
5f und 5h enthalten die Ablaufdiagramme
für die
Auflösung
eines codeString.
-
In 5f stellt
der Generierprozessor 52 fest, ob die gegenwärtigen codeString
bereits aufgelöst
ist, indem er in das codeString-Lexikon nachschaut, um festzustellen,
ob sich dort eine Eintragung für
den gelieferten codeString-Namen befindet (Schritt 135), dem eine
Kette zugewiesen wurde. Der Entwickler könnte unter Verwendung des Schlüsselwortes &blockOfCode, gefolgt
von einem Namen, einen Namen für
die codeString liefern, wenn er sie definiert. Wenn sie aufgelöst ist,
erhält
der Generator seinen Wert aus dem codeString-Lexikon (Schritt 136).
Wenn es sich nicht um eine aufgelöste codeString handelt, entscheidet
er, ob die codeString eine konstante codeString ist, indem er die
Abwesenheit der Kontextvariablen feststellt (Schritt 137).
-
Die Klassenkontextvariable und Attributkontextvariable
wurden berücksichtigt,
um einen abgeleiteten Klassennamen bzw. einen abgeleiteten Operationsnamen
von einem Klassenvariablen-Namen
bzw. einem Operationsvariablen-Namen zu erhalten. Sie gelten in
der gleichen Art und Weise wie eine parametrisierte codeString.
-
Insgesamt gibt es fünf Kontextvariablen-Arten,
wie nachstehend aufgeführt:
die Klassenkontextvariable, die Attributkontextvariable, die Operationskontextvariable,
die Paketkontextvariable und die codeString-Kontextvariable.
-
Eine Operationskontextvariable wird
vom Schlüsselwort &operation dargestellt,
gefolgt von dem folgenden Schlüsselwort,
das einen seiner Bezeichner beschreibt: definitionText ist eine
Kette, die den Inhalt des Attributs definitionText darstellt, das
mit der Operation verbunden ist. declaration Text ist eine Kette,
die den Inhalt des Attributs declarationText darstellt, der mit
der Operation verbunden ist.
-
Eine Paketkontextvariable wird vom
Schlüsselwort &package, gefolgt
von einem der folgenden Schlüsselworte
dargestellt, das einen ihrer Bezeichner beschreibt: name ist eine
Kette, die den Paketnamen darstellt. parentName ist eine Kette,
die den Paketnamen ihrer Mutter darstellt. commentDescription ist
eine Kette, die die Beschreibung des Pakets darstellt.
-
Eine codeString-Kontextvariable ist
eine andere codeString, die aufzulösen ist, um als ein gelieferter Wert
benutzt zu werden, um die Bindung mit der gegenwärtigen codeString zu bewirken.
-
In Schritt 138 stellt der Generierprozessor 52 fest,
ob die Kontextvariablen mit dem Schlüsselwort with geliefert wurden.
Wenn dies so ist, ist die Auflösung
einer parametrisierten codeString erforderlich, wie in der 5g dargestellt. Falls es
nicht der Fall ist, bedeutet dies, dass die Kontextvariablen mit
dem Schlüsselwort repeatForEach
geliefert wurden und in den Details mit der AuflÖsung einer repetitiven parametrisierten
codeString berücksichtigt
werden, wie in der 5h gezeigt.
-
Nachdem eine codeString aufgelöst wurde,
bestimmt der Generierprozessor 52, ob die gegenwärtige codeString
einen gelieferten Namen hat (Schritt 139). Falls ja, fügt der Generierprozessor 52 eine
Eintragung im codeString-Lexikon ein, wobei der gelieferte codeString-Name
als Schlüssel
verwendet wird und die aufgelöste
codeString als Wert (Schritt 140).
-
In Schritt 141 stellt der Generierprozessor 52 fest,
ob irgendeine Bezugsklasse mit der gegenwärtigen codeString geliefert
wurde. Falls ja (Schritt 142), werden die Bezugsklassen in den gegenwärtigen Knotenkontext
aufgenommen. In Schritt 143 wird festgestellt, ob der gegenwärtige Knotenkontext
ein Klassen-Knoten ist. Falls nicht, wird die Klasse, auf die Bezug
genommen wird, dem Eltern-Knoten rekursiv zugefügt, bis der Eltern-Knoten ein
Klassen-Knoten ist (Schritt 144).
-
Nachstehend wird nun die Auflösung einer
parametrisierten codeString beschrieben, die in der 5g dargestellt ist. Der Generierprozessor 52 erhält die erste
Kontextvariable, die von den anderen durch ein Komma getrennt ist
(Schritt 150). Er stellt fest, ob die gegenwärtige Kontextvariable eine
weitere codeString ist (Schritt 151). Falls ja, wird sie unter Verwendung
des in der 5f dargestellten Verfahrens
auf gelöst
und die aufgelöste
codeString wird als der gelieferte Wert verarbeitet (Schritt 152).
Wenn die Kontextvariable eine weitere codeString ist, holt sie den
gelieferten Wert von der Kontextvariablen durch Extrahieren des
Wertes ihres Bezeichners aus dem gegenwärtigen Knotenkontext (Schritt
153). Der Generierprozessor 52 bindet das Vorkommen der
Kette %n, wobei n ein ganzer Wert von 1 bis 9 ist, mit dem bereits
angegebenen gelieferten Wert (Schritt 154 bis einschließlich 156).
Wenn es mehr als eine Kontextvariable gibt, werden die Variablen
durch ein Semikolon getrennt.
-
In der 5h wiederholt
sich der Auflösungsprozess
einer codeString so oft, wie sich ergebende Knoten von dem gegenwärtigen Knotenkontext
für die
angegebene Filtervariable beschrieben wurden. Diese Art codeString
ist nützlich,
wenn das, was gewünscht
wird, nur das Einsetzen einer codeString ist, wenn die Filtervariable
keinen leeren Satz für
den gegenwärtigen
Knotenkontext zurückgibt.
-
In Schritt 160 könnte der Generierprozessor 52 die
Syntaxanalyse einer der folgenden Filtervariablen vornehmen: Attributfilter-Variable,
externe Eigenschaften-Variable. Operationsfilter-Variable, Superklassenfilter-Variable,
Bezugsklassenfilter-Variable.
-
Die externe Eigenschaften-Variable
besteht aus einer Kombination der folgenden Schlüsselwörter: Operation of &dependentConcept,
gefolgt von einem Konzeptnamen.
-
Eine Operationsfilter-Variable besteht
aus der Kombination folgender Schlüsselwörter: dem Schlüsselwort &operation, gefolgt
von einem Schlusselwort Wahlkriterien, beruhend auf dem gegenwärtigen Wert
der Schnittstellenart einer Operation wie der Wert all, private,
public, protected, package und gefolgt von einem Schlüsselwort
Auswahlkriterien, berühend
auf dem gegenwärtigen
Wert der Operationsart, wie der Wert instance, class oder classAndInstance.
-
Die Superklassenfilter-Variable ist
mit dem Symbol &superclass
gebildet.
-
Die Bezugsklassenfilter-Variable
ist mit einer Kombination der folgenden Schlüsselwörter: &referredClass notKnownByCurrent,
gefolgt vom Schlüsselwort
package oder class, gebildet.
-
In Schritt 161 holt der Generierprozessor 52 den
sich ergebenden Knoten-Zielsatz, beruhend auf der gelieferten Filtervariablen,
die zum Auswahlkriterium gegen den gegenwärtigen Knotenkontext wird.
In Schritt 162 stellt er fest, ob er einen Code nicht generieren
muss und falls dies der Fall ist, erfolgt die Bestätigung einer leeren
Kette. Er verarbeitet den ersten Knoten als den neuen Knotenkontext
(Schritt 163) und fügt
die aufgelöste
codeString dem Cache zu (Schritt 164). Er stellt fest, ob es einen
anderen von der sich ergebenden Sammlung resultierenden Knoten gibt
(Schritt 165) und verarbeitet ihn (Schritt 166). Er gibt den sich
ergebenden generierten Code aus dem Cache zurück.
-
6 ist
die Darstellung eines Verfahrens nach einem bevorzugten Ausführungsbeispiel
der vorliegenden Erfindung. Dabei werden neue Sätze von Generierbefehlen 170 erzeugt.
Die zum Generieren erforderlichen Parameter werden definiert 171 und
Codesegmente werden generiert 172. Diese Codesegmente könne gruppiert
werden, um ein vollständiges
Programm zu bilden.
-
7 ist
die Darstellung einer weiteren Methode nach dem bevorzugten Ausführungsbeispiel
der vorliegenden Erfindung. Eine Modell-Deklaration wird vorgeschrieben 175.
Diese modelliert die Struktur eines Systems, indem Objekte im System,
Beziehungen zwischen den Objekten sowie die Attribute und Operationen dargestellt
werden, die jede Objektklasse charakterisieren. Das Modell liefert
die erforderlichen Parameter für die
Generation. Die folgenden Einheiten sind bei der Spezifikation einer
Modell-Deklaration
zu erzeugen: Paket, Schnittstelle, Klasse, Superklasse, externe
Eigenschaften, Verbindung zu den teilnehmenden Rollen, Attributen,
Operationen und Unterklassen. Dann wird ein Satz von Generierbefehlen 176 entweder
erzeugt, personalisiert oder mit einer Generierbefehlsatz-Gruppe
geordnet. Schließlich
wird der gesamte Computer-Quellcode erzeugt 177 und ist
nicht vom Benutzer zu ändern
oder anzupassen.
-
8 ist
die Darstellung eines Verfahrens nach einem weiteren bevorzugten
Ausführungsbeispiel
der vorliegenden Erfindung, bei dem der von einem bevorzugten Verfahren
generierte Quellcode geändert
und neu generiert wird, ohne dass die übermäßige Manipulation des Code
durch den Benutzer erforderlich ist. Der Code wird entweder 180 in
einem Texteditor oder einer Benutzerschnittstelle zurückgeholt.
Der Benutzer bewertet, welche Änderungen
im Quellcode erforderlich sind 181. Zeiger zu den Generierbefehlen
werden erhalten 182. Falls erforderlich, werden auch Zeiger
zur Modell-Deklaration und den Generierparametern erhalten. Dann
wird eine Änderung 183 an
mindestens einem Satz von Generierbefehlen, der Modell-Deklaration
und den Generierparamtern (Filtervariablen, Kontextvariablen und
Anzahl Codeblocks jeder Art, die benutzt wurden) vorgenommen. Diese Änderung
kann automatisch oder manuell vom Benutzer vorgenommen werden. Die
vorgenommene Änderung
könnte
aus der Änderung
der Reihenfolge oder der Umstellung der Satze von Generierbefehlen
bestehen, Wenn schließlich
die entsprechenden Änderungen
vorgenommen wurden, kann der Computer-Quellcode generiert werden 184.
-
9 ist
ein Blockdiagramm der Vorrichtung nach dem bevorzugten Ausführungsbeispiel
der vorliegenden Erfindung. Ein Editor 185 wird benutzt,
um Satze von Generierbefehlen zu erzeugen oder zu ändern. Diese
Sätze werden
im Manager 186 verwaltet, wenn sie geordnet werben können. Ein
Kontext-Informationseditor 193 ist ebenfalls eingeschlossen.
Die Sätze
von Generierbefehlen und die Kontextinformationen werden an den
Quellcodegenerator 187 gesandt, der die Sätze von
Generierbefehlen unter Verwendung der Kontextinformationen verarbeitet
und den Quellcode in der Quellcode-Ausgabe generiert 188.
Die wahlweise Sprachendatenbank 189 kann Optionssätze liefern,
um den Generator 187 zu personalisieren, um eine Programmiersprache
zu unterstützen.
Ein wahlweiser Zeiger-Datengenerator 190 kann auch eingeschlossen
werden, der die Zeigerdaten 191 generiert, die bestimmen,
welcher Satz von Generierbefehlen während der Generierung benutzt
wurde. Er kann auch feststellen, welcher Teil der Kontextinformationen
beim Generieren benutzt wurde. Es kann eine Kombination aus Zeiger
und Quellcode-Ausgabe 192 generiert werden. Die Zeigerdaten können als
Anmerkungszeilen im ganzen generierten Quellcode oder als getrennte
Datei zur Einsicht eingeschlossen werden.
-
10 ist
die Darstellung einer weiteren Vorrichtung nach dem bevorzugten
Ausführungsbeispiel
der vorliegenden Erfindung. Es wird eine Kombination aus Zeigeranzeige
und Quellcode-Editor 195 geliefert. Wenn Änderungen
am zuvor generierten Quellcode vorzunehmen sind, kann der Generierbefehl-Manager 196 die
mit einem Zeiger versehenen Generierbefehle finden und sie im Generierbefehl-Editor 197 anzeigen.
Falls erforderlich, kann auch ein Zeiger zur Modell-Deklaration
benutzt werden um die Modell-Deklaration
in einem Modelleditor 201 zu finden. Die Änderungen
in den Generierbefehlen und in der Modell-Deklaration können manuell
oder automatisch anhand der Änderungen
erfolgen, die am zuvor generierten Quellcode vorgenommen wurden.
Dann werden die Sätze
von Generierbefehlen und die Modell-Deklarationen an den Quellcodegenerator 198 gesandt,
der eine Quellcodeausgabe 199 generiert. Es ist jedoch
wichtig, dass alle Änderung, die
direkt am Quellcode vorgenommen wurden, in den Sätzen von Generierbefehlen und
in der Modell-Deklaration reflektiert werden, falls erforderlich,
um sicherzustellen, dass die neueste Version des Quellcode, die
benutzt wurde, jederzeit unter Verwendung der letzen Version der
Sätze von
Generierbefehlen und der Modell-Deklaration
neu generiert werden kann. Auch hier können wahlweise Sprachendatenbanken 200 eingeschlossen
werden. Ein wahlweise bereitstellbarer Zeigerdaten-Generator 202 kann
auch zugefügt
werden, um eine kombinierte Ausgabe aus Zeigerdaten und Quellcode 203 zu
erhalten.
-
Weitere Einzelheiten zur Syntax,
wie in den 13 und 14 dargestellt,
sind erforderlich, damit die Syntax einem bevorzugten Ausführungsbeispiel
der vorliegenden Erfindung genau entspricht.
-
In der Fig. 13 muss
in der Definition der packageNameClass der packageName1 genau qualifiziert
werden. packageName2 ist in JAVATM nie zu
benutzen.
-
In der Definition der interfaceClause
und der classClause kann der interfaceName und der className kein
Punktzeichen enthalten.
-
In der Definition superclassesClause
bedeutet das Zeichen ";" dass mehr als eine Superklasse in die Schnittstelle
eingeschlossen werden könnte.
-
In der Definition operationName muss
der Operation-Signatur-Selektor
(anstatt des Operationsnamens) die ganze Operation-Signatur enthalten,
die die folgenden Informationen enthält:
-
- – interfaceType
- – statisch
(wahlweise)
- – synchronisiert
(wahlweise)
- – maschinenspezifisch
(wahlweise)
- – zurückgegebene
Art oder Leerstelle (falls keine)
- – Operationsnamen
- – '('
- – Eine
Parameterliste, beginnend mit der Parameterart, gefolgt vom Parameternamen
- – ')'
-
In der 14 wird
in der Definition generatorInstruction das Schlüsselwort needToBeGenerated
benutzt, wenn eine existierende classReceiverExpression generiert
wird, die vom Modellier-Werkzeug
vorhanden war. Als vorgabe wird kein existierender Knoten (Klasse
oder Schnittstelle) generiert und jeder neue Knoten wird generiert.
-
Wenn in der Definition die attributeSubExpression, &attribute enthält, ohne
etwas anderes zu benutzen, bedeutet dies, dass wir den Satz von
Generierbefehlen verarbeiten müssen,
wenn die Schnittstelle oder Klasse Attribute enthält. In der
Definition singleConstantCreationDeclaration und in der Definition
der variableCreationDeclaration, wird die definitionClause benutzt,
um den Superklassennamen zu definieren, wenn Schnittstellen und
Klassen erzeugt werden, und um ihren Vorgabewert anzugeben, wenn
Attribute erzeugt werden.
-
In der Definition variableCreationDeclaration
ist darauf hinzuweisen, dass die variableCreationDeclaration nur
eine oder mehrere Positionen erzeugt, wenn sie mit den Klauseln
"with" oder "repeatForEachstring benutzt wird. Der Operationsname
der variableNameClause muss die ganze: Operationssignatur enthalten, die
folgende Informationen enthält:
-
- –
- – interfaceType
- – statisch
(wahlweise)
- – synchronisiert
(wahlweise)
- – maschinenspezifisch
(wahlweise)
- – zurückgegebene
Art oder Leerstelle (falls keine)
- – Operationsnamen
- – '('
- – Eine
Parameterliste, beginnend mit der Parameterart, gefolgt vom Parameternamen
- – ')'
-
In der Definition variableNameClause
ist die codeStringStatementClause die einzige Stelle, wo die groupContextVariable
benutzt werden könnte.
-
Der variable Name darf keine Leerzeichen
enthalten, könnte
sich aber auf mehr als eine Kontextvariable beziehen.
-
Der interfaceNameFilter könnte mehr
als eine Schnittstelle zurückgeben.
-
Der constantName muss die ganze Operationssignatur
enthalten, die folgende Informationen enthält:
-
- – interfaceType
- – statisch
(wahlweise)
- – synchronisiert
(wahlweise)
- – maschinenspezifisch
(wahlweise)
- – zurückgebener
Art oder Leerstelle (falls keine)
- – Operationsnamen
- – '('
- – Eine
Parameterliste, beginnend mit der Parameterart, gefolgt vom Parameternamen
- – ')'
-
In der Definition filterVariable
ist darauf hinzuweisen, dass der Vorgabekontext für den Generator
stets der referencesNode ist, der die basedClass für eine derivedClass
ist und als solcher für
eine basedClass. &superclass
und &subclass
erstrecken sich nur auf eine Stufe vom Vorgabekontext. &subclass könnte mehr
als eine Klasse zurückgeben. &implementedInterface
wird nur für
die Klassendefinition benutzt.
-
In der Definition groupOfFilterVariable
erzeugt diese Filtervariable einen Codeblock, der mit der Kontextvariablen
der Bezeichnung &group
verbunden ist.
-
In der Definition associationFilterVariable
bedeutet die Verwendung von &Association,
die eine Rolle ohne etwas anderes spielt, dass die Generierbefehle
verarbeitet werden, wenn die Schnittstelle oder Klasse Assoziationen
enthält.
-
In der Definition externalPropertyContextVariables
fügt das
"+" das baseIncrement, das mit dem BlockOfCode verbunden ist, dem
Wert der externen Eigenschaft zu. Das Zeichen "++" tut das gleiche
und behält das
Ergebnis der Addition als den neuen Wert für das baseIncrement.
-
In der Definition communContextVariable
fügt das
Zeichen "#" die Paket-Stelle, die mit dem Inhalt der Kontextvariablen
verbunden ist, der Klausel referredlocation hinzu, die mit ihrem
BlockOfCode verbunden ist.
-
In der Definition filterVariableContextVariables
muss der Benutzer einen getrennten BlockOfCode erzeugen, wenn er
numberOfItems benutzt, weil es sich um die einzige Kontextvariable
handelt, die nicht für
jeden sich ergebenden Code, der mit dem gegenwärtigen Term Filtervariable
verbunden ist, iteriert werden muss. Der Ausgangswert des Index
ist das Grundinkrement seiner enthaltenen iterativen codeString.
-
BEISPIEL 1
-
Die vorliegende Erfindung wird unter
spezifischer Bezugnahme auf das folgende Beispiel leichter verständlich,
das angegeben wird, um die Erfindung zu erklären, und zwar eher als ihren
Schutzumfang zu begrenzen. Der von diesem Beispiel abgedeckte Code
reicht nicht aus, um die Applikation zu betreiben, jedoch erhält man eine
Vorstellung von der Art des Code, der generiert werden könnte.
-
Nach einem bevorzugten Ausführungsbeispiel
der vorliegenden Erfindung gestattet der Generator für JAVATM die Generierung von JAVATM-Code
für ein
bestimmtes Gerüst.
Dieses Beispiel zeigt die Generierung von Enterprise JavaBeansTM (EJB), wobei der zwischen den Applikationskomponenten
und ihren verbundenen Daten, die in der Datenbank gespeichert sind,
ein Nachhaltigkeitsservice implementiert wird. Das Modell und der
Applikationscode, die von diesem Beispiel abgedeckt werden, stammt
von IBM VisualAge für
JAVATM 2.0, das Code generiert, der EJB-Spezifikationen
implementiert. Bedauerlicherweise hindert VisualAge für JAVATM ein Unternehmen daran, ein Modellier-Werkzeug
als Einzelquelle für
Daten für
den generierten Code zu verwenden, weil sie ihre eigene grafische
Benutzerschnittstelle zum Erfassen von Implementationsdaten hat.
-
Der Generator nach dem bevorzugten
Ausführungsbeispiel
der vorliegenden Erfindung kann den gleichen Code anhand eines Modells
erzeugen, wobei die Wartungsarbeiten reduziert werden, da der durch
den Generator entstehende Code laut dem bevorzugten Ausführungsbeispiel
keine manuelle Intervention benötigt, wenn
er einmal generiert worden ist. Der Generator benutzt Sätze von
Generierbefehlen, um die Klassen und Verfahren, die zu generieren
sind, zu generieren und anzupassen.
-
Das folgende Muster-Modell, das mit
Rational Rose 98i Enterprise Edition entstand, definiert
die Kernleistungen für
den Einsatz in Banken. Die Darstellung erfolgte in der 11 und die Anweisung, die
dieser entspricht, ist in der TABELLE 1 dargestellt. Durch Einsatz
der Eigenschaften, die durch den Generator nach dem bevorzugten
Ausführungsbeispiel
zur Verfügung
stehen, wie als Zusatz für
Rational Rose 98i implementiert, enthält das vorgenannte Modell die
Definition der externen Eigenschaften, die in diesem Fall das Umsetzen der
einzelnen Attribute von Feldern ermöglichen, die in der Applikationsdatenbank
enthalten sind. Entwickler können
externe Eigenschaftsgruppen erzeugen und sie einem Klassen-Attributsatz
zuweisen. Nachdem die externen Eigenschaften definiert sind, sind
Werte, die mit diesen Eigenschaften verbunden sind, von den Entwicklern
erreichbar, die Sätze
von Generierbefehlen erstellen.
-
TABELLE
1. Modell-Deklaration
-
-
-
-
GENERIEREN VON EJB-KLASSEN
-
Die im Modell enthaltenen Klassen
werden jeweils zum Produzieren eines entsprechenden Klassensatzes
benutzt, der die Spezifikation Enterprise JavaBeanTM implementiert.
Für jede
Klasse des Modells generiert der Generator für JAVATM die
folgenden abgeleiteten Klassen:
-
- – die
Liste der EJB-Klassen und Schnittstellen;
- – NAMEBean
(für EJB
Bean)
- – NAME
(für externe
EJB-Schnittstelle)
- – NAMEHome
(EJB-Home-Schnittstelle)
- – NAMEKey
(für EJB-Schlusselklasse
oder Feld
- – und
die folgenden Klassen, die die bereits erwähnten EJB-Schnittstellen implementieren:
- – NAMEImpl
(für die
Implementation der externen FJB-Schnittstelle)
- – NAMEHomeImpl
(für die
Implementation der externen EJB-Home-Schnittstelle)
- – wobei
Name den Namen der einzelnen Klassen aus dem Modell darstellt.
-
EJB BEAN
-
Einige Sätze von Generierbefehlen, die
zum Generieren dieser abgeleiteten Klassen benutzt werden, sind
in der TABELLE 2 dargestellt.
-
TABELLE
2. SCHABLONE EINS
-
Die Geschäftsverfahren der Entity-Bean-Klasse
definieren, wie Instanzen manipuliert werden können. Die FJB-Bean-Klassen
sind Unterklassen von VapEntityBeanImpl, einer Klasse, die folgende
Standardmethoden für
eine FJB-Bean-Entity implementiert:
ejbActivate | ejbCreate |
ejbLoad | ejbPassivate |
ejbPostCreate | ejbRemove |
setEntityContext | unsetEntityContext |
-
Es wird darauf hingewiesen, dass
es, da die vorstehenden Verfahren von einer Klasse VapEntityBeanImpl
implementiert werden, nicht erforderlich ist, dass die generierten
Klassen diese Verfahren implementieren.
-
Der Generator für JAVATM generiert
die folgenden Verfahren für
die Klasse EJB Bean:
-
- – Für jedes
Attribut einen Satz von Generierbefehlen, der ein Get- und Set-Verfahren
für das
Attribut generiert.
- – Für jede Zielrolle
eine Verbindung, die navigierbar ist und die eine Kardinalität mit einer
Obergrenze von '1' hat, einen Satz von Generierbefehlen, der Get-
und Set-Verfahren für
die Rolle generiert
- – Für jede Zielrolle
eine Verbindung, die navigierbar ist und die eine Kardinalität mit einer
Obergrenze von 'n' hat, einen Satz von Generierbefehlen, der ein
Get- und Set-Verfahren für
die Rolle generiert sowie ein Get- und Set-Verfahren für die Klassen
Link und Key, z. B. setBranchLink und setBranchKey im Fall der Branch-Rolle.
- – Ein
initialisizeRelationship-Verfahren, das die Objekte initialisiert,
die die Rollen verkapseln.
- – Eine
NAMEImpl-Klasse zur Implementation von EJBObject.
-
Die Sätze von Generierbefehlen für einige
dieser generierten Teile sind in den TABELLE 3 und TABELLE 4 aufgeführt.
-
-
TABELLE
4. SCHABLONE DREI
-
EXTERNE (REMOTE) EJB-SCHNITTSTELLE
-
Ein Client greift auf ein Entity-Object
durch eine externe Schnittstelle (Remote-Schnittstelle) einer Entity-Bean.
Eine externe Schnittstelle definiert die Geschäftsverfahren, die von Kunden
verfügbar
sind. Der Generator für
JAVATM generiert die Verfahren, die in der
externen Schnittstelle zu definieren sind. Daher gibt es:
-
- – Für jedes
Attribut einen Satz von Generierbefehlen, der ein Get- und Set-Verfahren
für das
Attribut generiert
- – Für jede Zielrolle
in einer Verbindung, die navigierbar ist und die eine Kardinalität mit einer
Obergrenze von '1' hat, einen Satz von Generierbefehlen, der ein
Get- und Set-Verfahren für
die Rolle generiert sowie ein Get- und Set-Verfahren.
- – Für jede Zielrolle
eine Verbindung, die navigierbar ist und die eine Kardinalität mit einer
Obergrenze von 'n' hat, einen Satz von Generierbefehlen, der ein
Get- und Set-Verfahren für
die Rolle generiert sowie ein Get- und Set-Verfahren für die abgeleitete
Klasse Link und Key, z. B. setBranchLink und setBranchKey im Fall
der Brauch-Rolle.
-
FJB-HOME-SCHNITTSTELLE
-
Eine Home-Schnittstelle definiert
die von einem Client verwendeten Verfahren zum Erzeugen und Entfernen
von Instanzen des Enterprise-Beans und Erhalten von Metadaten über eine
Instanz. Der Generator für JAVATM enthält:
-
- – Einen
Satz von Generierbefehlen, der das Verfahren Create produziert,
indem als Parameter das Attribut verwendet wird, das den primären Schlüssel darstellt.
- – Einen
Satz von Generierbefehlen, der das Verfahren Find produziert, indem
als Parameter das Attribut verwendet wird, das den primären Schlüssel darstellt.
- – Einen
Satz von Generierbefehlen, der die Zugriffverfahren getROLELiteCollection
für die
Zielrollen produziert, die eine Kardinalität mit einer Obergrenze von
W haben.
- – Einen
Satz von Generierbefehlen, der die Klasse produziert, die die Home-Schnittstelle
implementiert. Der Verfahrensinhalt, der mit einer Methodensignatur
verbunden ist, die in der Home-Schnittstelle erwähnt ist, wird vollständig generiert
und benötigt
keine manuellen Interventionen seitens des Entwicklers.
-
EJB-KLASSE KEY
-
Diese Klasse wird benutzt, um den
primären
Schlüssel
für ein
EJBObject zu erzeugen und zu verwalten. Der mit der Key-Klasse verbundene
generierte Code wird mit folgenden Befehlssätzen generiert:
-
- – Einem
Satz von Generierbefehlen, der den Vorgabe-Constructor generiert
- – Einem
Satz von Generierbefehlen, der einen Constructor mit primaryKey
und LastName als Argumente produziert
- – Einem
Satz von Generierbefehlen, der ein Gleichheitszeichen-Verfahren
produziert
- – Einem
Satz von Generierbefehlen, der ein Hash-Verfahren produziert.
-
KLASSENIMPLEMENTATION
DER EXTERNEN (REMOTE) EJB-SCHNITTSTELLE
-
Sätze
von Generierbefehlen sind erforderlich, um alle Verfahren zu erzeugen,
die für
Klassen mit der Bezeichnung NAMEImpl generiert werden. Als Beispiel
werden alle Verfahren für
die Klasse VapAccountImpl produziert, die im Klasssen diagramm in
der 12 dargestellt wurden und ein
Beispiel für
den generierten Code für
das Verfahren firePropertyChange( ) ist in der TABELLE 10 aufgeführt. Der
zum Generieren eines Teils des firePropertyChange( )-Code benutzten
Satzes von Generierbefehlen wurde in der TABELLE 5 aufgeführt.
-
TABELLE
5. SCHABLONE VIER
-
-
KLASSE ZUM IMPLEMENTIEREN
DER EJB-SCHNITTSTELLE HOME
-
Satze von Generierbefehlen sind erforderlich,
um Verfahren für
Klassen mit der Bezeichnung NAMEHomeImpl zu generieren. Als Beispiel
werden alle Verfahren für
die Klasse VapAccountHomeImpl, wie im Diagramm Klasse in der 12 gezeigt, produziert und ein Beispiel
des generierten Code für
das Verfahren initializeRelatedHomes( ) ist in der TABELLE 11 aufgeführt.
-
FÜR VAPACCOUNT GENERIERTE EJB-KLASSEN
-
12 ist
die Darstellung eines Beispiels für einen Satz Klassen und Schnittstellen,
die für
die Klasse VapAccount generiert werden. Der Generator nach einem
bevorzugten Ausführungsbeispiel
für JAVATM produziert für jede Klasse, die im Modellier-Werkzeug
enthalten ist, einen äquivalenten
Satz Verfahren und Klassen, die abhängig von den damit verbundenen
Attributen und Rollen sind.
-
TABELLE 6 bis 11 sind Darstellungen
von Code, der unter Verwendung der Modell-Deklaration und eines
kompletten Satzes von Generierbefehlen generiert wurde.
-
TABELLE
6. GENERIERTE KLASSENDEFINITION
-
TABELLE
7 GENERIERTE SATZVERFAHREN-SIGNATUR FÜR DIE KLASSE VAPACCOUNT
-
TABELLE
8. FÜR
DEN SATZ FÜR
DAS ATTRIBUT KONTONUMMER IN DER KLASSE VAPACCOUNT GENERIERTER-VERFAHRENSINHALT
-
TABELLE
9. ABGELEITETE KLASSEN
-
TABELLE
10 EINIGE GENERIERTE VERFAHREN (AUSSER GET UND SET)
-
TABELLE
11: EINIGE GENERIERTE VERFAHREN (AUSSER GET UND SET) – FORTSETZUNG:
-
-
-
Obgleich die Erfindung unter besonderer
Bezugnahme auf das im Beispiel dargestellte Ausführungsbeispiel beschrieben
wurde, versteht es sich, dass der Fachmann zahlreiche Modifikationen
desselben finden wird. Daher sind die vorstehende Beschreibung und
die anliegenden Zeichnungen als eine Beschreibung der Erfindung
zu betrachten und nicht als Beschränkung derselben. Die verwendete
Programmiersprache war JAVAS", jedoch kann der Generator auch mit
anderen Sprachen wie C++ und SmallTalk benutzt werden.
-
Obgleich die Erfindung in Verbindung
mit spezifischen Ausführungsbeispielen,
derselben beschrieben wurde, versteht es sich, dass weitere Abanderungen
vorgenommen werden können
und diese Applikationen erstrecken sich auf alle Variationen, Einsätze oder
Anpassungen der Erfindung, wie von den anliegenden Anspruchen beschrieben.