Suche
Abnehmen, ohne zu hungern

Lean Modeling: mit natürlicher Sprache zum Modell

Dr. Mirko Seifert, Christian Wende, Florian Heidenreich und Tobias Nestler
© shutterstock.com/tomer turjeman

Modellierungswerkzeuge und domänenspezifische Sprachen sind in den letzten Jahren in der Softwareentwicklung zunehmend populär geworden. Für die meisten Java-Entwicklungsumgebungen existiert heute eine Vielzahl von ausgereiften Werkzeugen, um Modelle oder Modellierungssprachen zu nutzen oder selbst zu erstellen. Leider werden diese mächtigen Technologien noch viel zu selten genutzt. Eine leichtgewichtige Alternative zu klassischen Modellierungswerkzeugen und DSL-Tools ist Lean Modeling. Dieser Ansatz verwendet die Ideen von Acceptance Test-driven Development, um natürlichsprachliche Spezifikationen in der Anwendungsentwicklung zu nutzen.

Ausgangspunkt ist die Grundidee, natürlichsprachliche Texte als Spezifikation zu nutzen. Diese entstand ursprünglich im Kontext von Acceptance Test-driven Development, mit dem Ziel, lesbare, wartbare und ausführbare Akzeptanztests mit natürlicher Sprache zu beschreiben. Anhand von verschiedenen Beispielen wird gezeigt, wie einfach Texte als Modelle interpretiert und verarbeitet werden können. Wir bezeichnen dieses Vorgehen als „Lean Modeling“. Die Hauptaufgabe jedes Softwareentwicklers besteht darin, die Wünsche bzw. Anforderungen eines Kunden in eine lauffähige Software zu verwandeln. Dazu müssen diese Anforderungen zunächst möglichst genau erfasst werden, um sicherzustellen, dass man ein einheitliches Verständnis davon hat, was am Ende des Entwicklungsprozesses entstehen soll. Die Mittel, um ein solches gemeinsames Verständnis zu erreichen, sind vielfältig. Beispielsweise können Workshops genutzt werden, um Anforderungen zu erfassen oder das Verhalten der Anwendung kann in Fachspezifikationen beschrieben werden. Genauso gut kann man in regelmäßigen Abständen dem Kunden die Software vorlegen, um die gemeinsamen Vorstellungen abzugleichen.
Unabhängig davon, welchen Weg man bevorzugt: Die Anforderungen an die Anwendung werden fast immer aus einer fachlichen Perspektive und meist in natürlicher Sprache erfasst. Dadurch ergeben sich bereits die ersten beiden zentralen Herausforderungen. Zum einen muss die fachliche Perspektive mit einer technischen in Einklang gebracht werden, zum anderen müssen die natürlichsprachlichen Beschreibungen in formale Spezifikationen (z. B. Programmcode) übersetzt werden. Diesen beiden Aufgaben widmet sich jeder Softwareentwickler täglich.
Um die Kommunikation zwischen Kunden, Fachexperten und Entwicklern zu vereinfachen, wurden in der Vergangenheit verschiedenste Ansätze ausprobiert und mit unterschiedlichem Erfolg angewendet. Beispielsweise wurden Entity-Relationship-Diagramme genutzt, um gemeinsam über das Datenmodell einer Anwendung zu beraten. UML-Diagramme wurden eingesetzt, um neben dem Datenmodell auch andere Aspekte (z. B. Use Cases, Verhaltensprotokolle, Zustandsmodelle) zu erfassen. Besondere Popularität haben in den letzten Jahren Ansätze mit domänenspezifischen Sprachen (DSLs) erfahren, die es erlauben, fachliche Anforderungen besonders domänennah zu erfassen. Das gemeinsame Ziel all dieser Modellierungstechniken war und ist es, spezielle Abstraktionen einzuführen, mit denen Anwendungsteile einfacher und genauer spezifiziert werden können. Dieses Ziel teilt der Ansatz, der in diesem Artikel vorgestellt wird. Allerdings setzt Lean Modeling die Schwerpunkte anders als bisherige Modellierungsmethoden (Kasten „Die Ziele von Lean Modeling“).

Abstraktion, Modellierung – Muss das sein?

Warum sind zusätzliche Abstraktionsebenen bei der Softwareentwicklung so erstrebenswert? Nun ja, man kann sicher jede Anwendung auch ausschließlich mithilfe von Programmcode beschreiben. Dem Verständnis der Anwendung ist das aber sicher nicht zuträglich. So ist beispielsweise das Datenmodell einer Applikation zwar vollständig im Programmcode enthalten, aber nicht direkt ersichtlich. Um den Überblick zu behalten, braucht selbst ein erfahrener Entwickler eine Möglichkeit, die für das Datenmodell irrelevanten Teile des Codes auszublenden. Für Kunden und Fachexperten, die normalerweise nicht programmieren können und wollen, gilt dies noch viel mehr. Deshalb werden oft Fließtexte, Diagramme und Tabellen genutzt, um Informationen für alle an der Softwareentwicklung Beteiligten auf einem adäquaten Abstraktionsniveau darzustellen. Wir brauchen also ein gewisses Maß an Abstraktion, um die Komplexität zu beherrschen und um große Anwendungen zu verstehen. Modellierung bzw. Modellierungswerkzeuge stellen damit ein essenzielles Instrument für die Softwareentwicklung dar.

Die Ziele von Lean Modeling
• Geringere Einstiegshürde im Vergleich zu klassischen Modellierungsansätzen (keine Vorkenntnisse nötig)
• Einfache Zusammenarbeit mit Fachexperten durch Verwendung von natürlicher Sprache (keine technischen DSLs)
• Direkte Verwendung der Modelle für die Implementierung steigert die Entwicklungseffizienz (Codegenerierung oder Interpretation der Texte)
• Leicht zugängliche Methode zur Softwarespezifikation (eine Methode pro Satz, Matching über einfache Muster mit Platzhaltern)
• Spezifikation von Tests, Datenmodellen, Geschäftsregeln u.v.m. mit einem einheitlichen Mechanismus
• Extrem kurze Feedbackschleife bei der Entwicklung von Modellierungssprachen (keine Codegenerierung für die DSL selbst)

Werkzeuge – Der Stand der Technik

Je einfacher wir Modelle erstellen und verarbeiten können, desto effektiver können wir Abstraktionsebenen einführen und wechseln. Nun stellt sich die Frage, wie gut uns existierende Modellierungsansätze und -werkzeuge dabei unterstützen. Betrachtet man hier auf der einen Seite Werkzeuge mit fest definierten Modellierungssprachen (z. B. UML-Werkzeuge), so stellt man fest, dass man die vorgegebenen Sprachen zwar sofort nutzen kann, man bzgl. der Wahl der Abstraktionen aber stark eingeschränkt ist. Will man beispielsweise mit der UML Eingabeformulare modellieren, so muss man sich schon etwas verbiegen (z. B. Stereotypen benutzen).
Auf der anderen Seite gibt es Modellierungswerkzeuge, mit denen man eigene Sprachen entwickeln kann, d. h. die Abstraktion kann hier frei gewählt werden. Im Eclipse-Umfeld sind hier in den letzten Jahren viele Werkzeuge zur Entwicklung von textuellen und grafischen DSLs entstanden [1], [2], [3], [4]. Mit MPS steht zudem ein kommerzielles DSL-Werkzeug von JetBrains zur Verfügung [5]. Man kann mit all diesen Werkezeugen gezielt neue Abstraktionen einführen und hat dazu noch die Wahl, die neuen Konzepte (z. B. Formularfelder) grafisch oder in Form von Text auszudrücken.
Das klingt sehr komfortabel und einfach. Es stellt sich also die Frage, warum noch immer viele Softwareprojekte auf eigene DSLs und die schönen, komfortablen Editoren verzichten. Eine Ursache dafür ist unserer Erfahrung nach, dass die o. g. Werkzeuge nicht zugänglich genug oder zu schwerfällig sind.
Was muss man mit modernen DSL-Werkzeugen tun, um sich eine neue Sprache, d. h. eine neue Abstraktionsebene, zu schaffen? Zuallererst muss man sich natürlich mit den entsprechenden Werkzeugen und Konzepten vertraut machen. Hier betritt man meist unbekanntes Terrain. Bei DSL-Werkzeugen im Eclipse-Umfeld muss man sich mit der Entwicklung von Eclipse-Plug-ins befassen, was sicherlich kein triviales Thema ist. Auch bei der Nutzung von MPS muss man die gewohnte Entwicklungsumgebung erst einmal verlassen und sich in ein neues (Meta-)Werkzeug einarbeiten. Dieser Lernprozess betrifft natürlich nicht nur einen Entwickler im Team, sondern alle. Damit jeder von den neuen Abstraktionen profitieren kann, muss der Umgang mit DSLs leicht von der Hand gehen.
Kurzum, man steht vor einer substanziellen und teilweise sehr steilen Lernkurve. Hat man diese überwunden, was sicherlich erstrebenswert ist, ist man in der Lage, innerhalb relativ kurzer Zeit (z. B. weniger Tage) neue Sprachen zu erstellen. Wäre es aber nicht wunderbar, wenn die Einführung einer neuen Abstraktionsebene so schnell und so einfach wäre wie das Anlegen einer neuen Klasse?

Aufmacherbild: cork board with pinned yellow note and the phrase „dont eat“ written on it. room for text von Shutterstock / Urheberrecht: tomer turjeman

[ header = Seite 2: Hoppla, die Lösung liegt vor unseren Füßen ]

Hoppla, die Lösung liegt vor unseren Füßen

Hier kommt das Stichwort „Acceptance Test-driven Development (ATDD)“ ins Spiel. Auf den ersten Blick scheint dieses Thema keinen direkten Bezug zur Modellierung zu haben. Schaut man aber genauer hin, so ergeben sich doch wichtige Parallelen. Das zentrale Ziel von ATDD ist es, die Diskrepanz zwischen fachlichen Anforderungen (wie sie ein Kunde formulieren würde) auf der einen Seite und der technischen Überprüfung der Anforderungen (wie sie ein Entwickler in einem Test manifestiert) auf der anderen Seite zu überwinden. Damit widmet sich ATDD also dem oben angesprochenen Abstraktionsproblem.
Die Kernidee von ATDD ist es dabei, natürlichsprachliche Szenariobeschreibungen direkt zum Test von Anwendungen zu nutzen. ATDD nutzt demnach natürliche Sprache als sofort verständliches und natürliches Instrument, um fachspezifische Anforderungen darzustellen und gleichzeitig automatisiert auszuwerten.
Wenn man mit ATDD-Werkzeugen Dokumente in natürlicher Sprache einsetzen kann, um ausführbare Tests zu beschreiben, warum sollte man nicht das gleiche Prinzip bei der Implementierung von Software nutzen?

Probieren wir es doch einfach mal aus!

Ein zentraler Bestandteil jeder Anwendung ist das Datenmodell. Es besteht aus den Entitäten, Eigenschaften und Beziehungen der Anwendungsdomäne und wird klassischerweise mithilfe von ER-Diagrammen, SQL-Schemata oder UML-Klassendiagrammen modelliert. Würden wir natürliche Sprache (z. B. Englisch) nutzen wollen, um ein Datenschema zu beschreiben, so könnte das für eine Anwendung im Kontext einer Fluggesellschaft beispielsweise aussehen wie in Abbildung 1 dargestellt.

Abb. 1: Datenschema im NatSpec-Editor

Eine solche Beschreibung des Datenschemas klingt zwar noch etwas mechanisch, ist aber sowohl für Menschen als auch für Maschinen verständlich.
Wenn wir die Beschreibung als (textuelles) Modell betrachten, möchten wir daraus natürlich automatisch die SQL-Befehle zur Erzeugung des Schemas ableiten, genau wie es uns DSL-Werkzeuge erlauben. Dazu bedienen wir uns der prinzipiellen Funktionalität von ATDD-Werkzeugen: Wir bilden die einzelnen Sätze des Dokuments auf Code, d. h. auf einzelne Methoden ab. Beispielsweise ordnen wir dem Satz „There is a table Airplane.“ eine Methode zu, die eine Tabelle erzeugt. Analog dazu wird der nächsten Zeile eine Methode zugeordnet, die eine Spalte vom Typ VARCHAR anlegt.
Praktisch umgesetzt wird diese Zuordnung zwischen Sätzen und Methoden bei den meisten ATDD-Werkzeugen (z. B. bei Cucumber [6]) über spezielle Annotationen an den Methoden, die angeben, welchem Satz bzw. welchen Satzmustern die Methode entspricht. Für die Beispiele in diesem Artikel wird exemplarisch das Werkzeug NatSpec [7] verwendet, da es im Gegensatz zu herkömmlichen ATDD-Werkzeugen keine Einschränkungen bzgl. der möglichen Sätze aufweist und damit auch für den Einsatz außerhalb des Testens bestens geeignet ist.
NatSpec verwendet die @TextSyntax-Annotation zur Verknüpfung von Methoden und Sätzen. Um beispielsweise den ersten Satz aus Abbildung 1 mit der Methode createTable() zu verknüpfen, genügt der Code aus Listing 1.

@TextSyntax("There is a table #1.")
public Table createTable(String name) {
  Table newTable = new Table(name);
  allTables.add(newTable);
  return newTable;
}

Die Zeichenkette innerhalb der @TextSyntax-Annotation gibt an, welchen Sätzen die Methode zugeordnet wird. Platzhalter (z. B. #1) können verwendet werden, um die Methode mit Wörtern aus Sätzen zu parametrisieren. So kann createTable() zum Erzeugen verschiedener Tabellen verwendet werden. NatSpec verwendet hier einfache Platzhalter, die lediglich den Index des Parameters angeben. Andere ATDD-Werkzeuge setzen hier auf reguläre Ausdrücke, um die Menge der erlaubten Wörter noch stärker einzuschränken. Diese Satzmuster stellen das Gegenstück zu Grammatiken dar, die bei Parser-basierten DSL-Werkzeugen zum Einsatz kommen.
Innerhalb der createTable()-Methode wird ein neues Objekt vom Typ Table angelegt. Dieses Objekt repräsentiert eine Tabelle in dem Datenschema, das wir spezifizieren möchten. Für die anderen Sätze aus Abbildung 1 lassen sich ebenfalls Methoden mit entsprechenden Annotationen definieren. Diese sind in Listing 2 zu sehen.

@TextSyntax("Every #1 has a #2 which is a #3 property.")
public void addColumn(Table table, List<String> nameParts, String typeName) {
  String columnName = getColumnName(nameParts);
  String type = getType(typeName);
  Column newField = new Column(columnName, type);
  table.addColumn(newField);
}

@TextSyntax("Every #1 has an #2 which refers to table #3.")
public void addReference(Table table, List<String> nameParts,
Table otherTable) {

  String columnName = getColumnName(nameParts);
  Column newColumn = new Column(columnName, "INT");
  table.addColumn(newColumn);
}

Auch hier werden Platzhalter verwendet, um mit zwei Methoden insgesamt vier Sätze aus Abbildung 1 abzudecken. Eine Besonderheit stellen hier die Parameter vom Typ List<String> dar, da diese sich mehreren Wörtern im Satz zuordnen lassen. So können beispielsweise die Namen der Spalten im Datenmodell (z. B. „seat count“) im Text normal beschrieben werden und dann später, d. h. im Code, in die SQL-Schreibweise (seat_count) umgewandelt werden.

[ header = Seite 3: Das war ja einfach, aber reicht das aus? ]

Das war ja einfach, aber reicht das aus?

Dieses erste Beispiel zeigt die zentrale Idee und das prinzipielle Vorgehen bei Lean Modeling. Man kann leicht sehen, dass Standard-Java-Wissen ausreicht, um zu verstehen, wie das Ganze funktioniert. Jeder Entwickler, der schon einmal Annotationen benutzt hat, kann entsprechende Methoden schreiben. Nicht einmal mit der Syntax für reguläre Ausdrücke muss man vertraut sein, um die Satzmuster zu definieren. Hier kommen wir dem Ziel von Lean Modeling, die Einstiegshürde so gering wie möglich zu halten, schon sehr nahe (Kasten „Die Ziele von Lean Modeling“). Gleichzeitig wirft das Beispiel aber auch eine Menge Fragen auf: Was haben wir hier eigentlich getan? In erster Linie haben wir eine Menge relativ eintöniger Satzmuster auf Java-Methoden abgebildet, die wiederum Objekte erzeugen. Welchen Vorteil bringt es, Texte zu schreiben, die so ähnlich wie Programmcode klingen? Welche Texte können überhaupt auf Methoden abgebildet werden? In welchem Verhältnis steht dieses Vorgehen zu anderen DSL-Werkzeugen?
Obwohl das Datenschema aus Abbildung 1 sicherlich für Menschen lesbar ist, die mit den Konzepten relationaler Datenbanken (Tabelle, Spalte, Typ, Fremdschlüssel) vertraut sind, so mutet der Text doch noch sehr starr an. Alternativ könnte man das Schema auch wie in Abbildung 2 dargestellt beschreiben.

Abb. 2: Alternatives Datenschema im NatSpec-Editor

Dieser Text klingt schon wesentlich weniger formal. Der Text enthält keine Typinformationen für die Eigenschaften (z. B. seat count oder name), dafür aber eine Beschreibung der einzelnen Tabellen. Auch dieser Text lässt sich mithilfe der o. g. Annotationen auf drei Methoden abbilden. Diese sind in verkürzter Form in Listing 3 zu sehen, die vollständige Implementierung kann von GitHub [8] bezogen werden.

@TextSyntax("A #1 is a #2")
public Table createTable(String name, List<String> description) {...}

@TextSyntax("Every #1 has a #2")
public void createColumn(String tableName, List<String> nameParts) {...}

@TextSyntax("It also has a #1")
public void createColumn(List<String> nameParts, Table table) {...}

Diese drei Methoden funktionieren ähnlich wie die aus Listing 1 und 2 und definieren Satzmuster, die alle sieben Sätze aus Abbildung 2 abdecken. Allerdings bedient sich die zweite createColumn()-Methode einer besonderen Funktionalität von NatSpec. In der @TextSyntax-Annotation ist nur der erste Parameter (nameParts) mit einem Platzhalter versehen. Woher kommt also der Wert für den zweiten Parameter (table), wenn nicht aus dem Satz?
Hier wird der Kontext des Satzes genutzt, um einen Wert für den Parameter zu finden. Dieser Kontext besteht aus allen Sätzen vor dem aktuellen Satz, d. h. allen Aussagen, die zuvor gemacht worden. Wird durch einen vorhergehenden Satz ein Objekt vom Typ Table erzeugt, so kann dieses Objekt als Argument für die Methode createColumn() benutzt werden. Das erscheint auf den ersten Blick etwas ungewöhnlich, ist aber tatsächlich ein elementares Konzept von natürlichen (und auch von formalen) Sprachen. Wir beziehen uns bei unseren Aussagen (z. B. „Es war einfach grandios“) sehr oft auf zuvor Gesagtes (z. B. „Gestern war ich beim Konzert von Spinal Tap“). Bei Programmiersprachen entspricht das in etwa dem Scoping bei der Auflösung von Namen. Durch den Kontextbezug erspart man sich unnötige Referenzen und kann so Sachverhalte kompakter und natürlicher ausdrücken.

Neben der Nutzung des Kontexts für die Bestimmung zusätzlicher Parameter nutzt das zweite Beispiel auch Synonyme, um mit der Methode createTable() sowohl Sätze, die mit „A“ als auch Sätze, die mit „An“ beginnen, zu verarbeiten. Synonyme können bei NatSpec frei definiert werden und sind insbesondere nützlich, um Wörter, die sowohl in der Einzahl als auch in der Mehrzahl vorkommen, abzudecken.
Insgesamt zeigt dieses zweite Beispiel, dass man bzgl. der Wahl der Sätze sehr frei ist. Das gleiche Datenschema lässt sich auf verschiedene Weise ausdrücken. Man kann zum einen sehr generische Satzmuster definieren, die auf viele Sätze passen. Dadurch ergibt sich dann eine gleichförmigere, aber auch monotonere Beschreibung des Schemas. Man kann aber auch sehr spezielle Satzmuster nutzen, die im Extremfall sogar nur auf einen Satz passen. Auch hat man die Wahl, ob man Informationen über das Datenschema im Text oder in den dazugehörigen Methoden ablegt. So wurden die Typen der einzelnen Felder in der ersten Variante im Text spezifiziert, während die zweite Variante diese Information im Code hinterlegt.
Hier wird schnell deutlich, dass die Gestaltung der textuellen Spezifikationen viel Spielraum lässt. Dies ist ähnlich wie bei „klassischen“ DSL-Werkzeugen, bei denen man ja ebenfalls in der Gestaltung der Grammatik frei ist und letztendlich selbst entscheiden muss, in welcher Art die Inhalte der jeweiligen Sprache repräsentiert werden sollen. Hier gilt es, ein gutes Gespür für die richtigen Satzmuster zu entwickeln.

Jetzt schreiben wir doch wieder eine Grammatik?

Offensichtlich gibt es demnach eine Beziehung zwischen den Grammatiken der textuellen DSL-Tools und den Satzmustern, die wir in den o. g. Beispielen definiert haben. Beide Mechanismen dienen dazu, die gültigen Sätze der Sprache zu definieren. Allerdings gibt es hier auch entscheidende Unterschiede: Zum einen generieren die meisten DSL-Tools aus den Grammatiken Parser und Editoren. Die Annotationen werden dagegen interpretiert, und es wird ein und derselbe Editor für alle Dokumente verwendet. Der Hauptvorteil der Interpretation besteht darin, dass man die Sprache ändern kann (z. B. durch Änderung einer Annotation) und sofort sieht, ob die existierenden Texte der neuen Sprache genügen. Im Fall von NatSpec kann man dies leicht am Syntax-Highlighting erkennen. Nur Sätze, die einer Methode zugeordnet werden können, erscheinen im Editor hervorgehoben. So verkürzt sich die Feedback-Schleife bei der Entwicklung einer Sprache drastisch. Beispielsweise muss man bei der Nutzung von Eclipse keine zweite Eclipse-Instanz starten; die Sprache wird im selben Eclipse-Workspace definiert und auch genutzt.
Weiterhin muss man Sprachen nicht ausgehend von einer Grammatik entwickeln, sondern kann auch von Beispielsätzen ausgehen. So kann man einen neuen Satz in ein Dokument einfügen und sich dafür eine neue, passende Methode mit der entsprechenden @TextSyntax-Annotation automatisch per Quick Fix erzeugen lassen. Dieses beispielgetriebene Vorgehen ist sehr intuitiv und pragmatisch, wird von DSL-Werkzeugen, die einen Parser generieren, aber nicht unterstützt.
Ein weiterer Unterschied, der insbesondere den Freunden des Compilerbaus auffallen sollte, ist das Fehlen von rekursiven Aufrufen in den Satzmustern. Will man verschachtelte Strukturen aufbauen, so ist dies jedoch über den Kontext der Sätze möglich.

Wo bleibt der Codegenerator?

Um aus den textuellen Modellen Java-Code oder auch andere Artefakte zu erzeugen, wird natürlich ein Codegenerator benötigt. Bei normalen DSL-Werkzeugen verwendet man üblicherweise eine Templatesprache, um über das Modell zu traversieren und entsprechenden Text zu erzeugen. Das funktioniert natürlich auch mit NatSpec. Die Methoden aus Listing 1, 2 und 3 erzeugen ja bereits ein Modell. Dieses kann mit einer beliebigen Templatetechnologie in Code verwandelt und im Workspace abgelegt werden. Für unser Beispiel verwenden wir der Einfachheit halber einen normalen StringBuilder, der ausgehend von einer main()-Methode den Code für unser Datenmodell erzeugt und im Workspace abspeichert. Für die Codegenerierung unterscheidet sich das Vorgehen also nicht wesentlich von bekannten DSL-Tools.

[ header = Seite 4: Ein Datenmodell für SQL-Tabellen – Ist das alles? ]

Ein Datenmodell für SQL-Tabellen – Ist das alles?

Die bisherigen Beispiele waren sehr einfach gewählt, um die prinzipiellen Ideen hinter Lean Modeling darzustellen. Natürlich lassen sich auch andere Anwendungsfälle mit dem gleichen Vorgehen adressieren. So ist beispielsweise die Definition von Formularen im User Interface neben dem Datenschema eine wichtige Aufgabe während der Entwicklung. Als Beispielanwendung möchten wir eine Bestellapplikation für Android Devices betrachten. Sie ist in Abbildung 3 zu sehen.

Abb. 3: Beispielanwendung im Android-Simulator

Für die Entwicklung einer solchen Oberfläche können wir ebenfalls textuelle Spezifikationen einsetzen. Ein Beispiel ist in Abbildung 4 zu sehen.

Abb. 4: Formularbeschreibung im NatSpec-Editor

Der letzte Satz stellt die primitivste Art, ein Formularelement zu beschreiben, dar. Er enthält keinerlei Parameter und wird auf ein einfaches Eingabefeld für E-Mail-Adressen abgebildet. Trotzdem ist es sinnvoll, Formularelemente auf diese Weise zu spezifizieren, da der Satz für einen Fachexperten natürlich zugänglicher und verständlicher ist als der entsprechende Android-XML-Code.
Der zweite und dritte Satz sind parametrisierte Formularelemente, die wir jeweils auf ein Textfeld und eine Checkbox abbilden. Der Text für das Textfeld ist dabei variabel. Das User Interface kann also parametrisiert werden, und der zugehörige Implementierungscode wird automatisch durch die Codegenerierung erzeugt. Darüber hinaus sind die beiden Sätze wesentlich einfacher zu verstehen als die dazugehörigen XML-Fragmente.
Der erste Satz und die Anstriche danach stellen das komplexeste Formularelement in unserem Beispiel dar. Hier wird eine Auswahl von verschiedenen Optionen definiert, die später auf eine RadioBoxGroup abgebildet wird. Es wird hier sehr deutlich, dass man mit derartigen textuellen Regeln auf einem viel höheren Abstraktionsniveau als mit Sourcecode arbeiten kann.
Die Methoden zum ersten Satz sind in Listing 4 zu sehen. Es werden zwei Methoden benötigt. Die erste (addOptionSet()) legt ein neues Set von Optionen an. Danach können mithilfe von addOption() weitere Optionen in das OptionSet aufgenommen werden. Auch diese Methode bedient sich des Kontexts, um das OptionSet zu bestimmen, zu dem die neue Option hinzugefügt werden soll.

@TextSyntax("Let user select between the following options:")
public OptionSet addOptionSet() {
  String text = "Please select one of the following:";
  OptionSet optionSet = new OptionSet(nextID++, text);
  elements.add(optionSet);
  return optionSet;
  }

@TextSyntax("- #1")
public void addOption(List<String> parts, OptionSet optionSet) {
  String text = new StringUtils().explode(parts, " ");
  Option option = new Option(nextID++, text);
  optionSet.addOption(option);
}

Was geht noch so?

Mit textuellen Beschreibungen lassen sich natürlich auch andere Bestandteile von Applikationen spezifizieren. Zustandsmodelle, Protokollbeschreibungen, Prozessabläufe u.v.m. sind denkbar. Auch Varianten der Applikation, wie sie bei einer Produktlinie existieren, können beschrieben werden. Für die technische Dokumentation von Anwendungen, insbesondere ihrer Komponenten und Schnittstellen lassen sich textuelle, natürlichsprachliche Modelle ebenfalls einsetzen. Ob und wann der Einsatz einer textuellen Modellierung wirklich sinnvoll ist, hängt natürlich inhärent mit der Frage nach dem Wert einer abstrakteren Darstellung zusammen. Lässt sich ein Teil einer Anwendung mit einem textuellen Modell wesentlich kürzer und kompakter spezifizieren, so ist das ein erster Indikator für einen gewinnbringenden Einsatzbereich.

Fazit

Die zentrale Idee des Lean Modeling besteht darin, einfache Texte bzw. Sätze auf Java-Methoden abzubilden. Dieser Ansatz, der aus der ATDD-Community stammt, erlaubt es, ohne zusätzliche Frameworks und in der gewohnten Entwicklungsumgebung Texte zum Modellieren und Spezifizieren von Anwendungen zu nutzen. Setzt man geeignete Werkzeuge ein, muss man zudem nicht auf den Komfort klassischer DSL-Workbenches, z. B. Syntax-Highlighting, Code-Completion oder Hyperlinks, verzichten.
Das im Artikel vorgestellte Werkzeug NatSpec wird bei DevBoost intensiv in Kundenprojekten eingesetzt, um mehr Erfahrungen mit diesem Modellierungsansatz zu sammeln. Für den Einsatz zum Testen von Anwendungen hat sich die Vorgehensweise bereits etabliert und wird auch schon seit Längerem in anderen Unternehmen erfolgreich eingesetzt. Momentan wird auf verschiedenen Gebieten damit experimentiert, neue Einsatzbereiche außerhalb des Testens zu erschließen. Unter anderem wird NatSpec genutzt, um Datenbankschemata und Schnittstellen zu beschreiben oder auch, um Anforderungen strukturiert zu erfassen. Später wird es auch möglich sein, Word-Dokumente ähnlich wie im NatSpec-Editor zu bearbeiten. So könnten Fachexperten mit einem vertrauten Editor arbeiten, aber dennoch Dokumente erstellen, die direkt für die Entwicklung weiterverwendet werden können.

Geschrieben von
Dr. Mirko Seifert, Christian Wende, Florian Heidenreich und Tobias Nestler
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.