UML-Modellbasierende Softwareentwicklung

UML-Modellbasierende Softwareentwicklung

Inhalt


Topic:.ModelBasedSwDevlp.

Die Modellbasierende Softwareentwicklung geht von der Idee aus, dass die Software, klassich bestehend aus Quellcode, gleichzeitig als UML-Modell dargestellt und mit dem UML-Modell gepflegt wird. Die UML als Unified Modeling Language hat sich als geeignete grafische Beschreibung von Objektorientierten Softwareentwürfen etabliert. Die Vorteile dieser Modellbasierenden Softwareentwicklung liegen auf der Hand:

Die Vorteile lassen den Schluss zu, dass eine nicht-Modellbasierende Entwicklung nicht mehr zeitgemäß und nur bei kleinen Softwareaufgaben noch tragbar ist.


1 Bestandteile der Modellbasierende Entwicklung: Diagramme, Repository, Codierung

Topic:.ModelBasedSwDevlp..

Aus dem Blickwinkel eines Softwareentwicklers ergeben sich drei Sichten auf die Modellbasierende Entwicklung, die sich in konkreten Files festmachen lassen:

Zusammenhang von grafischen Repräsentationen und Repository: Grafische Darstellungen wie
Bild: ObjectModelDiagramme lassen sich grundsätzlich auch mit Standard-Grafiktools herstellen oder beispielsweise als Bleistiftskizze. So wird mit Visio eine umfangreiche Bibliothek von Vorlagen zum Zeichnen von UML-Bildern mitgeliefert. Man kann UML-Darstellungen zeichnen, hat aber kein Repository. Man kann zeichnen was man will, es ist manuell zu kontrollieren, ob das Gezeichnete mit einer tatsächlichen Implementierung (Quellcode) übereinstimmt. Ist dagegen ein Repository vorhanden, dann werden die Modellelemente mit ihren Zusammenhängen dort geführt. Es lässt sich nur das zeichnen, was tatsächlich im Modell vorhanden ist. Die Zeichnungen sind dann einerseits widerspruchsfrei gegenüber dem Repository, andererseits sind Zeichnungen viel schneller zu erstellen. Möchte man beispielsweise ein Objektmodelldiagramm neu zeichnen, in dem Klassen oder Instanzen und dessen Beziehungen (Assoziationen, Vererbung, Abhängigkeiten) dargestellt werden, dann sind die interessierenden Klassen schnell vom
Bild: Browserbaum des Repository auf die Zeichenfläche gezogen und in einer Standardgröße sofort richtig dargestellt. Alle Beziehungen zwischen den dargestellten Klassen sind mit einem Mausklick automatisch in die Grafik aufnehmbar, die Zeichenarbeit reduziert sich auf Plazierung der Klassen mit Tuning der Größe und Fein-Korrektur der Beziehungslinien. Ein weiterer Mausklick lässt in der Klasse vorhandene Attribute und Methoden für eine Darstellung in der Klasse auswählen.

Zusammenhang von Quellcode der Implementierung und Repository: Das Repository bildet ab, was im Quellcode enthalten ist. Von Modellbasierender Softwareentwicklung sollte nur geredet werden, wenn die Übereinstimmung von Quellcode und Repository prozessbedingt gewährleistet ist. Ein einfacheres Verfahren der toolgestützten Nutzung von UML geht davon aus, dass Architektur und Design in UML betrieben wird, das Modell ist damit vorgegeben für die Implementierung. Letzere, vereinfacht als "Codierung" bezeichnet, muss sich dann nach dem Modell als Vorlage richten. Solche Herangehensweisen berücksichtigen zuwenig, dass sich

Das Wasserfallmodell - Erst Anforderungen festschreiben, dann das Design entwickeln, dann 'nur noch' codieren und testen - hat sich in vielen Fällen als nicht tragfähig erwiesen. Zyklen der Entwicklung, in denen jedesmal Anforderungen, Design, Implentierung und Test durchlaufen und überdacht werden müssen, sind auch dann Tatsache, wenn eine Vorgabe nach einem Wasserfallmodell diesem nicht Rechnung trägt, einfach aus purer Notwendigkeit und Eigendynamik.

Die iterative Entwicklung von Software als Gesamtprozess erfordert also die ständige Übereinstimmung von Modell-Repository und Quellcodierung der Implementierung.


2 Möglichkeiten um Modell-Repository und Quellcodierung abzustimmen

Topic:.ModelBasedSwDevlp..


Bild: Generierung UML - Code Grundsätzlich gibt es zwei Möglichkeiten, eine Quellcodierung und ein Modell-Repositiory in Übereinstimmung zu bringen:

Beide Varianten gehen davon aus, dass es keine Notwendigkeit einer manuelle Nachbearbeitung wärend der Abstimmung Repository und Quellcode gibt. Eine manuelle Nachbearbeitung würde dazu führen, dass Informationen möglicherweise verlorengehen, oder eine Abstimmung aus Arbeitsaufwand längere Zeit unterbleibt. Damit wäre der Aufwand bei einer dann notwendigen Abstimmung höher, was insgesamt dazu führen würde, dass man nicht gern mit dem Modell arbeiten.

Beide Varianten sind aber nicht trivial und bezogen auf konkrete Einsätze diskussionswürdig.


2.1 Generierung des Quellcode aus dem Repository

Topic:.ModelBasedSwDevlp...

Für die Generierung ergeben sich zwei Möglichkeiten:


2.2 Vorteile, aus dem Repository Code zu generieren

Topic:.ModelBasedSwDevlp...

Man arbeitet mit dem UML-Modell. Änderungen erfolgen meist grafisch in den Diagrammen, die dann sofort im Repository wirksam werden. Einzelne Codierungen befinden sich an Modellelementen und sind dort aus der Grafik heraus leicht auffindbar. Die einzelnen Codeabschnitte, das sind Bedingungen für Statechart-Übergänge, Aktionen an den Übergängen, Initialwerte von Variablen, und typisch kurze Bodies der Methoden, sind in Einzel-Edit-Fenstern unter kontextsensitiver Hilfe im UML-Tool leicht editierbar. Erweiterungen wie grafische Beschreibung von Abläufen in Bodies der Methoden sind im UML-Tool unterbringbar, so dass sich der Umfang der Codeabschnitte, die als Programmierzeilen anzugeben sind, nochmals verringern würde.

Diese Vorteile sind dann sehr gut nutzbar, wenn auch ein Test ausschließlich im Modell möglich ist, die Generierung des Quellcodes für den Compiler dann nur noch ein formeller Akt ist. Es wird nicht im Quellcode selbst gearbeitet. Solche Bedingungen bestehen, wenn die Sprache, die in den Codeabschnitten verwendet wird, eher nicht maschinennahe ist (also nicht C oder C++) und damit Schreibfehler oder notwendige Formulierungen einfach formal syntaxtestbar und anzeigbar sind. Typisch wäre das bei einer spezialisierten Sprache (DSL = domain specific language), die zweckmäßigerweise auf die modellbasierende Entwicklung abgestimmt ist, oder bei universellen Standard-Hochsprachen wie Java.


2.3 Nachteile, aus dem Repository Quell-Code zu generieren

Topic:.ModelBasedSwDevlp...

Wenn es sich um maschinennahe Implementierungen handelt, dann sind teilweise spezielle Konstrukte im Quellcode notwendig, die in den einzelnen Codeabschnitten aus dem UML-Modell heraus nicht besser überblickt und getestet werden können als direkt im Code. Oft sogar schlechter, da möglicherweise eine vorhandene Entwicklungsumgebung für die Quellcodeprogrammierung diesbezüglich einschließlich dem Debuggen bessere Möglichkeiten bietet. Es wird also dazu führen, dass der Quellcode generiert wird, danach wird im generierten Quellcode weitergearbeitet zwecks Test und Feinkorrektur. Änderungen sind dort schneller eingebracht. Man braucht dann ein gutes Reverse-Engeneering, um die Änderungen wieder in das UML-Modell zurückfließen zu lassen. Damit ist aber der Arbeitsaufwand erhöht gegenüber einer durchgängigen Fertigstellung nur im Quellcode. Wird aber längere Zeit nur im Quellcode gearbeitet, also auch Strukturen geändert, dann kann ein Reverse-Engeneering möglicherweise hausgemachten Schwierigkeiten bieten. Quellcode und Repository sind auseinandergelaufen und in sich gegebenfalls wiedersprüchlich.

Möglicherweise müssen Strukturelemente des UML zusätzliche spezielle Implementierungseigenschaften kennen, die entsprechend auch im Modell formuliert werden müssen, was aber im Modell gegebenenfalls so nicht vorgesehen ist. Ein Ausweg ist dann eine weitere Abkehr vom eigentlichen Gedanken eines UML-Modells, indem implementierungsspezifsche Elemente anstatt UML-Elemente im Repository verwendet werden.

Man kann die Codegenerierung beliebig komplex gestalten, unter Zuhilfenahme von Rules (Regeln einstellbar) oder Properties (Wert von Zusatzvariablen an allen möglichen Stellen, spezifiziert auf eine bestimmte Zielplattform, spezifiziert für eine Generierungseinstellung, spezifiziert am gesamten Package, gültig nur für ein bestimmtes Modellelement). Damit gilt aber die Formel

 (Modell im Repository) x (Properties) x (Rules) =: Quellcode

Der Quellcode hängt also nicht nur vom Modell selbst ab sondern wird noch an einigen anderen Stellen beeinflusst. Ist da immer überschaubar?

Zusammengefasst: Die Nachteile sind erhöhter Arbeitsaufwand bei Feinausformulierung mit integrativem Test und veringerte Überschau/Kontrollierbarkeit des Quellcodes. Siehe auch Anwendungsgebiete der Generierung von Sekundärsources


2.4 Generierung des Repository aus dem Quellcode

Topic:.ModelBasedSwDevlp...

Wenn ein UML-Tool die Generierung von Quellcode beherrscht, ist meist auch der umgekehrte Weg als Reverse Engineering eingebaut und lässt sich verwenden. In der Regel rechnet man dabei aber mit der Zweckmäßigkeit einer Nachbearbeitung, denn es müssen verschiedenste Ausprägungen von Quellcodes verarbeitet werden. Damit ist aber die Forderung, ohne manuelle Nachbearbeitung auskommen zu können, nicht erfüllt.

Das Repository ist eineindeutig abbildbar mit einem XMI-File: Das XMI ist das XML Metadata Interchange-Format der Object Management Group (OMG). Wenn UML-Tools eine UML ab Version 2.0 unterstützen, dann sollte ein XMI-Export und -Import dabei sein. Der erste Zweck des XMI ist, eine Austauschbarkeit der Daten zwischen UML-Tools verschiedener Herstellern zu ermöglichen, sozusagen bei bestehendem Datenbestand einen Toolwechsel zu unterstüzten. Jedoch, abhängig von der Qualität eines XMI Ex- und Importes, kann XMI als genormte Datenrepräsentation des UML-Repositories verwendet werden.

Damit kann der Weg aus Quellcode zum Modell über den XMI-Import in ein UML-Tool erfolgen. Ein XMI-File lässt sich aus beliebigen Daten mit XML-hauseigenen Mitteln erzeugen. Hier kann ein Anwender außerhalb eines UML-Tools eigene Konvertierungen aus gegebenenfalls sehr speziellen Darstellungen von Quellcode programmieren oder als Dienstleistung programmieren lassen. Daten, die nicht als XML vorliegen, lassen sich parsen und nach XML konvertieren. Dazu kann immer ein ZBNF-Parser verwendet werden, aber auch andere Lösungen.

Der Weg von spezifischen Quellcodes zu XMI ist für alle Programmiersprachen und Darstellungsformen von Quellcodes gangbar, er muss nur entsprechend erarbeitet oder angepasst werden.


2.5 Vorteile, aus dem Quell-Code ein Repository zu generieren

Topic:.ModelBasedSwDevlp...

Ein wichtiger Vorteil ist: Eine bestehende Praxis des Umganges mit Quellcode wird durch das Aufsetzen der Modellbasierenden Entwicklung nicht beeinflusst. Der Quellcode kann so wie bisher weiter editiert, compiliert, getestet werden. Er wird nur zusätzlich in ein UML-Repository konvertiert, um zusätzlich aus diesem Blickwinkel betrachtet werden zu können, um zusätzlich die Qualität der Software zu verbessern. Entweder die Modellbasierende Betrachtung wird von einem anderen Personenkreis betrieben, der den eigentlichen Softwareentwicklern parallel gestellt ist. Oder, was freilich besser ist, der modellbasierende Gedanke hält nach und nach Einzug in die Praxis der Programmierung. Ein guter Programmierer wird schon die Vorteile sehen, die der modellbasierte Ansatz bietet, wenn er in Richtung Dokumentation arbeiten muss oder einen guten Überblick über seine Software haben will.

Insbesondere dann, wenn der Quellcode in nicht standardgemäßen Formen vorliegt oder notwendig ist, beispielsweise als hauseigene Programmiersprache (DSL = Domain Specific Language), ist meist auch XML im Spiel oder möglich. Die Klärung, in wieweit ein solcher Quell-Code überhaupt als UML dargestellt werden kann (möglicherweise gibt es dort nicht den Klassenbegriff usw.), muss im Vorfeld erfolgen. Eine solche Klärung mit Betrachtung gegebenenfalls gewachsener Programmiersysteme und -Gewohnheiten kann für eine generelle Strukturklärung von Software wichtig sein. Der notwendige Umsetzer nach XMI ist dann das Endprodukt dieser Überlegungen. Vorteil ist also, beliebige Software, die als UML betrachtet werden soll, einbeziehen zu können. Die Generierung eines XMI aus dem Quellcode hat man selbst in der Hand.

Ein weiterer Vorteil ist ein möglicher Mix aus verschiedenen Softwarebereichen. Möglicherweise enthält eine Gesamtsoftware Teile, die traditionell in C programmiert worden sind, nicht nur auf Treiber- und Betriebssystemebene. Andere Teile sind hauseigen, weitere Teile in einer der gängigen höheren Programmiersprachen. Alle zusammen bilden das Softwaresystem. Gegebenenfalls sollen nicht alle Quellcode-Teile in einem Modell betrachtet werden, aber wichtige Schnittstellen zwischen diesen Teilen sollen einbezogen werden. Schnittstellen lassen sich als Strukturen in C-Headerfiles darstellen, gegebenfalls werden sie aus einer anderen Umgebung heraus dort bedient. Das Modell soll das unter einem einheitlichem Aspekt darstellen.

Wenn Strukturänderungen der Software aus dem Test heraus an dem Quellcode der Implementierung vorgenommen werden, dann ist das eine durchaus erwartbare Rückkopplung aus der Implementierungsphase in eine Designphase. Man kann positiv unterstellen, das ein Implementierungsprogrammierer das Design kennt, keinen Wildwuchs erzeugt sondern die Änderung passend zu Architektur/Design ausführt. Man kann aber auch eine aus Implementierungssicht erzeugte Änderung, die zunächst eine Funktionalität erfolgreich nachbessert, nochmals über die Designphase führen und damit die letztgültige Implementierung festlegen. In beiden Fällen werden die Änderungen primär im Quellcode eingebracht, unter Beachtung des Modells.


2.6 Nachteile, aus dem Quell-Code ein Repository zu generieren

Topic:.ModelBasedSwDevlp...

Der erste Nachteil ist, man muss die Konvertierungstools aus einem gegebenfalls speziellen Quellcode nach XMI erstmal haben.

Der zweite Nachteil ist gegebenfalls, dass man diese Konvertierungstools womöglich nachpflegen muss, wenn selbst erarbeitete oder beauftragte Lösungen nicht alles berücksichtigt haben. Beide Nachteile entfallen, wenn man Standard-Sprachen benutzt, für die es diese Tools gibt.

Wenn Änderungen auf UML-Basis ausgeführt werden sollen, dann können die Änderungen entweder direkt auf Quellcode-Basis ausgeführt werden, das Repository wird dann geändert wieder aus dem Quellcode erzeugt. Oft arbeitet man aber direkt mit dem UML-Modell in einem UML-Tool, ändert dort Grafiken und damit das Repository. Um diese Änderungen im Quellcode einzubringen, sollte entweder eine Quellcode-Generierung aus dem Repository vorhanden sein. Oder man muss diese Änderungen nachträglich per Hand einbringen, das Repository aus dem Quellcode neu generieren und vergleichen. Man hat hier einen ähnlichen Aufwand der Abstimmung Quellcode-Repository wie beim umgekehrten Weg der Generierung-Das liegt daran,dass man in dem Teil ändert, der nicht die primäre Quelle ist. Um die Nachteile dieser beiden Varianten abzuwägen, sind die folgenden Fragen zu stellen:


2.7 Mögliche Schlußfolgerungen

Topic:.ModelBasedSwDevlp...


3 Praktisches Beispiel: Generierung von XMI aus Java-Sourcen

Topic:.ExampleJava2xmi.

Es gibt zwar eine Reihe von UML-Tools, die speziell Java berücksichtigen. Im konkreten Fall war aber die Situation so, dass ein spezielles da eingeführtes Tool, konkret Rhapsody verwendet werden sollte. Rhapsody war aber nur für C++-Entwicklungen verfügbar. Denkbar wäre nun eine Nutzung eines anderen ggf. Open-Source-UML-Tools für Java, aus dem XMI generiert wird, um dieses XMI für die Zwecke der Darstellung im Entwicklerteam in dem dort eingeführten Rhapsody wieder einzulesen. Nun sind Tools aber meist nicht ganz trivial, man braucht Erfahrungen im Umgang.

Beim Entwickler lagen aber statt dessen Erfahrungen beim Parsen von Java-Quellcode mit einem ZBNF-Parser vor. Als "Abfallprodukt" der Java2C-Entwicklung konnte das vorliegende ZBNF-Parserscript Xml_Toolbase/zbnf/Java2C.zbnf verwendet werden, um aus Java-Quelltext XML zu erzeugen. Aus einer anderen vorliegenden Entwicklung, der XMI-Generierung aus Headerfiles, lag die Konvertierung aus einem ähnlich strukturierten XML-Files erzeugt mit Xml_Toolbase/zbnf/Cheader.zbnf nach XMI vor.

Die Anpassung der Scripts Xml_Toolbase/xsl/CheaderTypes.xsl und Xml_Toolbase/xsl/Cheader2Xmi.xslp ( - Endung .xslp siehe Preprozessor_XSLP - ) an die notwendigen Scripts Xml_Toolbase/xsl/Java2xmiTypes.xsl und Xml_Toolbase/xsl/Java2xmi.xslp zur Erreichung eines nutzbaren Ergebnisses erforderte einen Arbeitsaufwand von ca. einem Tag, an dem XSL-Scripts korrigiert wurden. Das Ergebnis ist ein XMI aus Java-Sources, dass in das vorliegende Tool Rhapsody eingelesen werden konnte. Die Sprachbindung an C++ spielte dabei keine Rolle, da sie nicht für die Abbildung XMI-Repository gilt sondern nur für die Codegenerierung bzw.das zugehörige Reverse Enginnering.. Der Nutzeffekt ist, nunmehr sind komplexe Strukturen in den Java-Sources in der gewohnten UML-Umgebung sichtbar.

Auch in Java ist die Abbildung Java-Quellcode - UML nicht unbedingt eineindeutig festgelegt. In der UML sind sich Fachexperten nicht immer einig, oft werden einem Nutzer Interpretationsspielräume gelassen. Bei einer Abbildung Repository - Quellcode, egal in welcher Richtung die Generierung erfolgt, müssen aber diese offenen Punkte festgelegt sein. Ein UML-Tool wird sich bei einer Festlegung entweder offen zeigen - man muss dem Kunden in seinen Wünschen entgegenkommen - was dann wiederum irgendwelche Einstellungen notwendig macht, oder es trifft eine gegebenfalls im konkreten Projekt wenige geeigneten Festlegung. Im vorliegenden XSL-Script ist folgende Festlegung bezüglich der Interpretation von Java-Attributen (Fields) zu UML-Attributen / Assoziationen / Aggregationen / Kompositionen getroffen:

An den aufgeführten Problemfällen ist sichtbar, dass eine eineindeutige Abbildung UML-Repositiory - Quellcode nicht immer einfach festlegbar ist. Das Problem trit aber in beiden Fällen der Generierung: Erzeugung des Codes aus dem Repository und umgekerht, auf. Wenn Quellcode aus dem Repositiory nicht genügend richtig erzeugt wird, dann ist die End-Funktion gegebenenfalls falsch. Das kann kritisch sein. Wenn das UML-Modell nicht ganz richtig dargestellt ist, ist das lediglich ein Dokumentationsproblem. Man kann dem Abhilfe geben, in dem im Kommentar des jeweiligen Elementes im Quellcode eine Annotation für die UML-Konvertierung angebracht wird. Diese kann im Konvertieurngscript berücksichtigt werden.