Skip to main content

Anwendung von Methoden und Werkzeugen für Excellence im Software- und Systems-Engineering

Warum ist ein Wechsel der Methode (z.B: Prozedural zu OOP, Programmierung zu Modellierung ...) oder ein Wechsel der Notation (z.B: C zu C++, C++ zu UML ...) oder der Einsatz eines neuen Werkzeugs (z.B: MATLAB® , Rhapsody® , Test Realtime®, DOORS®, Tessy®...) häufig kontraproduktiv und führt zu noch mehr Problemen? Was muss berücksichtigt werden, damit die Produktivität wie erwartet gesteigert werden kann?

Warum ist die Kombination von Methode, Werkzeug und Prozess mehr als die Summe ihrer Teile?

Warum erfordert die Einführung neuer Vorgehen einen Paradigmenwechsel im Engineering und welche Probleme ergeben sich daraus, herkömmliche Software weiter zu verwenden? Wie können diese Probleme überwunden werden?

Warum werden Unternehmen am Standort Deutschland, die diese Innovationen nicht einsetzen, in den kommenden 10 Jahren Probleme bekommen?

Vorgehensweisen

In der Newsletter Serie „Richtiges richtig tun“ kommen wir an dieser Stelle zum Kern dieser Aussage.

Der Nutzen eines Werkzeugs ist nur so groß, wie die Eignung des Werkzeugs für die zu verrichtende Aufgabe. Sehr häufig werden Werkzeuge für Arbeiten eingesetzt, für die sie eigentlich nicht gedacht sind. Oder sie werden in Kombination mit Methoden eingesetzt, für die sie sich nicht gut eignen. ,Mit dem Hammer in der Hand sieht die Welt aus wie ein Nagel‘, da wird auch schon einmal eine Schraube mit dem Hammer in die Wand geschlagen. Das ist mühsam und vor allem die ,Schraub‘-Verbindung wird auf diese Weise nicht das ,halten‘, was sie verspricht.

Was mit Nägeln immer gut funktioniert hat läuft auf einmal schief, obwohl doch die viel teureren und angeblich besseren Schrauben verwendet werden.

Erfolgreiches Anwenden von Methoden, Werkzeugen ... ist von verschiedenen Einflüssen abhängig. Jedem SoftwareEntwickler ist sicher klar, dass, wenn ich einen C-Compiler einsetze, mit diesem aber weiterhin in Assembler programmiere (mit Inline Assambler Instruktionen wäre das möglich), würde ich nicht viel effizienter werden. Im Gegenteil, die Handhabung eines Compilers auf diese Art wäre wahrscheinlich aufwändiger, als die eines einfachen Assemblers. Dieses Vorgehen ist also sicher nicht von Erfolg gekrönt.

Trotzdem sind vergleichbare Kombinationen in der Praxis immer wieder anzutreffen. Der Einsatz eines C++ Compilers ohne wirkliche OOP-Erfahrung. Die Kombination von Scheduling Pattern mit ungeeigneten Kommunikations Pattern ...

Wenn das Werkzeug dann nicht so hilfreich ist, wie vom Vertrieb angepriesen, wird häufig dem Werkzeug oder dem Vertrieber die Schuld gegeben.

∨ mehr Text anzeigen

Abgesehen davon, dass es Werkzeuge gibt, die ihr Geld nicht wert sind, ist ein unsachgemäßer Umgang mit ihnen auch häufig anzutreffen.

Zu einer erfolgreichen Vorgehensweise im Software Engineering gehören im Wesentlichen die in Abbildung Nr. 1 zu sehenden Faktoren:

An erster Stelle steht der Prozess. Innerhalb dieses Prozesses werden für die anstehenden Arbeitsschritte Methoden herangezogen. Soll der Einsatz der Methode durch Werkzeuge unterstützt werden, dann wird eine Notation und ein Werkzeug benötigt. Letztendlich muss der Anwender entsprechende Kenntnisse und Erfahrungen haben, Prozess, Methode, Notation und Werkzeug fachgerecht anzuwenden.

Nur wenn alles harmonisch in sich ist, wird das Ergebnis hinsichtlich Kosten, Arbeitseinsatz und erzeugter ArbeitsQuantität und -Qualität zu einem effizienten Ergebnis führen.

Passt einer der Faktoren nicht, so passiert etwas, was häufig unterschätzt wird. Justus von Liebig hat auf Basis dieser Erkenntnis den Ertrag der Lanwirtschaft revolutioniert. Eliyahu M. Goldratt sieht es in seinem Buch ,Das Ziel‘ als Basis jeglicher Prozessoptimierung.

Es ist die Engpasskonzentrierte-Analyse. Sie besagt, das Ergebnis eines Prozesses ist immer nur so gut, wie der Durchlass des Engpass-Faktors.

Was Justus von Liebig an Pflanzen entdeckte, weiß heute jede Hausfrau. Eine Pflanze benötigt im Wesentlichen vier Faktoren: Wasser, Nährstoffe, Licht und Wärme. Mangelt es an einem Faktor, hilft es nicht, die anderen Faktoren zu erhöhen. Ganz im Gegenteil, hat die Pflanze Mangel an Wasser, so ist die Erhöhung der Temperatur kontraproduktiv. Der gleiche Mechanismus gilt für jeden Prozess, auch für Software- und System-EngineeringProzesse. In Abbildung Nr. 1 wird die Leistung eines Prozesses durch die Fläche der Kreise dargestellt. Der begrenzende Faktor wirkt auch als Begrenzung für alle anderen Faktoren bezüglich des Durchsatzes. Investitionen in die Faktoren, die keinen Engpass verursachen, wirken sich nicht leistungserhöhend aus. Ganz im Gegenteil, sie binden Geld und Zeit, was sich aus Sicht des Gesamtsystems negativ auswirkt. Kosten steigen, der Output nicht.

Und hier die gute Nachricht: die Investition in den Engpass wirkt sich hinsichtlich der Leistung exponentiell aus. Das gilt natürlich nur so lange, wie dieser Faktor der Engpass ist.

Beispiele aus der Praxis

Jeder kennt die Aussage, dass sich in jeder Sprache objektorientiert programmieren lässt. Man muss nur wissen, wie es geht. Das ist natürlich grundsätzlich richtig. Bezogen auf die Effizienz möchte ich jedoch behaupten, dass die Anwendung OOP auf Basis der Noataion C++ und eines Compiler zu effizienteren Ergebnissen führt, als die Anwendung der Notation Assembler.

Aber umgekehrt gilt das Gleiche. Die Anwendung der Notation C++ mit einem C++ Compiler ohne ausreichende Kenntnisse in der OOP liefern unter Umständen unwirtschaftlichere Ergebnisse, als die erfahrene Anwendung der strukturierten Programmierung auf Basis der Notation C.

Ich kenne ein Projekt, in dem ein EC++ - Compiler (Embedded C++ - Compiler) eingesetzt wurde, der keine Mehrfachvererbung unterstützte. Darauf war aber das ganze Konzept der Software-Implementation abgestimmt und musste nun neu erstellt werden, was mehrere Monate benötigt hat. Preiswerter wäre es gewesen, einen neuen Compiler zu kaufen, was die Geschäftsleitung nicht bewilligt hat. An dieser Stelle zu sparen war letztendlich eine teure Entscheidung. Eine einzelne Eigenschaft eines Tools war in diesem Fall der Engpass und, wie dieser Fall gezeigt hat, ist es am Ende teuer wenn am Engpass gespart wird.

 

Architektur Design

Das Software Architektur-Design bildet sehr häufig die Basis für ein große Anzahl an Entscheidungen zum Einsatz der Mittel im Software Engineering. Angefangen vom Einsatz der Werkzeuge, über die Methode, bis hin zur Notation. Damit bildet es auch entsprechend häufig den Engpass.

Um das besser zu verstehen, an dieser Stelle erst einmal etwas Grundsätzliches zum Architektur-Design.

Gerade in Embedded Systemen für technische Systeme haben wir hinsichtlich der Laufzeitarchitektur eine Basisentscheidung zu treffen. Diese Entscheidung ist weichenstellend für viele weitere Entscheidungen.

Dabei haben wir es mit der grundsätzlichen Problematik zu tun, dass sich unsere reale Umwelt aus zeitlicher Sicht kontinuierlich verhält und keine Sprünge (vor allem nicht in der Zeit) kennt. (Für diese Betrachtung gehen wir nicht in die Tiefen der Quantenphysik). Es kommt noch etwas anderes hinzu. Die reale Umwelt ist nicht sequenziell und rhythmisch, sondern chaotisch mit einer großen Varianz an Frequenzen und Ereignissen und das alles parallel bzw. mit infinitesimal kleinen Zeitunterschieden.

Unsere CPU hingegen hat einen ganz anderen Charakter. Sie ist zeitdiskret. Aus zeitlicher Sicht gibt es einen Augenblick in dem genau ein Vorgang bearbeitet werden kann. Es gibt keine Parallelität (An dieser Stelle betrachten wir keine Multi Prozessor Systeme sondern beschränken uns auf eine CPU).

Die kleinste Zeiteinheit ist unsere Taktfrequenz des Prozessors. Stoßen aus unserer Umwelt zwei Ereignisse in kurzer Folge (innerhalb der Zeiteinheit unserer Taktfrequenz) auf unsere CPU und die Software muss darauf reagieren, dann kann das aus Sicht der Außenwelt nur sequenziell geschehen. Es wäre streng genommen kein Echtzeitverhalten mehr.

So weit die Theorie. Zum Glück sind die zeitlichen Anforderungen in der Praxis nicht ganz so kritisch. In der Regel reicht es, wenn unsere CPU in einer Zeit reagiert, die weit oberhalb unserer Taktfrequenz liegt. Typische Werte für die Taktfrequenz liegen im Nanosekundenbereich. Die typischen Reaktionszeiten unserer Systeme hingegen liegen Faktor 1.000 darüber im Mikrosekundenbereich.

Oft liegen sie so weit darüber, dass wir uns aus ArchitekturSicht einen Luxus erlauben können. Der nennt sich Round Robin oder main() Loop. Das heisst, die CPU führt einzelne Teile unserer Software, die eigentlich parallel reagieren müssen, einfach zyklisch nacheinander aus. Dabei liegt die Zykluszeit des gesamten Durchlaufs immer noch weit unter der minimalen Reaktionszeit der zeitkritischsten Routine. Damit erscheint unser System gegenüber der realen Umgebung, als würde es sich zeitkontinuierlich verhalten.

Jeder, der einmal einen Regler programmiert hat, kennt diese Situation. Der Regler muss gegenüber seiner Strecke (Umwelt) in einem bestimmten Zeitintervall reagieren. Dann erscheint das Verhalten des Reglers zeitkontinuierlich, obwohl es streng genommen immer zeitdiskret ist.

Aber manchmal holt uns die Zeit ein. Das heißt, es gibt Reaktionszeiten, die kleiner sind, als die Zykluszeit unserer Schleife, die alles abarbeitet.

Nun haben wir zwei Möglichkeiten:

  1. Wir bleiben bei unserer Laufzeitarchitektur (die Schleife) und leisten uns eine schnellere CPU.
  2. Wir optimieren das Laufzeitverhalten unserer Schleife.

Meistens ist 1. zu teuer und es kommt 2. zum Einsatz. Denn bei genauerem Hinsehen stellen wir fest, dass nicht all unsere Routinen innerhalb der Zykluszeit unserer Schleife reagieren müssen. Wir können also eine schnelle und eine langsame Schleife programmieren und die Funktionen entsprechend ihrer notwendigen Reaktionszeit zuordnen.

Nun werden einige der Funktionen wesentlich seltener ausgeführt. Dadurch gewinnen wir CPU-Zeit, die wir nutzen können, um die anderen Funktionen entsprechend häufiger auszuführen.

Aber bald werden wir sehen, dass innerhalb dieser Schleifen das gleiche Problem wieder auftritt. Wir können natürlich noch weiter optimieren und noch weitere Schleifen mit neuen Zykluszeiten einführen.

Spinnen wir dieses Beispiel weiter, dann hat am Ende jede Funktion ihre eigene Zykluszeit.

Aber unser System muss noch schneller reagieren, was machen wir nun?

Bei der bisherigen Architektur fragt unser System die Umwelt auf Veränderungen ab (Polling). Wenn wir auch da genauer hinsehen, dann stellen wir evtl. fest, dass sich in einigen Fällen die Umwelt gar nicht verändert hat und wir ganz umsonst abgefragt haben (einen Schalter z.B.). Also gibt es noch mehr Optimierungspotential. Wir könnten das Signal auf Basis eines Flankenwechsels am Schalter über einen Interrupt Eingang unserer CPU erkennen. Dann würde unsere Routine immer nur dann ausgeführt, wenn eine reale Anforderung aus der Umwelt anliegen würde.

Nun sind wir bei einer ganz anderen Laufzeit-Architektur angelangt, der ,Ereignis getriebenen‘.

Bisher hatten wir Zeitintervalle als zentralen Steuerungsmechanismus. Funktionen unseres Systems wurden nach festem, zeitlichen Schema abgearbeitet (Zeitorientierte Laufzeit-Architektur). Nun haben wir Ereignisse als Steuerungsmechanismus (Ereignisorientierte Laufzeit-Architektur).

Grundsätzlich lassen sich folgende Eigenschaften über diese beiden grundverschiedenen Laufzeit-Architekturen feststellen:

  • Ereignisorientierte Laufzeitarchitekturen reagieren hinsichtlich der Reaktionszeiten und der CPUAuslastung immer optimaler als zeitgorientierte Architekturen.
  • Ereignisorientierte Systeme sind von der Logik her analoger zur realen Umwelt. Komplexe Systeme lassen sich mit ihnen verstehbarer darstellen.
  • Ereignisorientierte Systeme sind wenig robust gegenüber unsicheren Sensorsignalen. Eine (z.B. durch Elektrosmog hervorgerufene) Flut an Ereignissen kann das System überlasten und zu Ausfällen führen. Aus diesem Grund werden sie seltener in sicherheitskritischen Anwendungen verwendet.

Eine der elementaren Architekturentscheidungen, die in jedem ,ja in jedem‘ Projekt getroffen werden muss ist die Entscheidung, ob eine laufzeitorientierte oder eine ereignisorientierte Architektur eingesetzt wird.

Eine Kombination von beiden ist grundsätzlich möglich, nur sollte man sich darüber bewusst sein, dass in beiden Verhalten grundsätzlich unterschiedliche Gesetzmäßigkeiten gelten und diese dann leicht durcheinander geraten können.

Kommunikation und Daten

Eine laufzeitorientierte Architektur harmonisiert nur mit zeitkontinuierlichen Daten (Signalen). Also Daten, die zu jedem Augenblick gültig sind. Stellen Sie sich einen CANBus vor, der einen Datenwert liefert. Dieser kommt sicher nicht zu genau dem Augenblick, in dem die Routine, die ihn verarbeiten soll und auslesen wird, Rechenzeit hat. Also muss der Datenwert in einer (aus zeitlicher Sicht kontinuierlichen) Variablen zwischengespeichert werden. Hier ist ein Paradigmenwechsel notwendig.

Infolgedessen vertragen sich Ereignisse und zeitgetriebene Laufzeit-Architekturen nicht gut.

Unsere Außenwelt liefert uns aber in der Regel Ereignisse. Der Fahrer tritt auf die Bremse, wann er es für sinnvoll hält und nicht, wenn die Zeitscheibe zur Auswertung des Bremsensensors gerade Rechenzeit hat. Das Rad blockiert entsprechend den physikalischen Gesetzmäßigkeiten der Umwelt und nicht synchron zur Zeitscheibe unserer Laufzeit-Architektur

Was will ich damit sagen? Unsere Außenwelt ist ereignisgetrieben und unsere CPU zeitgetrieben. Wir haben es mit zwei grundsätzlich unterschiedlichen Paradigmen zu tun.

Zum Glück können beide Paradigmen ineinander konvertiert werden, und mindestens einmal in jedem Softwaresystem findet dieser Paradigmenwechsel zwischen kontinuierlich und diskret statt.

Grundsätzlich gibt es drei Möglichkeiten, wo dieser Paradigmenwechsel stattfinden kann.

Auf der Grenze der Sensorik und Aktorik.

  1. Das ganze Software System läuft zeitgetrieben und pollt zyklisch auf die Sensorik und Aktorik.
  2. Auf der Grenze zur CPU. Die Sensorik und Aktorik wird auf Basis des Interrupt Systems abgetastet. Auch das geschieht natürlich aus zeitlicher Sicht diskret, aber mit der schnellst möglichen Taktrate, die die CPU zur Verfügung stellt. Die CPU führt den Paradigmenshift durch den Interrupt Controller durch.
  3. Irgendwo dazwischen innerhalb der Softwarearchitektur

Alle drei Möglichkeiten sind in der Praxis gebräuchlich. Oft findet man auch mehrmalige Paradigmenwechsel innerhalb einer Softwarearchitektur, aber genau das kann äußerst kritisch sein.

∨ mehr Text anzeigen

Wie wir gesehen haben, gelten innerhalb der beiden Paradigmen unterschiedliche Gesetze was die Kommunikation anbelangt. Werden beide Ansätze vermischt, dann wird unklar, welche Gesetze gerade gelten und dann addiert sich zu der eigentlichen Komplexität der Applikation eine nicht unerhebliche Komplexität der Laufzeit-Architektur. Systeme mit einer inkonsistenten Laufzeit-Architektur werden wesentlich schneller unverstehbar und damit unrobust in ihrem Verhalten.

Wie wir an dieser Stelle bereits sehen: die LaufzeitArchitektur steht in unmittelbarem Zusammenhang mit der Kommunikations-Architektur. Grundsätzlich kann gesagt werden, dass eine zeitgetriebene Laufzeit-Architektur nur mit zeitkontinuierlichen Daten harmonisiert und eine ereignisorientierte Laufzeit-Architektur mit Ereignissen.

Bisher haben wir nur kooperative Laufzeit-Architekturen betrachtet. Da sind die Gesetzmäßigkeiten noch relativ einfach. Bei präemtiven (unterbrechbaren) LaufzeitArchitekturen kommen weitere hinzu. Hier werden in der Praxis häufig elementare Fehler in der Kombination von Architekturmustern gemacht. Aber in diesem Rahmen möchte ich nicht weiter darauf eingehen. (Wenn Sie interessiert sind können Sie das Thema vertiefen mit unserer Newsletter No 21 ,Jonglieren mit der Zeit‘ unter willert.de/newsletter).

Ich möchte jetzt den Bogen zur Modellierung spannen.

Kontinuierliche und diskrete Signale

Die Begriffe kontinuierlich (continuous) und diskret (diskontinuierlich; discrete) beziehen sich sowohl auf die unabhängigen Variablen (Raumkoordinaten x, y, z; Raumwinkel α, β, γ; Länge; Zeit; Frequenz; Wellenlänge usw.) (discrete time signal, DTS), als auch auf die abhängige Variable x (discrete amplitude signal). Ein kontinuierliches Signal liegt dann vor, wenn dieses für jeden beliebigen Wert der unabhängigen Variablen jeden beliebigen Wert der abhängigen Variablen annehmen kann. Dagegen wird ein diskretes Signal nur diskrete, das heißt, höchstens abzählbar viele Werte bezüglich der unabhängigen und / oder abhängigen Variablen annehmen. Da fast alle physikalischen Größen kontinuierlich sind, entstehen nichtkontinuierliche Signale meistens künstlich. Generell ist eine physikalische Größe eine Funktion von Raum und Zeit. Wegen des Aufwandes ist es nicht möglich (und oft auch nicht sinnvoll), den Wert einer Größe an jedem Raumpunkt und zu jedem Zeitpunkt zu ermitteln.

Quelle: Ruhm, K. H. "Wissenschaft und Technik des Messens" (PDF)

Modellierung und Architekturdesign

Ein weiteres Beispiel, das ich im Rahmen der Verbreitung der Modellierung antreffe, ist die Anwendung von Modellierungsmethoden und Diagrammen, die nicht mit der darunter liegenden Software-Architektur harmonisieren.

Bei Kundengesprächen treffe ich immer häufiger darauf, dass das logische Verhalten von Software auf Basis von Zustandsmaschinen modelliert wird. Das begrüße ich natürlich, da es eine gute Methode ist, der steigenden Komplexität von Verhalten zu begegnen.

Nun muss man wissen, dass Zustandsautomaten im ursprünglichen Gedanken als Zustandsübergang auf Ereignisse reagieren. Viele technische Systeme haben jedoch keine ereignis- sondern eine zeitorientierte LaufzeitArchitektur. Das heißt, die verschiedenen Teile einer Applikation werden mit bestimmten Zeitintervallen von der CPU abgearbeitet. Der Datenfluss geschieht dementsprechend nicht auf Basis von Ereignissen, sondern auf Basis von Signalen (aus zeitlicher Sicht kontinuierlich gültige Werte z.B. in Form von Variablen). Das kennen wir ja aus dem vorherigen Kapitel.

Die meisten Werkzeuge, Matlab® Stateflow®, IBM® Rational® Rhapsody®, ... lassen nun auch die Modellierung von Zustandsautomaten auf Basis von kontinuierlich anliegenden Signalen zu.

Dazu werden für Zustandsübergänge so genannte ,Guards‘ (Abfrage der Inhalte von Variablen) verwendet.

Lassen Sie uns einmal exemplarisch die Logik einer Bedienerschnittstelle betrachten. In unserem Fall gibt es drei Tasten zur Bedienung eines Monitors. Zwei Tasten, um Lautstärke (volume) oder Helligkeit (brightness) zu erhöhen oder zu verringern (plus, minus), und eine Taste zum Umschalten zwischen der Bedienung von Lautstärke und Helligkeit (mode). Entsprechend den Tasten werden einmal Ereignisse in Form von Events erzeugt und einmal Variablen gesetzt.

In Abbildung Nr. 2 ist das beschriebene Verhalten auf Basis von Ereignissen und in Abbildung Nr. 3 auf Basis von sogenannten Guards implementiert.

So weit könnte man denken, sind beide Verhalten gleich und oberflächlich betrachtet wird das Verhalten auch gleich sein.

Werfen wir jedoch einen Blick auf das Zeitverhalten. Die CPU wird diesen Teil der Applikation nicht exklusiv ausführen. Dieser Teil der Logik wird also in einem Zeitraster ausgeführt. Immer wenn die CPU andere Teile der Applikation ausführt, ist dieser Teil nicht aktiv.

Stellen wir uns nun einen besonderen Fall vor: die Logik befindet sich im Modus ,Helligkeit‘ und ein Bediener möchte die Lautstärke erhöhen. Dann wird er erst die ,mode‘ Taste drücken und dann die ,plus‘ Taste. Aber genau in diesem Augenblick ist die CPU sehr beschäftigt und der Bediener drückt die Tasten ganz schnell hintereinander, so dass in der Austastlücke unserer Zustandsmaschine beide Tasten innerhalb eines Zeitintervalls gedrückt werden.

Jetzt werden beide Implementierungen evtl. unterschiedlich reagieren. In der Zustandsmaschine, basierend auf Ereignissen, liegt im Hintergrund eine so genannte Queue. In ihr ist die Reihenfolge der Ereignisse gespeichert und in genau dieser Reihenfolge wird die Zustandsmaschine sie auch abarbeiten. Die Logik wäre also eindeutig.

Im Fall der zeitgetriebenen Architektur auf Basis von Signalen gibt es die Information, in welcher Reihenfolge die Variablen geändert wurden, aber nicht. In dem Augenblick, in dem die Zustandsmaschine wieder Rechenzeit bekommt, sind zwei Variablen geändert. Daraus ergibt sich eine zweideutige Situation. Je nachdem, in welcher Reihenfolge ,mode‘ und ,plus‘ abgearbeitet werden, würde einmal die Helligkeit, und ein anderes mal die Lautstärke erhöht werden.

Um das zu verhindern, müssten die Zustandsübergänge priorisiert bzw. mit einer generellen Reihenfolge versehen werden. (Das ist z.B. in Matlab Stateflow® möglich, in der UML aber nicht vorgesehen).

Aber auch wenn es von einigen wenigen Werkzeugen unterstützt wird, kann die Zustandsmaschine schnell komplex werden, wenn immer darauf geachtet werden muss, dass es keine mehrdeutigen Zustandswechsel geben darf und diese dann mit Reihenfolgen versehen werden müssen. Aber es ergibt sich noch ein weiteres Problem. Evtl. möchte der Anwender erst die Helligkeit erhöhen und dann erst den Modus wechseln. In diesem Fall wäre die vorgegebene Reihenfolge falsch.

Würde man nun die Logik auf Basis eines zeitgetriebenen Systems mit Signalen konsequent zu Ende denken, dann würde sich ein Ablauf- oder Aktivitäts-Diagramm ergeben, wie in Abbildung Nr. 4 zu sehen.

Grundsätzlich ist es also ratsam, bei Laufzeit-Architekturen mit Zeitsteuerung auf Basis von Aktivitäts-Diagrammen zu modellieren und bei ereignisorientierten LaufzeitArchitekturen auf Basis von Zustandsmaschinen.

Immer wieder erlebe ich, wie in zeitorientierten Architekturen mit Zustandsmaschinen modelliert wird und diese dann komplex werden, weil implizit Abläufe modelliert werden, wozu Zustandsmaschinen nicht gut geeignet sind. Das Resümee ist dann leider häufig die pauschale Aussage, dass die UML nicht tauglich ist.

In Wirklichkeit wurde nur eine falsche ModellierungsMethode auf eine vordefinierte Laufzeit-Architektur angewandt.

Engpass Laufzeit-Architektur

Im Architektur-Design, und hier speziell in der LaufzeitArchitektur, stoße ich sehr häufig auf die Kombination von Methoden und Werkzeugen, die nicht miteinander harmonisieren.

Zum Beispiel auf den Einsatz von synchronen Kommunikationsmethoden in Kombination mit präemptivem Laufzeitverhalten. Um Zugriffe auf Variablen bzw. Single Ressourcen zu reglementieren wird dann mit Semaphoren (Verriegelungen) gearbeitet, die in bestimmten Situationen zu Deadlooks führen können. Um das zu verhindern ergeben sich dann Prioritätsinvertierungen. Die damit verbundenen Effekte erhöhen die Komplexität einer Applikation enorm und wären mit einer sauberen Architektur vermeidbar

Leider erlebe ich nur selten, dass eine Analyse der Architekturanforderungen in Verbindung mit der Auswahl von geeigneten Architekurpattern systematisch durchgeführt wird.

Daraus ergeben sich dann Komplexitäten. Nicht aus der eigentlichen Applikation heraus, sondern zusätzlich aus einer ungünstigen Kombination an Werkzeugen, Methoden, Notationen, ...

Engpass Wissen

Zum Glück gibt es inzwischen die Technische Informatik als Ausbildungsrichtung an den Hochschulen.

Als ich studiert habe, gab es diese Fachrichtung noch nicht. Meine Fachrichtung war Nachrichtentechnik. Die Programmierausbildung hat sich auf einige wenige Fortran Programme beschränkt, die auf Basis von Lochkarten erstellt wurden. Es waren verschiedene Sortieralgorithmen.

Strukturierte Programmierung, Architektur Design, ... das alles war in der Ausbildung nicht enthalten.

Vielleicht nicht ganz so extrem, aber doch ähnlich ist es den meisten, heute als Embedded-Programmierer arbeitenden, Ingenieuren ergangen. Sie haben einen hervorragenden Kenntnisstand, was die Applikation, aber sehr häufig einen autodidaktischen Kenntnisstand was Software Engineering anbelangt.

Die meisten von ihnen haben nicht einmal eine ANSI-C Schulung bekommen, geschweige denn Schulungen über Architekturdesign. Nun soll modelliert werden, mit AutoCode-Generierung, und die Wissenslücken werden gleich ,Auto-beseitigt‘.

,Domain Specific Languages‘ ist das Zauberwort. Damit kann auch ein Maschinenbau-Ingenieur ohne weitere Informatikkenntnisse Software modellieren. Schön wäre es. So werden dann Hammer benutzt, um Schrauben in die Wände zu schlagen.

Am Ende ist die Notation schuld oder das Tool oder der Vertrieber wenn‘s mit der ,Auto ...‘ nicht funktioniert.

Wir benötigen in unseren UML-Schulungen viel zusätzliche Zeit, weil sehr häufig die Grundlagen im Architekturdesign fehlen.

Aber die Zeit und die Möglichkeit sich Engineering Know How anzueignen bekommt fast kein Entwickler. Zum Glück gibt es auch Ausnahmen und Firmen, in denen Ausbildung auch nach dem Studium praktiziert wird.

Bei diesen Kunden erkenne ich, dass Modellierung, Anforderungsmanagement, Architekturdesign, ... funktioniert.

Mit geeigneten Methoden, Werkzeugen und dazu passenden Notationen, aber vor allem auch Kenntnissen in der professionellen Anwendung macht das Arbeitsleben eines Ingenieurs, der inzwischen als Modellierer arbeitet, wieder Spaß. Das zeigt sich immer häufiger!

Engpass dokumentenzentrisches Vorgehen

Apropos Spaß bei der Arbeit: ich kenne Kunden, deren Produkte für den Einsatz in sicherheitsrelevanten Bereichen zertifiziert werden müssen. Dafür ist die sogenannte Traceability der Anforderungen erforderlich.

Diese werden in Word geschrieben und bekommen Nummern. Testfälle z.B. werden auch in Word spezifiziert und die Ergebnisse der Durchführung dokumentiert.

Auch die Implementation wird in Word dokumentiert. Alles bekommt Nummern und in Excel wird eine Krossreferenzliste gepflegt.

Das Pflegen dieser Excel Liste gehört zu den kreativsten Aufgaben der Ingenieure. Das ist dokumentenzentrisches Vorgehen.

Stand der Technik ist repositoryzentrisches Vorgehen. Dort werden all diese Dinge mit Werkzeugen, die im Hintergrund auf Datenbanken zurückgreifen, durchgeführt. Eine einmalige Verbindung von Elementen ist ausreichend, und verschiedenste Traceability Views können automatisch erzeugt werden.

Kein Pflegen von Excel Tabellen. Die Kreativität der Ingenieure kann auf andere Bereiche der Entwicklung konzentriert werden.

Näheres zu diesem Thema finden Sie in der vorherigen Ausgabe der Newsletter No. 24 auf unser Homepage.

Resümee

Gerade im Software Engineering werden nicht immer am Stand der Technik ausgerichtete Methoden, Notationen und Werkzeuge eingesetzt. Wahrscheinlich liegt es daran, dass das technische Software Engineering noch eine recht junge Disziplin ist und nicht so sehr lange an den Universitäten vermittelt wird.

Eine große Anzahl der heutigen Ingenieure, die technische Software entwickeln, haben als Ausbildung ,Maschinenbau‘ oder ,Elektrotechnik‘ genossen.

Lesenswertes zur Vertiefung

Das Ziel Höchstleistung in der Fertigung, Eliyahu M. Goldratt / Jeff Cox

SW Engineering Newletter Nr.21
Jonglieren mit der Zeit, Andreas Willert

SW Engineering Newletter Nr.24
Richtiges richtig tun Teil 1, Andreas Willert

Software Engineering war dort nur rudimentär enthalten. Das sollte aber kein Grund sein, heute nicht Engineering Methoden, orientiert am Stand der Technik, einzusetzen.

Zum Glück sehe ich, wie die Ausbildung an unseren Hochschulen inzwischen diese Bereiche abdeckt. Anderes fällt dabei zunehmend unter den Tisch, z.B. Basiskenntnisse in der hardwarenahen Programmierung von Embedded Microcontrollern. Wer kann heute noch das in Assembler geschriebene cstartup.asm des Compilers verstehen? Manchmal ist es aber notwendig.

Beide Welten und Generationen miteinander zu verbinden, darin wird die Herausforderung der Zukunft liegen.

Wenn ein ,Greenhorn‘ von der Hochschule keine besonderen Kenntnisse in der hardwarenahen Programmierung von Microcontrollern auf Basis von ANSIC beherrscht, bedeutet das noch lange nicht, dass seine UML-Kenntnisse unnütz sind.

Umgekehrt sollten ,alte Hasen‘ ernst genommen werden bezüglich ihrer Bedenken, die Anforderungen umzusetzen.

Nur zu oft sind nicht die neuen Techniken Ursache, warum deren Einsatz scheitert, sondern mangelnde Kenntnisse, die alten Anforderungen auf Basis der neuen Techniken umzusetzen und unsinnige Kombinationen von Methoden, Notationen, Prozessen und Werkzeugen.

Aber vergessen wir nicht unser wichtigstes Werkzeug, unser Gehirn. Wie z.B. sieht es mit der Effiziens aus, wenn die Arbeitsbedingungen nicht gehirngerecht gestaltet sind? Zu diesem äußerst interessanten und wichtigen Thema mehr in der nächsten Ausgabe.

Ich wünsche Ihnen viel Erfolg in Ihren Projekten und immer das passende Werkzeug zur passenden Methode.

Autor:

Andreas Willert
Haben Sie noch Fragen oder Anregungen zum Thema? Dann freue ich mich über eine E-Mail: awillert@willert.de

Herausgeber:

WILLERT SOFTWARE TOOLS GMBH
Hannoversche Straße 21
31675 Bückeburg
E-Mail: info@willert.de
Tel.: +49 5722 9678 - 60

Alle ESE-Reports im Überblick

Aktuelles Know-how und neueste Entwicklungen und Trends rund um das Thema Emedded Software Engineering

> zu den ESE-Reports

Hinweis: Unsere Webseite nutzt Cookies. Wenn Sie fortfahren, nehmen wir an, dass wir Ihre Erlaubnis haben Cookies zu setzen. Informationen zum Einsatz von Cookies sowie unsere Datenschutzbestimmungen finden Sie in unserer Datenschutzerklärung und über unser Impressum.