Dokumente über Pumpen
Das Beispiel, das ich hier benutze, ist eine im ABZ 5-7/1999 von Tanner Dokuments beschriebene Pumpe, bei der darauf geachtet werden muss, dass sich vor dem Einschalten keine Flüssigkeit mehr im einem Behälter des Geräts befindet. Dort illustriert diese Pumpe einige Konzepte des Funktionsdesigns, vor allem die Notwendigkeit, die Elemente einer Bedienungsanleitung nach ihrer Funktion zu gliedern und systematisch anzuordnen. Für jede Handlungssequenz muss das damit verfolgte Ziel genannt werden, die möglichen Gefahren und Vorbedingungen müssen klar benannt werden und erst dann die einzelnen Handlungsschritte mit ihren Auswirkungen beschrieben werden.
Also nicht:
Stellen Sie den Schalter A auf Position 1. Die grüne Kontrollampe leuchtet auf. Dabei sollten sie darauf achten, dass sich keine Flüssigkeit im Behälter befindet. Damit ist die Pumpe betriebsbereit.Sondern klar strukturiert:
Vorbereiten der Pumpe Sachschäden durch überlaufende Füssigkeit! Behälter vor dem Einschalten leeren. Schalter A auf Position 1 stellen. Grüne Kontrollampe leuchtet auf. Pumpe ist betriebsbereit.
Dass diese Vorgaben eingehalten werden und zum Beispiel alle Warnhinweise vor der ersten Handlungsaufforderung stehen, kann man dadurch sicher stellen, dass man die Bedienungsanleitung der Pumpe als ein SGML- oder XML-Dokument erstellt und die richtige Reihenfolge in der benutzten DTD festschreibt. Die Definition für die Beschreibung einer Handlungssequenz könnte dann zum Beispiel so aussehen (bei den hier nicht deklarierten Elementen kann man o. B. d. A. annehmen, dass ihre Definition eine Variante des Musters "fortlaufender Text" ist):
Innerhalb einer Sequenz muss immer zuerst das Ziel benannt werden, dann kommen die Warnhinweise, sofern sie vorhanden sind. Darauf folgt eine Liste von konkreten Handlungsaufforderungen, gegebenenfalls mit der Beschreibung der damit erreichten Zwischenzustände, und schließlich die Beschreibung des mit der Handlung erreichten Endzustands:<!ELEMENT Handlung (Ziel, Warnhinweis*, (Aufforderung, Zwischenzustand?)+, Endzustand)>
<Handlung> <Ziel>Vorbereiten der Pumpe</Ziel> <Warnhinweis>Sachschäden durch überlaufende Flüssigkeit! Behälter vor dem Einschalten leeren.</Warnhinweis> <Aufforderung>Schalter A auf Position 1 stellen.</Aufforderung> <Zwischenzustand>Die grüne Kontrolllampe leuchtet auf.</Zwischenzustand> <Endzustand>Die Pumpe ist betriebsbereit.</Endzustand> </Handlung>
So kann man aber nicht überprüfen, ob die Warnung tatsächlich zu der beschriebenen Handlungssequenz passt, und auch nicht, ob nicht vielleicht ein Warnhinweis vergessen worden ist.
Ein abstraktes Modell der Pumpe
Um mehr als nur die korrete Struktur der Anleitung zu überprüfen, muss man sie gegen eine abstrakte Beschreibung der Pumpe validieren. Das bedeutet natürlich zunächst einmal Mehrarbeit: Man muss das abstrakte Modell entwickeln, und man muss in der Bedienungsanleitung Verweise auf die Elemente dieses Modells erfassen.
Eine Möglichkeit ist es, die zu beschreibende Maschine als einen endlichen Automaten zu modelieren. Das Maschinenmodell als XML-Datei besteht aus einer Reihe von eindeutig gekennzeichneten Zuständen:
Zu jedem Zustand gehört dabei eine Liste von möglichen Übergängen in andere Zustände, die durch die vorzunehmende Operation gekennzeichnet werden:<!ELEMENT Maschinenmodell (Zustand+)> <!ELEMENT Zustand (Übergang+)> <!ATTLIST Zustand id ID #REQUIRED >
Wenn die Maschine durch diese Operation in einen gültigen Betriebszustand übergeht, kann man ihn mit einem Attribut kodieren, für dieses Beispiel ist das aber irrelevant. Hier kommte es nur darauf an, dass Übergänge mit Warnungen verbunden sein können, auf deren Vorhandensein das Stylesheet testen kann.<!ELEMENT Übergang (Warnung?)> <!ATTLIST Übergang oper NMTOKEN #REQUIRED ziel IDREF #REQUIRED >
Eine minimales Modell der Pumpe aus dem Beispiel hat drei Zustände:
Aus
: Die Pumpe ist ausgeschaltet und leer.Ein
: Die Pumpe ist eingeschaltet und pumpt.Rest
: Die Pumpe ist ausgeschaltet, aber es befindet sich möglicherweise noch ein Rest Flüssigkeit im Behälter.
A1
: Der Schalter A wird in Position 1 gestelltA0
: Der Schalter A wird in Position 0 gestelltL
: Der Behälter wird entleert.
A1
einzuschalten, wenn sie sich im Zustand
Rest
befindet (Datei <?xml version="1.0" encoding="iso-8859-1"?> <Maschinenmodell> <Zustand id="Aus"> <Übergang oper="A1" ziel="Ein"></Übergang> </Zustand> <Zustand id="Ein"> <Übergang oper="A0" ziel="Rest"></Übergang> </Zustand> <Zustand id="Rest"> <Übergang oper="L" ziel="Aus"></Übergang> <Übergang oper="A1"> <Warnung>Schäden durch Flüssigkeit im Behälter</Warnung> </Übergang> </Zustand> </Maschinenmodell>
Bedienungsanleitung und Maschinenmodell
Um nun die Bedienunganleitung gegen das Maschinenmodell validieren zu
können, muss man erst einmal ein Verbindung zwischen beiden
herstellen.
Zum Beispiel kann man das Modell als eine externe Entität in die
Bedienungsanleitung integrieren (Datei
<?xml version="1.0" encoding="iso-8859-1"?> <!DOCTYPE anleitung SYSTEM "anleitung.dtd" [ <!ENTITY maschinenmodell SYSTEM "pumpenmodell.xml"> ]> <Anleitung> &maschinenmodell; <Text> [...] </Text> </Anleitung>
Die Beschreibungen der einzelnen Handlungssequenzen finden dann ihren
Platz in dem Text
-Element der Anleitung.
Für dieses Beispiel wird eine sehr einfache Logik für die Validierung zu Grunde gelegt: Wenn die Handlungssequenz eine Aufforderung zu einer Operation enthält, für die es eine Warnung gibt, muss die Bedienungsanleitung einen Warnhinweis enthalten, der sagt, bei welchem Zustand der Maschine es mit dieser Operation Probleme geben kann.
Die wichtigste daraus folgende Änderung bei der Erfassung der Anleitung gegenüber der ursprünglichen Version ist, dass bei jeder Aufforderung auch die Operation, die durchgeführt werden soll, als ein Attribut angegeben werden muss:
<Aufforderung oper="A1">Schalter A auf Position 1 stellen.</Aufforderung>
Ebenso muss bei den Wanrhinweisen festgehalten werden, auf welchen Zustand sie sich beziehen:
<Warnhinweis zust="Rest">Sachschäden durch überlaufende Flüssigkeit! Behälter vor dem Einschalten leeren.</Warnhinweis>
Das Stylesheet
Wenn zusätzlich zu dem Modell der Maschinen diese Angaben vorhanden sind, kann man mit einem XSLT-Stylesheet die vollständigkeit der Warnungen überprüfen. Den Ansatz, Stylesheets zu benutzen, um eine nicht als Übereinstimmung mit einer Grammatik verstandene Validierung von Dokumenten durchzuführen, hat vor allem das Schematron von Rick Jelliffe populär gemacht. Der hier verfolgte Ansatz ist stark vom Schematron inspiriert worden, allerdings ist das Schematron für die hier angestrebte Funktionalität nicht flexibel genug. Es dürfte aber nicht schwierig sein, ein Stylesheet, das nach dem hier beschriebenen Muster aufgebaut ist, mit einem Schematron Stylesheet zu kombinieren.
Der erste Schritt des Stylesheets (Datei
Die Bearbeitung der Datei wird durch ein Template gestartet, das das
Ergebnis mit etwas HTML umgibt und sonst nichts weiter macht, als für
die weitere Verarbeitung einen Modus zu setzen, in dem der normale
Text des Dokuments nicht ausgegeben wird:
Die eigentliche Logik steckt in dem Template, das in diesem Modus für
die Verarbeitung der in einer Handlungssequenz enthaltenen
Aufforderungen zuständig ist:
Das Template weist zunächst drei relativ zu der aktuellen Aufforderung
definierte Größen an Variablen zu und bearbeitet dann mit Hilfe des
anfangs definierten Schlüssels alle Zustände aus dem Modell der
Maschine, für die es Warnungen bezüglich der aktuellen Operation gibt:
Die Zwischenspeicherung in Variablen ist notwendig, da innerhalb
dieses
Für jeden dieser Zustände wird dann getestet, ob es in der Anleitung
einen ihm entsprechenden Warnhinweis gibt.
Wenn es keinen gibt, wird eine Warnung ausgegeben, die das Ziel der
aktuellen Handlungssequenz, die Operation, den problematischen Zustand
und den Text der im Maschinenmodell enthaltenen Warnung ausgibt, hier
wieder in etwas HTML verpackt:
Wenn alles in Ordnung ist, produziert das Stylesheet nur eine leere
Liste von Typ
Je nach Vorlieben und Funktionsumfang des XSLT-Prozessors kann man
dafür natürlich auch andere Darstellungsformate wählen, die es
z. B. ermöglichen können, dass der für die Erstellung der
Anleitung benutzte Editor gleich an die Stelle springt, an der der
Warnhinweis fehlt.
<xsl:key name="Warnungen"
match="/Anleitung/Maschinenmodell/Zustand"
use="Übergang[Warnung]/@oper" />
<xsl:output method="html"/>
<xsl:template match="/">
<dl>
<xsl:apply-templates mode="M1"/>
</dl>
</xsl:template>
<xsl:template match="text()" priority="-1" mode="M1"/>
<xsl:template match="Handlung/Aufforderung" priority="4000" mode="M1">
<xsl:variable name="oper" select="@oper"/>
<xsl:variable name="handlung" select="../Ziel"/>
<xsl:variable name="warnhinweise" select="../Warnhinweis"/>
<xsl:for-each select="key('Warnungen',$oper)">
xsl:for-each
-Elements die Zustände des Modells und
nicht mehr die Aufforderungen in der Handlungssequenz der aktuelle
Kontext der Verabeitung sind.
<xsl:variable name="zustand" select="@id"/>
<xsl:if test="count($warnhinweise[@zust=$zustand]) = 0">
<dt><xsl:apply-templates select="$handlung"/></dt>
<dd>Operation "<xsl:value-of select="$oper"/>":
Problem möglich mit Zustand "<xsl:value-of select="@id"/>":
<br />
<xsl:apply-templates
select='Übergang[@oper=$oper]/Warnung'/>
</dd>
</xsl:if>
</xsl:for-each>
<xsl:apply-templates mode="M1"/>
</xsl:template>
dl
.
Fehlt in dem Beispiel dagegen die Warnung, den Behälter vor dem
Einschalten der Pumpe zu leeren, sieht das Ergebnis so aus:
Schäden durch Flüssigkeit im Behälter