Komplexität im Software Engineering, Teil 1
Wenn ich in meinen Vorträgen auf Kongressen in die Runde der Zuhörer die Frage stelle, wer NICHT vom Wachstum der Komplexität betroffen ist, bekomme ich lediglich vereinzelt ein oder zwei Meldungen. Wir können davon ausgehen, die Komplexität in unserer Gesellschaft wächst, und das sogar mit zunehmender Geschwindigkeit.
Anbieter zum Thema

Was ist eigentlich Komplexität? Folgende Aussage findet man unter Anderem auf Wikipedia:
Der Ökonom Peter Ulrich bezeichnet die Komplexität einer Situation mit der Vielfalt der einwirkenden Faktoren und dem Ausmaß ihrer gegenseitigen Interdependenzen und charakterisiert diese als Merkmal schlecht strukturierbarer Entscheidungssituationen. Komplexität ist eine mögliche Form eines Gegenteils von Einfachheit, Determinierbarkeit und der Überschaubarkeit.
Wie konkret zeigt sich Komplexität im Software- und Systems-Engineering, und welche Hilfestellungen (Techniken) haben wir, um ihr zu begegnen? Darum geht es im folgenden.
Wie wirkt sich Komplexität in unserem Umfeld aus?
Es ist unglaublich, als was ich mein iPhone in Kombination mit verschiedensten Apps alles nutzen kann. Angefangen von einer Wasserwaage bis hin zu einem komplexen Audio Signal Analyser, der auf Basis einer FFT die genauen Frequenzanteile analysiert. Der Kreativität scheint keine Grenzen gesetzt zu sein.
Aber wenn ich eine Telefonnummer anrufen möchte, die ich z.B. in einer Mail zugeschickt bekommen habe und die wie folgt aufgeschrieben wurde: +49 (0) 5722 9678 60, treibt mich das iPhone dicht an den Wahnsinn. Das iPhone erkennt sofort, dass es sich um eine Telefonnummer handelt, wählt aber die (0) mit und lässt mir in der Telefon-App keine Möglichkeit die Nummer zu editieren. Der Workaround Kopieren der Nummer in eine andere App und dortiges Editieren, hört sich simpel an, ist aber in Kombination der Touchscreen-Bedienung und der Motorik meiner Finger immer wieder eine echte Herausforderung und Geduldsprobe für mich.
Wie kann es angehen, dass ein Produkt, was im ureigensten Sinn ja immer noch ein Telefon sein sollte, inzwischen Millionen von erweiterten Diensten bereitstellt, aber das Telefonieren in manchen Situationen komplizierter macht, als je zuvor? Es liegt nicht an der technischen Machbarkeit, es ist die Komplexität, die immer häufiger dazu führt, dass Systeme verschlimmbessert werden.
Immer häufiger kommen Systeme in Situationen, in der die Kombination von Zusammenhängen und deren Auswirkungen bei der Entwicklung nicht mehr überblickt werden. Die Systeme reagieren dann undefiniert bis fehlerhaft. Müssen wir zukünftig damit leben, dass wir unsere Mobile Devices zwar für nahezu alles Erdenkliche nutzen können, diese aber nur noch gelegentlich funktionieren?
Ich denke nein. Es gibt bereits betriebsbewährte Techniken, auf deren Basis wir der wachsenden Komplexität begegnen können. Bevor wir uns diesen widmen, möchte ich die Komplexität noch einmal etwas durchleuchten.
Wie zeigt sich uns Komplexität im Engineering?
Wird ein System kompliziert, dann ist einer der meist eingesetzten Instrumente, um das Verstehen weiterhin zu gewährleisten, die Zerteilung (Teile und Herrsche). Dieses Instrument wird bis heute erfolgreich eingesetzt, auch bei komplexen Systemen, dort jedoch mit zunehmend weniger Erfolg. Warum ist das so? Das werden wir uns nun etwas genauer ansehen.
Teile und Herrsche wird so lange durchgeführt, bis die einzelnen Teilsysteme in ihrer Kompliziertheit beherrschbar erscheinen. Was langläufig unberücksichtigt bleibt, ist die Tatsache, dass dem Teilen (Dekomposition) das Zusammenfügen (Aggregation) folgen muss. Alle Teilsysteme müssen am Ende wieder harmonisch zusammen funktionieren und die Funktion des Gesamtsystems abbilden. Hier beginnt heute die Problematik.
Um das zu verstehen, lassen Sie uns einen Blick auf die Abbildung 1 (siehe Bildergalerie) werfen. Hier ist der Teilungsprozess dargestellt. Behalten wir im Kopf, dass nur auf Basis der Aggregation das Gesamtsystem funktionieren kann, dann bilden sich Schnittstellen (Interfaces). Die Anzahl der potentiellen Interfaces wächst polynom mit der Anzahl der Elemente. Wir verschieben die Kompliziertheit von der Elemente-Ebene auf die Interface-Ebene.
Wir könnten das Spiel Teile und Herrsche immer weiter fortführen, dann würde irgendwann die Kompliziertheit in den Elementen infinitesimal klein sein. Sie wäre dann vollständig auf die Interface-Ebene verschoben. Diese übertriebene Situation würde uns nicht weiterhelfen. Irgendwo dazwischen kann unser Gehirn am besten mit der Kompliziertheit umgehen.
Nun stellt dieses Beziehungsgeflecht nur eine Ebene dar. In realen Software-Projekten haben wir jedoch mehrere Ebenen und hier beginnt das System komplex zu werden. Der Grad der Vernetzung über mehrere Ebenen macht es nahezu unmöglich die dynamische Ausprägung einer Änderung in einer statischen eindimensionalen Betrachtung vorhersagbar zu machen.
In der Praxis: Die Änderung einer Zeile C-Code mag in Bezug auf die Logik des Basis-Betriebsmodus überschaubar sein. Aber da gibt es noch den Modus für Service und Diagnose. Der wird noch einmal überlagert von Versionen (Im Feld laufen Systeme mit neuen und alten Komponenten und der Service-Stecker ist dort jeweils anders ausgeprägt) und dann kommt noch die Luxusvariante dazu ... Verstehen Sie was ich meine? Die Codeänderung muss in jeder Hinsicht kongruent sein. Das zu gewährleisten ist heute die Problematik.
In der Praxis haben heutige Systeme auf etwa 7-12 Ebenen Beziehungen. In Abbildung 4 (siehe Bildergalerie) sind exemplarisch einige Ebenen aufgeführt, auf denen sich im Software-Engineering Beziehungen potentiell ausprägen.
(ID:43693627)