Die Zukunft der Modellierung: Interview mit Andreas Willert (Teil 1)

Dies ist der erste Teil eines Interview mit Andreas Willert, Geschäftsführer der Willert GmbH, die sich auf Software Engineering im Umfeld eingebetteter Systeme spezialisiert hat. Neben seiner geschäftlichen Tätigkeit ist er Buchautor und häufig als Sprecher auf Konferenzen und anderen Veranstaltungen zu sehen.

Ich unterhielt mich mit Andreas am 10. Oktober 2019.

Hinweis: Andreas Willert hält mit seinen Mitautoren das Seminar Model-Driven Embedded Software Engineering am 2. Dezember auf dem ESE-Kongress 2019.

Was ist der Stand der Modellierung in der Systementwicklung?

Interessant, dass Du nach System- und nicht nach Softwaremodellierung fragst. Im Bereich MBSE (Model Based Systems Engineering) erleben wir gerade einen riesigen Hype. Im SE setzt sich immer mehr die Erkenntnis durch, dass komplexe Systeme nicht mehr textuell nur auf Basis von Anforderungen beschrieben werden können, sondern das Modelle gebraucht werden.

Es gibt zur Zeit viele prominente Projekte, wie FAME bei Audi oder SEED (Systems Engineering Enhancement@DAIMLER) bei Daimler. Hierzu die Aussage von Daimler:

Bei Daimler digitalisieren wir jede Komponente bevor sie verbaut wird um Probleme frühzeitig zu erkennen, nur nicht im Software und Systems Engineering. Das muss sich ändern.

Das sind genau die Engpässe, die heute viele unserer Kunden haben. Heute werden mechanischen Komponenten digitalisiert und zuerst digital zusammengesetzt, bevor eine Komponente in der Produktion freigegeben wird. Das wird mit Software und Systems nicht gemacht. Bei dem SEED Programm geht es darum, das Gesamtsystem simulierbar zu machen, bevor es in die einzelnen Engineeringdisziplinen geht. Und das kann man nur mit Modellen machen.

Was ist der Haupttreiber für diese Initiativen?

Komplexität! Jemand belädt den Kofferraum, schließt ihn, und das System macht ihn immer wieder auf, weil es sich an irgendetwas stört. Die Entwickler sitzen monatelang daran, durch die verschiedenen Abhängigkeiten der Systeme nach dem Problem zu suchen.

Wenn die Komplexität des Systems steigt, dann steigt auch die Anzahl der Abhängigkeiten und die Gefahr, dass diese bei einer Änderung nicht vollständig berücksichtigt werden. Dort, wo unberücksichtigete Abhängigkeiten (so genannte Hidden Links) aufschlagen, entsteht Emergenz. Und aus diesen nicht definierten Reaktionsmustern kann dann Dysfunktion entstehen. Und je komplexer die Systeme werden, umso höher die Wahrscheinlichkeit für „hidden Links“, und umso höher die Wahrscheinlichkeit für Emergenz und Dysfunktion. Ein reales praktisches Beispiel: Jemand belädt den Kofferraum, schließt ihn, und das System Auto macht ihn immer wieder auf, weil es sich an irgendetwas stört. Die Entwickler sitzen monatelang daran, durch die Abhängigkeiten der Systeme über die Engineering Disziplinen hinweg nach der Ursache zu suchen.

Eine sichere Maßnahme dem zu begegnen wäre direkt die Komplexität zu reduzieren. Doch das ist in der Regel keine Lösung, denn dadurch müsste ich Funktionen einschränken, die das Produkt ja erst wettbewerbsfähig machen. Realistischere Optionen sind, die Komplexität managebar zu machen, zum Beispiel durch die Erhöhung der Abstraktion. Ich verstehe dann besser die Zusammenhänge.

Es geht fast immer darum, die „hidden Links“ zu verhindern, bzw. deren Anzahl zu reduzieren. Das geht mit Abstraktionen, Contract-based Design oder Traceability.

Modellierung greift an verschiedenen Punkten. Zum Beispiel kann Contract- Based Design in UML auf Basis von Ports und Interfaces viel leichter umgesetzt werden als etwa mit C. Modelle greifen sowohl auf der Contract-Based-Design-Ebene, als auch der Abstraktionsebene, als auch der Traceability-Ebene. Um kurz über Software, nicht Systeme zu sprechen: Wie machst Du denn einen ein- eindeutigen Link auf eine Zeile Code? Es gibt keine Metastruktur, keine eindeutigen IDs (UUIDs) im Code oder im Editor. Diese gibt es jedoch im Modell – die entsprechende Toolunterstützung vorausgesetzt. Damit kann dann das Problem der „hidden Links“ adressiert werden.

Aber ist in der Programmierung die Signatur einer Klasse und deren Methode nicht etwas vergleichbares wie eine UUID?

Zeig mir ein Werkzeug, das da einen eineindeutigen Link drauf setzen kann. Modellierung zeigt hier einen Weg, denn UML gibt mir eine UUID, die ich für Linkbeziehungen und infolge Traceability nutzen kann. Damit haben wir dann eine Traceability von Anforderung zum Modell, und über Codegenerierung bis zum Code. Und mit geeigneten Werkzeugen auch in die Verifikation.

Noch mal zurück zum Stand der Modellierung: In manchen Bereichen hat sie sich ja durchgesetzt. Die Hälfte unserer Kunden zum Beispiel setzt Matlab und Simulink ein. Dort werden weder Modellierung, Codegenerierung oder Simulation in Frage gestellt, ganz im Gegenteil

Das interessante ist ja, dass sich die Modellierung in manchen Bereichen sehr erfolgreich durchgesetzt hat und in manchen nicht. Die spannende Frage ist doch: Was macht den Unterschied aus? Ich würde gerne noch einmal die verschiedenen Engineering Bereiche betrachten. Im Systems Engineering gibt es gerade einen riesigen Boom zur Modellierung. Im Software Engineering sehe ich drei Bereiche: Ich sehe die statische Architektur, also Klassen, Objekte, Methoden, etc. Dort wird rudimentär modelliert, zum Beispiel mit Enterprise Architect, weil das Werkzeug fast nichts kostet. Oftmals werden daraus auch Coderümpfe generiert. In der Verhaltensmodellierung wie Reglern und Zustandsmaschinen hat sich Matlab stark durchgesetzt. Dort wird auch die Codegenerierung durchweg eingesetzt und nicht mehr in Frage gestellt. Und es gibt die Ereignis (Event) Basierte Architektur, wo tendenziell wieder eher UML eingesetzt wird, sich aber nicht wirklich durchsetzen konnte.

Interessanterweise hat sich in der Softwareentwicklung die UML bis heute nicht wirklich konsequent durchgesetzt.

Interessanterweise hat sich in der Softwareentwicklung die UML bis heute nicht wirklich konsequent durchgesetzt, vor allem nicht in der durchgängigen Anwendung, z.B. wie bei Matlab / Simulink. Und die Codegenerierung wird dort häufig abgelehnt, im Gegensatz zu Matlab.

Das ist kein neues Phänomen, das ist schon 15 Jahre alt. Damals gab es auch bei Matlab Vorbehalte, aber inzwischen gibt es die zwei Codegeneratoren, ‚TargetLink‘ von dSpace und ‚EmbeddedCoder‘ von Matlab selber. Da herrscht Konsens darüber, dass die Modellierung ohne Codegenerierung wenig Vorteile bringt.

Ich habe auch eine Erklärung dafür – ich weiß nicht, ob sie stimmt, aber das ist meine Interpretation. Diejenigen, die mit Matlab arbeiten, haben typischerweise wenig Programmiererfahrung. Das sind Maschinenbauer und Elektrotechniker, die Regler entwickeln. Für die ist es ein Problem, einen Regler zu codieren. Die sind glücklich, dass sie sich in ihrer Domänensprache (Matlab) den Regler zusammenklicken und simulieren können. Wenn alles passt drücken sie einen Knopf, und daraus wird Code generiert. Aus heutiger Software Enineering Sicht ist der generierte Code übrigens weit von modernen Prinzipien entfernt. Ein heutiger erfahrener Java oder C++ Programmierer würde wahrscheinlich die Hände über dem Kopf zusammen schlagen. Da ist die Codegenerierung z.B. aus UML auf Basis von Rhapsody sehr viel eleganter und objektorientiert. Bei Matlab wird das interessanterweise akzeptiert, bei Rhapsody kritisiert.

Warum? Ich vermute, weil viele Matlabanwender nicht unbedingt erfahrene Programmierer sind und den generierten Code aus fachlicher Qualitätssicht gar nicht beurteilen können.

Jetzt kommt die UML und richtet sich an den Software Entwickler, der seit 15 Jahren C-Code programmiert. Der kann programmieren, aber kein UML. Du bringst ihn auf eine Ebene, wo er das Verständnis auf Modell Ebene noch nicht hat und durch eine Talsohle muss, wo er erst mal am Kämpfen ist mit der UML. Und dann kommt da noch ein Code-Generator, der Code generiert, den er auch erst einmal nicht versteht. Der ist nicht unbedingt schlechter, aber anders, und der Programmierer hat das Gefühl, dass er jegliche Kontrolle verliert. Und dagegen sträubt er sich. Das ist zumindest meine Erklärung, warum sich in Matlab Codegenerierung durchgesetzt hat, aber nicht in der Anwendung der UML. Die Zielgruppen der Anwender sind andere.

Um von der Modellierung profitieren zu können, muss erst eine Talsohle (Lernkurve) durchschritten werden, was viele sich nicht trauen, bzw. im beruflichen Alltag die Zeit dafür nicht vom Management zugestanden bekommen.

Kunden, die diese Talsohle durchschritten haben, sagen fünf Jahre später: „Wir wissen gar nicht mehr, wie wir ohne Modelle, Simulation und Codegenerierung engineeren können.“

Hat das vielleicht etwas damit zu tun, dass ein Simulink-Modell oft domänenspezifisch ist, also bspw. ein Regler, während das UML-Modell generisch ist?

Das glaube ich nicht. Es ist eher ein Problem, dass die UML im ersten Ansatz vor ca 15 Jahren nicht wirklich durchgängig (aus Sicht des Engineering) spezifiziert wurde. Es gibt da insbesondere zwei Dinge in der UML: Sie hat nicht sofort eine Art „Action-Language“ gehabt, wodurch wir es nicht schaffen, vollständig im Modell zu arbeiten. Spätestens, wenn Du eine C-Variable abfragen willst, dann gibt es dafür kein UML-Notationselement. Du musst teilweise bis auf die C, oder C++-Ebene herunter, also die Action-Language. Man hat dort eine Lücke gelassen, aber das hat es ja schon immer gegeben. Selbst in C gibt es die Möglichkeit, Assembler in-line einzubetten. Das ist nichts Neues oder Dramatisches, aber hat Entwickler davon abgehalten zu Modellieren, da sie ja trotzdem noch Anteile programmieren mussten. Eigentlich eine Ausrede, höre ich aber oft als Argument. Übrigens wird diese Lücke gerade geschlossen in der OMG UML Arbeitsgruppe ‚Precise Semantic‘.

Das viel Schwerwiegendere ist, dass beim Entwurf der UML die drei Amigos die Codegenerierung gar nicht auf dem Schirm hatten. Das verwundert mich bis heute. Vor allen, da bis zu diesem Zeitpunkt alle am Markt etablierten Modellierungswerkzeuge für Software Codegenerierung unterstützt haben. Rose RT (Object Time), StateMate, STL-Suite (SDT) oder Rhapsody).

Als die UML geschaffen wurde, konnten alle erfolgreichen Softwaremodellierungswerkzeuge Code generieren. Meiner Meinung nach war die Modellierung damals viel weiter, als sie heute ist.

Wir haben heute noch Kunden, die mit den alten Werkzeugen ObjectTime oder SDT arbeiten und sehr zufrieden sind. Sie modellieren damit bereits seit zwanzig Jahren. Sie wechseln nicht auf UML Lösungen, weil sie mit diesen alten Umgebungen durchgängiger unterwegs sind, bis hin zu Simulation und allem drum und dran. Und das, obwohl die Werkzeuge an sich inzwischen ziemlich veraltet sind.

Modellierung in Software hat schon mal funktioniert, Ende der 90er bis Mitte 2000. Und meiner Meinung nach hat die UML dadurch, dass sie in Richtung „Bildchen-Malen“ und Dokumentation gegangen ist, diese ganze Bewegung zunichte gemacht, und heute sind wir rückständiger als wir es vor 15 Jahren waren. Wobei die Grundidee, eine standardisierte Notation zu haben, super war. Wie es umgesetzt wurde ist destruktiv gewesen. Da haben die drei Amigos dem Engineering absolut keinen Gefallen getan.

Ist die UML vielleicht auch zu kompliziert?

Das glaube ich nicht. Es gibt natürlich mehrere Gründe, aber ich sehe das Problem darin, dass die drei Amigos die Modellierung zum Bildchen-Malen getrieben haben, und nicht in Richtung von seriösem Engineering mit Simulationsfähigkeit der Modelle und Codegenerierung.

Durch das Grafische ist vielleicht sogar ein Trugschluss entstanden: Man denkt, „Es ist ja ganz einfach, wir malen Bildchen.“ Und es wird häufig „detailliert“ mit „präzise“ verwechselt. Und viele sagen: „Das ist nicht simulierbar“, und meinen, es müsste dafür detaillierter sein, es müsse jede C-Variable definiert und modelliert sein, bevor ich simulieren kann. Aber das stimmt ja so nicht. Um es simulieren zu können, muss es auf einer bestimmten Ebene präzise sein.

In der UML-Modellierung wird häufig „detailliert“ mit „präzise“ verwechselt.

Ein Beispiel: Wenn ich im Windkanal meine Aerodynamik testen möchte, dann muss ich ein Modell meines Autos oder Flugzeugs erstellen, welches sehr präzise bezüglich der aerodynamischen Eigenschaften ist. Es muss aber nicht detailliert sein, also beispielsweise den Motor und das Getriebe enthalten. Das wird häufig verwechselt, gerade von Programmierern. Die haben oft keine Vorstellung, wie man überhaupt nach oben abstrakt werden kann, weil sie das nie im Leben gemacht haben.

In der Entwicklung wird aus der Vergangenheit viel von unten nach oben, und nicht von oben nach unten gearbeitet. Man baut hier ein kleines Fragment, nimmt erst einmal den CAN-Bus in Betrieb, dort den Sensor, und so weiter. Mit UML, oder modellgetrieben, geht man genau den umgekehrten Weg. Das ist für die meisten nicht vorstellbar, und sie haben es noch nie im Leben gemacht.

Das ist ein Handikap, nicht detailliert statt präzise zu arbeiten, vielleicht die Interfaces mit Ports zu definieren und sich auf Architekturgesichtspunkte zu konzentrieren, wie Contract-Based Design. Es ist doch in einer frühen Design-Phase nicht wichtig, ob hier ein Integer oder Float benutzt wird. Viel wichtiger ist, wenn ich Top-Down abstrahiere, wird hier „Kilometer pro Stunde“ mit „Miles per Hour“ zusammengesteckt, oder wird auch ein gültiger Sensorwert geliefert wenn die Zündung aus ist? Wir müssen erst einmal auf der logischen Ebene konsistent sein, nicht im Detail, aber in der Präzision. Das muss abgesichert sein, bevor ich im Detail implementiere. Die Kurve, wo die Kosten über die Zeit explodieren wenn Fehler entstehen bzw. behoben werden müssen, sollte ja allgemein bekannt sein. Maßnahmen zu ergreifen, um das Risiko bereits in frühen Designphasen zu verringern, ist die Basis, um Kosten und Zeit zu sparen. Das ist mit Front Loading gemeint und es ist bei steigender Komplexität unverzichtbar.

Zum 2. Teil >>