Suchen

Modellbasiertes Software Engineering Architekturprüfung für UML-Modelle

| Autor / Redakteur: Ingo Battis und Thomas Eisenbarth* / Christine Kremser

Die Versprechungen der UML-Modellierung mit anschließender Codegenerierung sind signifikant höhere Wartbarkeit, Fehlerfreiheit und Flexibilität im Vergleich zur manuellen Codierung. Damit muss man das UML-Modell so behandeln, als ob es die Stelle von Code einnähme, und es vor Software-Erosion und Implementierungsfehlern schützen.

Firma zum Thema

Ohne Architektur kein Modell: Erfolgreiche Modellierung setzt daher immer eine stimmige Architektur voraus.
Ohne Architektur kein Modell: Erfolgreiche Modellierung setzt daher immer eine stimmige Architektur voraus.
(Bild: gemeinfrei/Pixabay / CC0 )

In unserem Falle muss daher das Implementierungsmodell einer Architektur folgen, die folglich nicht im Implementierungsmodell selbst enthalten sein kann. Erst dadurch kann das Modell auf verschiedene Arten von Korrektheit geprüft werden.

Einsatz-Szenario bei Sennheiser

Für die Entwicklung eines neuen Projekts haben wir uns entschieden, zu einem großen Teil auf die Modellierung mittels UML und die anschließende Generierung von Code aus den Modellen zu setzen. Nur in der Treiberschicht soll manuelle Codierung eingesetzt werden. Zu diesem Zweck werden das Design und die Implementierung vollständig in Rhapsody durchgeführt.

Bildergalerie

Bildergalerie mit 6 Bildern

Außerdem pflegen wir eine Architektur, die die Blaupause für Design und Implementierung darstellt.

Hierarchisch gegliederte Modelle

Im betrachteten Projekt erfolgt die Entwicklung der Software als die Erstellung einer Hierarchie von Modellen. Diese Modelle werden durch Relationen ihrer jeweiligen Elemente miteinander verbunden. Eine dieser Relationen nennen wir Verfeinerung. In unserem Beispiel gibt es die Modelle Architektur, Entwurf und Codierung. Die Modelle werden in der Hierarchie von oben nach unten immer detaillierter und dabei immer konkreter. In unserem konkreten Anwendungsfall enthält die Architektur die Schichten, der Entwurf betrachtet Komponenten und weitere Details innerhalb der Schichten, die Codierung schließlich stellt konkrete Elemente der Zielsprache dar, z.B. C-Funktionen.

Die Elemente eines Modells werden in dem hierarchisch darunterliegenden Modell verfeinert. Die Architektur wird manuell zum Entwurf verfeinert, dieser wird in unserem Falle weitestgehend automatisiert durch einen Generator zur Implementierung implizit verfeinert.

In Bild 1 ist als Beispiel die Verfeinerung eines UML Packages aus der Architektur (Modell Mn) in zwei UML Packages im Entwurf (Modell Mn+1) dargestellt: Diese Verfeinerung ist später wichtig für die Prüfung. Die Verfeinerung erfolgt manuell und folgt in unserem Beispiel einer Namensregel, was für die Nachvollziehbarkeit zwar wünschenswert, jedoch im Allgemeinen nicht notwendig ist. Die hier beschriebene Vorgehensweise ist übrigens unabhängig von den konkreten Typen der Elemente und somit auch nicht auf die UML festgelegt.

Für unseren Ansatz ist es gleichgültig, in welcher Reihenfolge die Modelle erstellt und verändert werden. Die Modelle können nachträglich verändert und erweitert werden. Es ist somit nicht notwendig, die Modelle und die Verfeinerungen streng sequentiell und top-down (analog zu einem Wasserfallmodell) durchzuführen, eine iterativ-inkrementellen Vorgehensweise ist jederzeit möglich. Tatsächlich nutzt die angewendete Prüfungsmethodik die Modelle und die Verfeinerungsrelationen, jedoch kein Wissen über Reihenfolgen im Entstehungsprozess.

Wenn man UML-Werkzeuge einsetzt, um die hier angesprochenen Modelle zu definieren, dann hat man das Problem, dass in UML selbst nur ein UML-Modell existiert. Diagramme dienen nur der Darstellung, haben aber ansonsten keine Auswirkungen auf die Struktur des UML-Modells.

Um in der Hierarchie der Modelle prüfen zu können, ob eine korrekte Verfeinerung vorliegt, müssen die Modelle disjunkt und über die Verfeinerungsrelation verbunden sein. Ansonsten ist eine Prüfung nicht möglich. Beispiel: Nehmen wir an, die gleichen UML Package-Entitäten werden sowohl in der Architektur als auch im Entwurf genutzt.

In Bild 2 wird in Modell Mn eine UML Dependency zwischen zwei Packages A und B eingeführt, weil in Mn+1 in diesen Packages enthaltene Klassen voneinander ableiten. Genau diese Abhängigkeit hätte man so bereits in der Architektur einfügen können. Es lässt sich nicht mehr prüfen, ob diese Abhängigkeit korrekt von der Architektur in den Entwurf verfeinert worden ist.

Das Beispiel zeigt auch, dass ein System, bei dem eine Änderung in einem Modell automatisch zu einer Änderung im anderen Modell führt, keine Konsistenzprüfung zwischen den Modellen zulässt. Oft wird diese Kopplung als Vorteil gesehen („das Gesamtmodell stimmt immer“), es ist aber nur aus dem Gesichtspunkt des Reverse-Engineerings und des simplen Programmverstehens sinnvoll („ich sehe, was ist“). Aus der Sicht der Planung, der Nachvollziehbarkeit und des abstrakten Programmverstehens („ich sehe, wo die Unterschiede liegen zwischen dem was ist, und dem was sein sollte“) ist dieses Vorgehen kontraproduktiv.

Um die Integrität der Architektur zu gewährleisten, haben wir uns entschlossen, die Architektur in Enterprise Architect zu modellieren, das Design jedoch in Rhapsody. Auf diese Weise ist bereits technisch ausgeschlossen, dass ungewollt Beziehungen aus einem Modell in ein anderes gelangen.

(ID:44055610)