| Teil I - Übersicht | |
2 Kurze Einführung am Beispiel Speichern Unter - Dialog |
|
In diesem Kapitel wird an Hand eines einfachen Beispiels die Tango-Beschreibungsmethodik vorgestellt. Das Beispiel wird Stück für Stück rekonstruiert, dabei werden Sprachelemente erläutert, soweit dies zum Verständnis des Beispiels notwendig ist. Eine detailliertere Besprechung der Tango-Beschreibungsmethodik ist späteren Kapiteln vorbehalten.
2.1 Beispiel: Speichern Unter - Dialog |
|
In den meisten Software-Anwendungen wird über einen Menüpunkt ähnlich Datei | Speichern unter die Möglichkeit zur Speicherung von Arbeitsergebnissen angeboten. Es kann vorausgesetzt werden, dass die prinzipielle Funktionsweise dieses Menüpunktes dem Leser vertraut ist. Eine vereinfachte Version dieser Programmfunktion wird im Folgenden mit Tango beschrieben. Dies ist das klassische Lern-Beispiel, um mit möglichst wenig Aufwand eine Tango-Beschreibung lesen zu können.
Die Beschreibung soll beginnen, wenn ein Anwender den Menüpunkt Datei | Speichern unter ausgewählt hat. Es erscheint ein Dialogfenster.
!#WnSpeichernUnterDialog
.$Inhalt <- EXTERN.{zu speichernde Daten}
.EtDateiMitPfad : [ leer | FormatFalsch | VerzeichnisExistiertNicht |
DateiExistiert | DateiIstNeu ]
.+CR // Return-Taste
=> .@PrüfeSpeichern
.+BtSpeichern
=> .@PrüfeSpeichern
.+BtAbbrechen
=> .WnSpeichernUnterDialog.CLOSE
!@PrüfeSpeichern
=> ? WnSpeichernUnterDialog.EtDateiMitPfad =
= leer
=> .BEEP
= FormatFalsch
=> .USER << "Kein gültiges Dateinamen-Format"
= VerzeichnisExistiertNicht
=> .USER << "Verzeichnis existiert nicht" // Wird nicht automatisch angelegt
= DateiExistiert
=> .? USER << "Datei existiert, überschreiben?" =
= "Ja, überschreiben"
=> .@JetztSpeichern
= "Nein, nicht überschreiben"
=> .WnSpeichernUnterDialog.EtDateiMitPfad.MARKIEREN
.{ganzen Inhalt des Feldes selektieren und Focus drauf setzen}
= "Aktion abbrechen"
=> .NOP
= DateiIstNeu
=> .@JetztSpeichern
!@JetztSpeichern
=> .$DateiMitPfad <- WnSpeichernUnterDialog.EtDateiMitPfad
.$Inhalt <- WnSpeichernUnterDialog.Inhalt
.?{Datei $DateiMitPfad angelegt oder ersetzt mit $Inhalt} =
= "OK, erfolgreich gespeichert"
=> WnSpeichernUnterDialog.CLOSE
= "NOK, etwas ging schief"
=> USER << "Speichern war nicht erfolgreich"
2.2 Erläuterung der Spezifikation |
|
!#WnSpeichernUnterDialog
.$Inhalt <- EXTERN.{zu speichernde Daten}
.EtDateiMitPfad
.+BtSpeichern
.+BtAbbrechen
Jede Tango-Spezifikation beschreibt eine Menge von Eigenschaften des Systems, bezeichnet als Aspekte. Aspekte können lokalisierbare Elemente sein (z.B. ein Bedienknopf auf einer grafischen Oberfläche) oder allgemeine Eigenschaften (z.B. maximale Antwortzeit auf eine Anfrage). Die Aspekte werden aufgezählt und verfeinert durch untergeordnete Aspekte.
Eine Tango-Spezifikation besteht aus einer Folge von Definitionsblöcken, die mit dem Ausrufezeichen ! eingeleitet werden. Die erste Zeile eines Definitionsblocks bezeichnet einen Aspekt, hier das Element WnSpeichernUnterDialog, das in den Folgezeilen des Definitionsblocks durch weitere Aspekte beschrieben wird. Die Unteraspekte sind unter der Kopfzeile eingerückt.
Die Markierung # kennzeichnet einen Container, also ein Element, das aus mehreren anderen Teilen besteht. Jedes Element in der Spezifikation kann aus vielen Teilen bestehen, dies ist keine ungewöhnliche Eigenschaft. Ein Container ist explizit als solcher markiert, weil die Zusammenfassung mehrerer Elemente an dieser Stelle für den Anwender von besonderer Bedeutung ist. Die Kennzeichnung als Container ist optional.
Wn ist ein Spezialisierungsprefix, der ein Fenster (Window) kennzeichnet. Spezialisierungsprefixe sind ein Teil des Aspektnamens. Sie müssen nicht verwendet werden, aber sie bieten die Möglichkeit, das Wesen des Aspekts genauer zu bezeichnen. Es gibt keine verbindliche Liste von Spezialisierungsprefixen, sie können je nach Anwendungsgebiet selbst vergeben werden. Die in diesem Beispiel verwendeten Zwei-Buchstaben-Prefixe sind üblich für die Beschreibung von Software.
Die einzelnen Unteraspekte sind als Aufzählung mit einem führenden Punkt . niedergeschrieben. Die Reihenfolge der Unteraspekte in einer Aufzählung ist nicht signifikant, die Abfolge der Unteraspekte könnte also beliebig vertauscht werden, ohne dass sich an der Aussage der Spezifikation etwas ändert.
Die Markierung + kennzeichnet einen Aktivator. Ein solches Element wird verwendet, um ein Ereignis entgegenzunehmen. Dies kann ein Knopf sein, der gedrückt wird, oder aber ein Tastendruck wie Control-S oder Return . Das Element WnSpeichernUnterDialog enthält die Aktivatoren BtSpeichern und BtAbbrechen.
Der Spezialisierungsprefix Bt kennzeichnet einen Knopf (Button) im Fenster.
Ein weiterer Unteraspekt von WnSpeichernUnterDialog ist das Eingabefeld EtDateiMitPfad. Der Spezialisierungsprefix Et kennzeichnet ein Feld, in das Text geschrieben werden kann (Editable text).
Der Unteraspekt Inhalt ist ein Zustand, der durch die Markierung $ als solcher gekennzeichnet ist. Inhalt verweist in diesem Beispiel auf Daten, die nicht innerhalb des spezifizierten Systems, sondern von außerhalb zur Verfügung gestellt werden. Das Verweis-Konstrukt
lokalerAspekt <- andererAspektbedeutet:
EXTERN in Großbuchstaben kennzeichnet einen terminalen Aspekt. Terminale Aspekte werden in der Domäne, also dem Themenbereich oder Fachbereich einer Tango-Spezifikation als bekannt vorausgesetzt und müssen deshalb nicht näher erläutert werden. EXTERN erlaubt per Konvention den Zugriff auf Information, die von irgendwoher angeliefert wurde, und das spezifizierte System kann sich darauf verlassen, dass diese Information zur Verfügung steht. Ein formlos beschriebener Unteraspekt {zu speichernde Daten} von EXTERN erlaubt den Zugriff auf diese Daten. Die zu speichernden Daten stehen durch Nutzung des Verweis-Konstrukts unter der Bezeichnung Inhalt zur Verfügung.
Aspekte müssen nicht unbedingt durch Namen benannt werden, sie können auch durch eine formlose Beschreibung in geschweiften Klammern angegeben werden. Die durch einen Punkt getrennte Angabe von Aspekten EXTERN.{zu speichernde Daten} ist ein Pfad, der auf einen Unteraspekt von EXTERN verweist.
!#WnSpeichernUnterDialog
.+BtSpeichern
=> .@PrüfeSpeichern
.+BtAbbrechen
=> .WnSpeichernUnterDialog.CLOSE
...
Die Ellipse ... zeigt an, dass diese Beschreibung unvollständig ist. Die Einrückung der Ellipse sagt, dass Unteraspekte von WnSpeichernUnterDialog fehlen.
Der Wirkungspfeil => unter einem Aktivator kennzeichnet einen Aktivitätsblock, in dem die Wirkungen niedergeschrieben sind, die beim Auslösen des Aktivators eintreten. Die einzelnen Aktivitäten sind Unteraspekte des Aktivitätsblocks. In diesem Ausschnitt des Beispiels hat jeder Aktivitätsblock nur eine einzige Aktivität.
CLOSE ist ein terminaler Aspekt, genauer ein als bekannt vorausgesetztes Ereignis, das am Fenster WnSpeichernUnterDialog ausgelöst werden kann. CLOSE ist nicht als Ereignis markiert, da es als bekannt vorausgesetzt wird, es könnte aber im Falle von Unklarheiten als Ereignis *WnSpeichernUnterDialog.CLOSE markiert werden.
Die Markierung @ im Aktivitätsblock von BtSpeichern kennzeichnet eine Aktion namens PrüfeSpeichern. Diese Aktion besteht aus einem Aktivitätsblock, der an anderer Stelle der Spezifikation in einem eigenen Definitionsblock beschrieben ist. Die Nutzung des Namens der Aktion erspart an dieser Stelle die explizite Niederschrift des Aktivitätsblocks der Aktion .PrüfeSpeichern
!#WnSpeichernUnterDialog
.EtDateiMitPfad : [ leer | FormatFalsch | VerzeichnisExistiertNicht |
DateiExistiert | DateiIstNeu ]
.+CR // Return-Taste
=> .@PrüfeSpeichern
...
Das Feld EtDateiMitPfad kann mehrere Zustände einnehmen: Das Feld kann leer sein, das Format des eingegebenen Textes ist falsch, das angegebene Verzeichnis existiert nicht, die angegebene Datei ist vorhanden oder nicht vorhanden.
Das Feld EtDateiMitPfad kann verschiedene Zustände einnehmen, die zu unterschiedlichen Reaktionen des beschriebenen Systems führen. Die Aufzählung der verschiedenen Zustände an dieser Stelle ist optional. Es würde genügen, die einzelnen Fälle dort zu unterscheiden, wo tatsächlich unterschiedliche Wirkungen eintreten, in diesem Beispiel in der Aktion @PrüfeSpeichern.
einElement : möglicheInhalte
erlaubt Aussagen über die Werte, die der Zustand einElement annehmen kann. Die Beschreibung möglicheInhalte kann eine Auswahlliste sein:
[ alternative1 | alternative2 | alternative3 ]Die Auswahlliste enthält die Werte selbst oder Beschreibungen der Werte von einElement, und für jeden möglichen Wert muss mindestens eine der Alternativen zutreffen. Wenn sich die Alternativen überschneiden, wenn also ein Wert in mehr als eine Alternative passt, so ist dies ohne Bedeutung.
Die Markierung // kennzeichnet einen Kommentar bis zum Ende der Zeile. Ein Kommentar ist nur für den Leser bestimmt, er ist kein Teil der Spezifikation. Soll die Information in der Spezifikation Berücksichtigung finden, kann stattdessen eine formlose Beschreibung verwendet werden.
!@PrüfeSpeichern
=> ? WnSpeichernUnterDialog.EtDateiMitPfad =
= leer
=> .BEEP
= FormatFalsch
=> .USER << "Kein gültiges Dateinamen-Format"
= VerzeichnisExistiertNicht
=> .USER << "Verzeichnis existiert nicht" // Wird nicht automatisch angelegt
= DateiExistiert
=> .? USER << "Datei existiert, überschreiben?" =
= "Ja, überschreiben"
=> .@JetztSpeichern
= "Nein, nicht überschreiben"
=> .WnSpeichernUnterDialog.EtDateiMitPfad.MARKIEREN
.{ganzen Inhalt des Feldes selektieren und Focus drauf setzen}
= "Aktion abbrechen"
=> .NOP
= DateiIstNeu
=> .@JetztSpeichern
Die Verzweigung
? Wertlieferant =
= wert1
=> .machWas
= wert2
=> .machWasAnderes
erlaubt Wirkungen zu beschreiben, die nur unter bestimmten Bedingungen eintreten. Die Wirkungen werden in einem Aktivitätsblock unter der jeweiligen Alternative beschrieben Es können beliebig viele Alternativen angegeben werden. Die Wirkungen der ersten zutreffenden Alternative treten ein, alle nachfolgenden Bedingungen werden ignoriert. Es wird also immer genau ein Aktivitätsblock wirksam. Wenn der Wertlieferant einen Wert annehmen könnte, so dass keine der Bedingungen gültig ist, dann wäre dies ein Fehler in der Spezifikation.
Wenn die Datei bereits existiert und der USER (terminaler Aspekt, deshalb selbsterklärend) die Frage nach dem Überschreiben unbeantwortet lässt und stattdessen die Aktion abbricht, dann soll das System keine Handlung ausführen. Dazu wird die terminale NOP-Aktivität (No Operation) in den Aktivitätsblock geschrieben.
Das Versenden von Information oder Werten an einen beliebigen Empfänger im beschriebenen System oder außerhalb wird durch das folgende Konstrukt beschrieben:
Empfänger << Information
Die Information wird an den Empfänger übermittelt, die Entgegennahme oder Bearbeitung ist Aufgabe des Empfängers. Aus Sicht des Empfängers ist diese übersandte Information über den terminalen Aspekt EXTERN zugänglich. Dem Empfänger steht frei, ob und wann er die Information nutzt. Die Meldung "Kein gültiges Dateinamen-Format" wird dem USER zur Verfügung gestellt, und der USER kann diese Meldung sofort, später oder überhaupt nicht zur Kenntnis nehmen.
Existiert die Datei, so wird der USER gefragt, wie weiter vorzugehen ist. In diesem Fall wird wie bei jedem Versenden Information an den USER versandt, aber das System wartet jetzt, bis der USER antwortet. Das Senden-Konstrukt ist hier der Wertlieferant für eine Verzweigung:
= DateiExistiert
=> .? USER << "Datei existiert, überschreiben?" =
= "Ja, überschreiben"
...
Mit der Verzweigung werden die drei USER-Antwortalternativen bearbeitet.
Eine formlose Wertbeschreibung wird von Gänsefüßchen eingefasst, sie beschreibt den Wert eines Zustandes oder allgemein irgendeine Information. Die Beschreibung entspricht nicht notwendigerweise dem tatsächlichen Inhalt, sie soll die Bedeutung des Wertes wiedergeben. Deshalb kann nicht davon ausgegangen werden, dass der USER tatsächlich eine wörtliche Meldung "Kein gültiges Dateinamen-Format" erhält. Die möglichen USER-Antworten sind ebenfalls als formlose Wertbeschreibungen notiert, und auch hier ist der Sinn der Antwort beschrieben. Ergänzende Information zu der Bedeutung der Alternativen ist üblich und einem trockenen Ja oder Nein vorzuziehen.
Wenn eine existierende Datei nicht überschrieben werden soll, dann wird das Eingabefeld WnSpeichernUnterDialog.EtDateiMitPfad zur Bearbeitung vorbereitet, indem der Inhalt selektiert wird und der Focus auf dieses Feld gesetzt wird:
= "Nein, nicht überschreiben"
=> .WnSpeichernUnterDialog.EtDateiMitPfad.MARKIEREN
.{ganzen Inhalt des Feldes selektieren und Focus drauf setzen}
Das MARKIEREN ist ein terminaler Aspekt, weil dieses Ereignis für Eingabetextfelder üblich ist. Trotzdem wird hier mit einer Verfeinerung klargestellt, was mit MARKIEREN eigentlich gemeint ist. Jeder Aspekt, auch ein terminaler, kann durch Unteraspekte genauer beschrieben werden.
!@JetztSpeichern
=> .$DateiMitPfad <- WnSpeichernUnterDialog.EtDateiMitPfad
.$Inhalt <- WnSpeichernUnterDialog.Inhalt
.?{Datei $DateiMitPfad angelegt oder ersetzt mit $Inhalt} =
= "OK, erfolgreich gespeichert"
=> .WnSpeichernUnterDialog.CLOSE
= "NOK, etwas ging schief"
=> .USER << "Speichern war nicht erfolgreich"
DateiMitPfad und Inhalt sind Verweise auf andere Zustände im beschriebenen System. Diese wären auch ohne die Verweise zugänglich, so dass die Nutzung von Verweisen an dieser Stelle nur eine Schreibvereinfachung ist.
Die wesentliche Aktivität ist als formlose Beschreibung notiert: {Datei $DateiMitPfad angelegt oder ersetzt mit $Inhalt}. Eine formlose Beschreibung oder ein anderer terminaler Aspekt sind der übliche Endpunkt einer Verfeinerung in einer Tango-Spezifikation, denn irgendwann überwiegen die Implementierungsdetails, die nicht Teil dieser Spezifikation sind.
Das Schreiben in die Datei kann erfolgreich sein oder nicht, deshalb ist diese Aktivität ein Wertlieferant. Abhängig vom Erfolg dieser Handlung wird der jeweilige Aktivitätsblock ausgeführt. Das Schließen des Fensters WnSpeichernUnterDialog ist gleichzeitig das Ende der Aktivitäten am beschriebenen System, denn es ist jetzt nichts mehr vorhanden, was bedient werden könnte. Damit ist auch das Ende der Beschreibung erreicht.
2.3 Anmerkungen zum Beispiel |
|
Globale Sichtbarkeit von Elementen |
Formlose Beschreibungen von Aktivitäten haben das grundsätzliche Problem, dass hier eigentlich keine Aktivitäten beschrieben werden, sondern Wirkungen von durchgeführten Aktivitäten. Wenn exakt formuliert wird, dann klingt die Beschreibung hölzern: {$DateiMitPfad angelegt oder ersetzt mit $Inhalt}. Diese Formulierung enthält, dass eine Aktivität vorausging und jetzt das Ergebnis überprüft werden soll. Lesbarer wäre: {$DateiMitPfad anlegen oder ersetzen mit $Inhalt}. Dies impliziert aber eine Aktion, die an dieser Stelle erst durchgeführt wird, also eine Aufforderung. Üblicherweise wird die geschmeidige letzte Variante der Formulierung gewählt, es muss aber berücksichtigt werden, dass in einer Tango-Spezifikation immer die Ergebnisse betrachtet werden, niemals die Aktivitäten, die zu den Ergebnissen führen. Die im Beispiel verwendete Formulierung {ganzen Inhalt des Feldes selektieren und Focus drauf setzen} ist also üblich, aber etwas missverständlich.
Aktionen oder Aktivitätsblöcke sind keine Prozeduren und keine Funktionen, sondern lediglich Zusammenstellungen von Wirkungen. Hier gilt der Grundsatz "Was an dieser Stelle passiert (genauer: beobachtet wird), wird an dieser Stelle hingeschrieben". Aus Sicht eines Programmierers ist diese Vorgehensweise zumindest kaltblütig, in einer Tango-Spezifikation ist diese Art der Niederschrift der Normalfall.