© Excellent backgrounds/Shutterstock.com
Teil 1: Flow Design: ein neuer Ansatz für Softwaredesign

Lasst es fließen


Die wenigsten von uns beschäftigen sich mit Computer Science und meistern ­algorithmische Herausforderungen. Die meisten machen Softwareengineering und verwalten Code und einfache Funktionalitäten, verpackt in GUIs oder Bibliotheken. Software wandelbar zu halten, ist unsere eigentliche Herausforderung.

Immer wieder stellt sich die Frage: Warum ist Softwareengineering so anders als sonstige Ingenieurdisziplinen, die sich mit Gegenständen der realen Welt befassen? Warum ist das Design eines Softwaresystems im Code meist nicht wiederzuerkennen? Warum macht es so viel kognitive Arbeit, sich in unbekannte SW-Systeme oder nach einer Weile auch wieder in die eigenen einzuarbeiten?

Unsere Ingenieurdisziplin ist im Vergleich zum Maschinenbau oder zur Elektrotechnik noch nicht sonderlich alt. Ich bin überzeugt, dass unsere Zunft aus der Art und Weise, wie andere Ingenieurdisziplinen ihre Systeme konzipieren, viel lernen und ihnen in ihrem Systemdesign wesentlich näher kommen kann, als das heute noch der Fall ist. Es ist natürlich ein wenig Umdenken erforderlich. Diese Artikelserie ist ein Versuch, einen neuen Weg vorzuschlagen, ohne gleich die bereits gemachten Erfahrungen mit objektorientiertem und funktionalem Design über Bord zu werfen.

kuniss_flowdesign_1.tif_fmt1.jpgAbb. 1: Blockschaltdiagramm eines Apple-I-Videoterminals (San Bergmans CC ­BY-SA 4.0)

Abbildung 1 zeigt abstrakt, wie die Komponenten des Apple-I-Videoterminals miteinander in Beziehung stehen und interagieren. So fließen z. B. Daten vom Zeilenschieberegister C3 in die Zeichen-ROM-Komponente D2. Alles ist klar: D2 hängt in diesem Design von C3 ab. Wenn wir dieses Systemdesign mit einem objektorientierten Ansatz in Code realisieren würden, wie würde das aussehen? Ich denke, als Erstes würden wir die Komponente D2 als Klasse implementieren, die die Möglichkeit bietet, ein Zeichen zur Darstellung auszuwählen:

class D2 { void select(char c) }

Es wäre naheliegend, die Komponente C3 ebenso als Klasse zu realisieren, die D2 aufruft, denn C3 hängt ja von D2 ab:

class C3 { void shiftTo(char c) { D2.select(c) } }

Aber wo ist der Unterschied zu einer Realisierung in echter Hardware und damit der Unterschied zwischen einer elektronischen und einer softwaretechnischen Realisierung? In beiden Fällen hängt C3 von D2 ab. Aber nur in der softwaretechnischen Realisierung muss C3 die Komponente D2 kennen, um ihre Abhängigkeiten zu bedienen. Ohne diese Kenntnis kann sie nicht implementiert werden. Dagegen werden in der elektronischen Umsetzung alle Komponenten unabhängig voneinander entwickelt und realisiert. Nur durch die Integration, hier das Videoboard, wird ein Kontext definiert und werden die Abhängigkeiten festgeschrieben. In anderen elektronischen Boarddesigns könnte der C3-Baustein mit ganz anderen elektronischen Komponenten verbunden sein, ohne dass D2 in irgendeiner Weise beteiligt ist. Die Komponenten C3 und D2 sind generell voneinander unabhängig. In der softwaretechnischen Implementierung dagegen kann die Klasse C3 niemals ohne D2 verwendet werden.

Man könnte einwenden, dass die Definition eines Interface unter Zuhilfenahme von Dependency Injection das Problem lösen könnte. Man könnte also folgende Schnittstelle definieren und die Klassen C3 darauf basierend neu implementieren:

interface ID2 { void select(char c) } class C3 { @Inject ID2 d2; void shiftTo(char c) { d2.select(c) } }

Ich denke nicht, dass dies das Problem löst. Denn das Problem mit Methoden und Funktionen ist, dass an sie Ausführungssemantik gebunden sind, sonst würden wir uns nicht so darum bemühen, ihnen gute, sprechende Namen zu geben.

Ziehen wir wieder einen Vergleich mit den elektronischen Bausteinen. Hier sind auch Schnittstellen involviert. Der elektronische Baustein C3 hat sicher ein Datenblatt, das die Bedingungen seiner Benutzung und die seiner Pins beschreibt. Das ist nichts anderes als eine Schnittstellenbeschreibung in einer Programmierung. Aber D2 würde in dieser Schnittstellenbeschreibung niemals auftauchen, denn möglicherweise wurde C3 sogar entwickelt, bevor es D2 überhaupt gab. Undenkbar in der objektorientierten Softwarewelt. Hier kann C3 nur in Kenntnis der Schnittstelle ID2 implementiert werden. Die Realisierung des Input-Pins shiftTo kann nur in Kenntnis und mit Existenz der Schnittstelle ID2 erfolgen.

Das eigentliche Problem hier ist, dass die Methode select eine Bedeutung hat, die sich in ihrem Namen manifestiert, ob sie nun in der Schnittstelle ID2 oder in der Klasse D2 definiert ist. ...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang