Der Erfolg eines Softwareprojekts steht und fällt mit der Architektur eines Systems. Nicht immer führen anfängliche schnelle Erfolge zu einer stabilen Software. Mit welchen Herausforderungen sich ein Softwarearchitekt initial und im Laufe des Projekts konfrontiert sieht, lässt sich am Beispiel des fiktiven Bob nachvollziehen.

Nach seiner Umschulung zum Softwareentwickler steht Bob, der Baumeister, vor der ersten großen Herausforderung. Zusammen mit anderen Leidensgenossen soll er die Softwarearchitektur für einen Webshop erstellen. Was er zunächst für ein lächerlich einfaches Projekt hielt, erweist sich auf dem zweiten Blick als ganz und gar nicht trivial. Vor ihm steht bedrohlich ein weißes, bislang gähnend leeres Flip-Chart. Es scheint sehnsüchtig darauf zu warten, dass Bob es mit architektonischen Entwürfen füllt.

Bob sieht sich mit diversen Herausforderungen konfrontiert. Er muss überlegen, welches der erste Schritt im Architekturentwurf ist, und wie er anschließend systematisch das Softwaresystem erstellt. Außerdem muss er sich klarmachen, welche Informationen und Voraussetzungen zu gewährleisten sind. Dieser Artikel konzentriert sich ganz auf diese architektonische Brille. Details wie der Entwicklungsprozess oder die Rolle des Architekten sind nicht Gegenstand der Betrachtungen.

Abbildung 1: Ein systematischer Prozess für den Architekturentwurf ist inkrementell und ermittelt zu Beginn alle architektonisch relevanten Anforderungen.
Abbildung 1: Ein systematischer Prozess für den Architekturentwurf ist inkrementell und ermittelt zu Beginn alle architektonisch relevanten Anforderungen.

Offensichtlich benötigt der Softwarearchitekt Bob am Anfang eine Liste von hinreichend detaillierten Anforderungen, allesamt mit eindeutigen Prioritäten versehen. Wie vollständig eine solche Liste sein muss, daran scheiden sich bisweilen die Geister. Dass schon zu Beginn alle Anforderungen vorliegen, entspricht zwar dem Ideal, dürfte aber bei komplexeren Projekten dem Finden des heiligen Grals gleichkommen. Übrigens mit ein Grund dafür, warum Wasserfallmodelle sich oft als Sackgasse erwiesen haben. Einer „Mission Impossible“ gleicht das andere Extrem, das mit keinen oder wenigen Anforderungen auskommen will. Es führt letztendlich zu übergenerischen Softwarearchitekturen, die es keinem recht machen können, weil sie es allen recht machen wollen. Die Wahrheit liegt also irgendwo in der Mitte.

Conditio sine qua non

Je mehr architektonisch signifikante Anforderungen bekannt sind, desto stabiler das architektonische Fundament. Damit sich der Architekt in Konfliktsituationen für das richtige Vorgehen entscheiden kann – ähnlich der Rechts-vorlinks-Regel im Straßenverkehr – sollten diese Anforderungen eindeutige Prioritäten besitzen. Meistens stammen die Anforderungen nicht von den Softwareentwicklern, sondern von Anforderungsingenieuren, Produktmanagern oder Kunden. Daher kommt der Kommunikation mit dem genannten Personenkreis essenzielle Bedeutung zu, was bedeutet, dass sich der Alltag des Softwarearchitekten nicht auf technische Aspekte beschränkt. Nicht immer sind die Anforderungen verständlich, detailliert und widerspruchsfrei formuliert oder haben eindeutige Prioritäten. Hier heißt es oft, intensiv nachzubohren und bisweilen Überzeugungsarbeit zu leisten.

Damit Softwarearchitekten in einem konkreten Projekt die Ziele ihrer Organisation oder ihrer Kunden unterstützen können, benötigen sie grundlegendes Wissen über geschäftliche Aspekte. Je nach Kontext kann es zum Beispiel in einem Fall sinnvoll sein, wichtige Teile des Systems mithilfe von Offshoring-Maßnahmen zu entwickeln und die Architektur entsprechend zu planen, während sich dieses Vorgehen in einem anderen Fall vollkommen verbietet. Zudem lässt sich manche geschäftliche Zielvorgabe überhaupt nicht umsetzen, zumindest nicht mit vernünftigem Aufwand. Basiswissen über grundlegende Instrumente und nichttechnische Softwarearchitekturaspekte erweist sich daher in diesem Zusammenhang als unbedingt erforderlich.

Zu guter Letzt müssen Softwarearchitekten sowohl die fachliche Problemdomäne als auch die technischen Lösungsdomänen verstehen. Fehlt ihnen die geistige Durchdringung der Fachdomäne, bleibt die Problemstellung im Dunkeln. Haben sie nur unzureichende Kenntnisse der Lösungsdomänen, können sie keine technisch fundierten Ergebnisse erzielen. Wie sagte Bertrand Meyer einst so schön: „Bubbles don’t crash.“

Softwarearchitektur – was ist das?

Bob denkt an seine Umschulung zurück. Für den Begriff „Softwarearchitektur“ gibt es mindestens ebenso viele Definitionen, wie die Menschheit Gottesbeweise hervorgebracht hat. Zum Glück besitzen die diversen Definitionen mehr Gemeinsamkeiten als Unterschiede. Softwarearchitektur beschreibt demnach die Komposition eines Softwaresystems aus Subsystemen, deren Beziehungen zueinander sowie die Grundprinzipien, mit deren Hilfe die Architekten die Anwendung erstellen.

Hinzuzufügen ist an dieser Stelle, dass der Blick auf eine Softwarearchitektur immer aus verschiedenen Perspektiven (Viewpoints) erfolgen muss. Demzufolge geben die verbreiteten Diagramme, die lediglich eine Menge von Rechtecken über eine Menge von Linien verbinden, nicht wirklich die Softwarearchitektur wieder. Es bedarf stattdessen weiterer Beschreibungen des Systems, etwa der Interaktionen zwischen den Komponenten oder der Systemzustände. Und da bloße Syntax nichts anderes repräsentiert als Kreidehaufen, gehört zur Softwarearchitektur neben dem „Was“ immer auch das „Warum“, also das Rationale für alle architektonischen Entscheidungen. Mit einer Sammlung von UML Diagrammen ist es demnach nicht getan.

Aber was hat es mit den ominösen Grundprinzipen auf sich, die sich in der obigen Definition verstecken, fragt sich Bob. Dass viele Köche den Brei verderben, gilt nicht zuletzt auch für die Softwareentwicklung. Wenn ein Entwickler zur Fehlerbehandlung Ausnahmen wirft, während ein anderer Fehlerwerte zurückgibt und ein dritter Informationen in ein Logbuch schreibt, befinden sich unvermittelt drei Varianten der Fehlerbehandlung im System. Treten zudem im selben Architekturentwurf verschiedene Softwaremuster zur Lösung ähnlicher Problemstellungen auf, leidet die daraus resultierende Softwarearchitektur an Qualitätsmängeln, beispielsweise an schlechter Verständlichkeit und geringer Symmetrie. Daher sollten Bob und seine Koarchitekten schon zu Beginn des Projekts dafür sorgen, dass sie einheitliche Entwurfskonventionen und -regeln einführen. Mit der Erstellung von Dokumenten ist es allerdings nicht getan. Vielmehr müssen sie die Einhaltung aller Vorgaben und Konventionen auch regelmäßig kontrollieren.

Prioritäten des Zwiebelmodells

Das Prinzip der systematischen Architekturerstellung lässt sich am besten anhand einer Zwiebel illustrieren, was nicht nur daran liegt, dass die architektonischen Anstrengungen Bob bisweilen Tränen in die Augen treiben. Zu Beginn des Entwurfs und damit im Kern des Zwiebelmodells steht das fachliche Objektmodell. Bob überlegt, aus welchen fachlichen Entitäten sich ein Webshop zusammensetzt. Da wären zum Beispiel der Produktkatalog, der Warenkorb, das Zahlungssubsystem, die Kundendatenbank, das Logistik- und das Bestellsystem. Natürlich fristen diese Objekte kein Inseldasein, sondern haben Beziehungen zueinander. Ein Warenkorb muss mit dem Produktkatalog interagieren, ebenso mit dem Bezahlsystem.

Abbildung 2: Das Zwiebelmodell veranschaulicht die richtige Reihenfolge beim Entwurf: Zuerst die fachlichen Aspekte, dann die nichtfachlichen, jeweils mit absteigender Tendenz.

Fragt sich, wie Bob diese Beziehungen eruieren kann. Im Idealfall existiert für die Problemstellung bereits eine allgemein bewährte Referenzarchitektur für Webshops, derer er sich bedienen kann. Leider gibt es solche Vorlagen nur für wenige Anwendungsdomänen. Daher greift der Softwarearchitekt im Normalfall zu Anwendungsszenarien – zu Neudeutsch Use Cases –, um die Erwartungen an das Zielsystem aus der Vogelperspektive zu beschreiben, sowie zu einem Kontextdiagramm, um zu definieren, welche Entitäten sich im System und welche sich außerhalb befinden.

Für den Webshop ermittelt Bob dabei eine Reihe von Anwendungsfällen, etwa „Im Produktkatalog suchen“, „Produkt zu Warenkorb hinzufügen“ oder „Warenkorb bestellen“. Da der Kunde das existierende SAP-Warenwirtschaftssystem zur Verwaltung von Bestellungen verwenden möchte, befindet sich die SAP-Schnittstelle im Kontextdiagramm außerhalb des Webshops, ebenso wie das Logistiksystem oder die notwendigen Schnittstellen zu Banken und Kreditkartenfirmen. Aus den Anwendungsfällen und dem Domänenwissen ergibt sich nun inkrementell ein grobgranulares fachliches Objektmodell.

Für den Übergang der von Use Cases propagierten Black-Box- zu einer WhiteBox-Sicht mit detaillierten Abläufen existiert leider kein Automatismus. Dass es für Bobs Webshop einen Anwendungsfall „Warenkorb bestellen“ gibt, ist eine Sache. Wie die internen Komponenten zur Realisierung dieses Anwendungsfalles zusammen spielen müssen, eine ganz andere. Die Softwarearchitekten stützen sich auf ihre Domänenkenntnisse, um aus Use Cases etwa Sequenzdiagramme abzuleiten.

Abbildung 3: Use Cases repräsentieren als Black-Box-Sicht alle Erwartungen an das System seitens der Benutzer. Ein Kontextdiagramm klärt, was innerhalb und außerhalb des Systems sein soll.

Muster erleichtern das Leben

Für die generelle Strukturierung der Gesamtarchitektur bieten sich die sogenannten architektonischen Muster an, zu denen beispielsweise Layers, MVC (Model-View-Controller) oder Pipes-and-Filters gehören. Dass sich eine webbasierte Geschäftsanwendung wie Bobs Webshop gut mittels eines Mehrschichtenmodells entwerfen lässt, dürfte inzwischen zum Allgemeinwissen gehören. Ebenso, dass Techniken wie Ruby on Rails, JSF, Struts oder ASP.Net ein Anwenden des MVC-Musters forcieren. Überhaupt empfiehlt sich das Nutzen von Softwaremustern für alle Granularitätsebenen des Designs, wollen Entwickler nicht ständig das Rad neu erfinden. Was wieder auf die Grundprinzipien der Architekturerstellung zurückführt. Bobs Bibliothek enthält daher die entsprechende Standardliteratur in Griffweite.

Erfahrungsgemäß scheitern viele Softwareentwicklungsprojekte weniger an den funktionalen Aspekten. Der Knackpunkt besteht stattdessen oft in der Umsetzung nichtfunktionaler Qualitäten. Die übliche Wunschliste operationaler Eigenschaften wie 99,999 % Verfügbarkeit oder Skalierbarkeit bis 100ˇ000 Kunden lässt sich ebenso wenig en passant realisieren wie entwicklungstechnische Eigenschaften à la leichte Änderbarkeit oder Administrierbarkeit. Gerade die operationalen Eigenschaften eines Softwaresystems beeinflussen dessen Architektur als Ganzes, während entwicklungstechnische Eigenschaften oft nur lokalen Einfluss auf eines oder wenige Subsysteme haben. Trotzdem stürzen sich viele Softwarearchitekten oft zuerst auf Letztere. Ein Strategy-Muster hier und da und vielleicht noch ganz woanders zur vermeintlich besseren Änderbarkeit – schon krankt die gesamte Softwarearchitektur am Strategy-Syndrom und mutiert zu einem schwer beherrschbaren, übergenerischen Softwaresystem.

Drei Ebenen sind genug

Ein systematisches Vorgehen sieht anders aus. Grundsätzlich lassen sich drei Ebenen beziehungsweise Phasen in der besagten Zwiebel unterscheiden, sobald Bob das fachliche Objektmodell seines Webshops mit nichtfachlichen Aspekten schmücken will.

Phase I – Verteilung und Parallelität: Zu Beginn sind die meisten Softwaresysteme heutzutage als nebenläufige und verteilte Systeme konzipiert. Ein Webshop läuft in der Regel auf einem vom Kunden separierten Server und benutzt Parallelitätskonzepte, um Skalierbarkeits- und Performanceanforderungen zu erfüllen. Dies impliziert, dass der vorliegende funktionale Kern in eine verteilte, nebenläufige Infrastruktur einzubetten ist. Für die Trennung der Präsentationsschicht von den Geschäftskomponenten sowie deren Separation von EIS-Systemen (Enterprise Information Systems) wie Datenbanken oder ERP-Anwendungen bieten sich broker- und komponentenbasierte Softwarearchitekturen an. Und auch hier finden sich wieder die Softwaremuster für verteilte und nebenläufige Systeme. Genau genommen entwirft der Softwarearchitekt eine passende Infrastruktur für Verteilung und Parallelität, in die er anschließend das bereits vorhandene fachliche Objektmodell integriert. Das resultierende Architekturmodell dient dann als Basis für die weiteren Phasen.

Phase II – strategisches Design: Nun erfolgt der strategische Entwurf. Für alle operationalen Eigenschaften erstellen Bob und seine Freunde ebenfalls passende Infrastrukturen. Dabei orientieren sie sich hinsichtlich der Reihenfolge an den vorgegebenen Prioritäten. Würde also Sicherheit die wichtigste operationale Eigenschaft darstellen, müssten sie zunächst gemäß der vorliegenden Anforderungsbeschreibung eine Sicherheitsinfrastruktur konstruieren, die Subsysteme beziehungsweise Komponenten wie Firewalls, Sicherheitsprotokolle oder Authentisierungsserver beinhaltet. Diese Infrastruktur integrieren sie in die bisherige Architektur. Danach folgen die weiteren operationalen Anforderungen mit absteigender Priorität. Je weiter innen im Zwiebelmodell eine solche Eigenschaft liegt, desto mehr Einfluss hat sie naturgemäß auf die gesamte Softwarearchitektur. Ein Webshop, der in erster Linie sicher und nur in zweiter Linie verfügbar sein soll, besitzt folgerichtig eine andere Softwarearchitektur als einer, der primär mit Verfügbarkeit und sekundär mit Sicherheit glänzen will. Mindestens für die wichtigsten operationalen Eigenschaften sollten Entwicklungsprojekte eigene Experten oder sogar ganze Teams spendieren, die sich hauptsächlich um genau diese nichtfachlichen Aspekte kümmern. Grundsätzlich ließen sich natürlich auch Verteilung und Nebenläufigkeit als operationale Eigenschaften charakterisieren. Da diese Aspekte aber normalerweise über andere operationale Eigenschaften dominieren, ist es sinnvoll, zwischen den beschriebenen Phasen I und II zu unterscheiden.

Phase III – taktisches Design: Es lässt sich trefflich darüber streiten, wo architektonisches Design endet und Softwaredesign beginnt. Oft betrachten Experten Architektur- und Softwaredesign als Synonyme. Im taktischen Entwurf konzentrieren sich Architekten auf die entwicklungstechnischen Eigenschaften. Dazu zählen unter anderem Wartbarkeit, Erweiterbarkeit, Änderbarkeit und Testbarkeit. Es handelt sich also um Anforderungen, die weniger das Laufzeitverhalten der Anwendung als viel mehr deren Entwicklung oder Evolution betreffen. Nicht immer leuchtet den Projektbeteiligten allerdings ein, warum so wichtige Eigenschaften wie Änderbarkeit erst am Schluss einfließen. Gerade derlei Qualitäten sollten sich aber in einem stabilen Fundament begründen statt im Chaos. Bei Flexibilitätsanforderungen bietet sich die Commonality/Variability-Analyse als adäquates Instrument an. Diese stellt fest, welche Bestandteile der Anwendung invariant und welche variabel sein sollen. Erstere beeinflussen die Softwarearchitektur bereits in früheren Entwurfsphasen, während Letztere im taktischen Design zum Tragen kommen. Zwei Beispiele mögen das illustrieren:

Bob hat bereits im funktionalen Entwurf berücksichtigt, dass jeder Webshop über ein Bezahlsystem verfügen muss. Andererseits soll der Webshop für verschiedene Kunden zum Einsatz kommen, deren Wünsche bezüglich der Zahlungsoptionen variieren können. Während einige Online-Shops Zahlung per Rechnung offerieren, beschränken sich andere auf Einzugsermächtigung oder Vorkasse. Die Art der Zahlung stellt somit eine Variabilität dar, während die Notwendigkeit des Bestellsystems selbst eine Invariante repräsentiert.

Skalierbarkeit ihrer Webshops wünschen natürlich alle Kunden. Deren potenzielles Ausmaß ist allerdings direkt proportional zu ihren finanziellen Möglichkeiten. So könnte Bob neben Web- auch Applikationsserver und Datenbanken replizieren und über Komponenten für Lastverteilung ansteuern. Oder er beschränkt sich auf die kostengünstigere Variante, die lediglich eine Replikation der Webserver vorsieht und alle Softwareserveranwendungen parallel vorhält. Letztere Variante sieht Bob deshalb für alle Kundenszenarien vor, betrachtet das Replizieren von Applikationsservern und Datenbankservern aber als optional.

Die Reihenfolge beim Einbringen taktischer Eigenschaften bestimmt Bob erneut anhand eindeutiger Prioritäten. Am Ende seiner Bemühungen steht er vor der vollendeten Zwiebel beziehungsweise vor einer stabilen Basisarchitektur, die als Fundament für die nachfolgenden Verfeinerungsschritte dient. Auf die Implementierungsphase selbst kann dieser Artikel nicht weiter eingehen.

Der Teufel steckt im Detail

Irgendwann während seiner architektonischen Schwerstarbeit stellt sich Bob die philosophische Frage, wie detailliert die Basisarchitektur für den Webshop überhaupt sein muss. Wie weit sollte der Softwarearchitekt also gehen und wann beginnt die eigentliche Implementierungsphase? In einigen Projekten soll die Entwurfsphase angeblich schon unüberschaubare Ausmaße angenommen haben und so mancher Kunde vor Beendigung des Projektes dahingeschieden sein. Eine wissenschaftlich fundierte Antwort gibt es hierfür leider nicht, wohl aber eine Daumenregel. Und weil Bilder oft mehr sagen als tausend Worte, möge das Pyramidenmodell (Abbildung 4) der Veranschaulichung dienen. Die Architektur eines Softwaresystems umfasst demnach maximal drei Ebenen: das System als Ganzes, die grundlegenden Subsysteme und ihre Beziehungen sowie die Komponenten, aus denen sich wiederum die Subsysteme konstituieren.

Abbildung 4: Um sich nicht in Details zu verlieren, schlägt das Pyramidenmodell einen dreistufigen Ansatz vor.

Die Abbildung der mehrdeutigen Begriffe Subsysteme oder Komponenten auf reale Entitäten hängt vom Problemkontext ab. In einem serviceorientierten Umfeld könnten die Subsysteme zum Beispiel Dienste darstellen, die sich ihrerseits aus Komponenten zusammensetzen. Für Kleinstsysteme könnten Subsysteme zu Komponenten und Komponenten zu Klassen mutieren.

Bekanntlich beginnen die wenigsten Softwareprojekte auf der grünen Wiese. Da wünschen Auftraggeber die Nutzung eines speziellen Datenbanksystems für ihren Webshop oder fordern die optimale Nutzung eines bestimmten Betriebssystems. Ein Extrem stellen in diesem Zusammenhang eingebettete und Echtzeitsysteme dar, weil sie stringente Vorgaben hinsichtlich Laufzeitverhalten und Ressourcennutzung implizieren. Hier stellt sich die Frage, ob solche Aspekte überhaupt ins bisherige Bild passen oder derartige Systeme einen gänzlich anderen Prozess benötigen. Zum Glück lassen sich die beschriebenen Prinzipien auch auf diese Problemkontexte anwenden, sofern die Softwarearchitekten die genannten stringenten Vorgaben als Anforderungen höchster Priorität betrachten. Im Zwiebelmodell müsste Bob also von Anfang an Vorgaben wie die Begrenzung auf 512 KByte Hauptspeicher berücksichtigen.

Fazit

Bob ist überglücklich, nachdem er sein erstes Projekt erfolgreich zu Ende geführt hat. Er hat gelernt, dass erfolgreiche Softwarearchitekturen sich nur in einem systematischen und inkrementellen Prozess realisieren lassen, wie dies auch bei allen anderen Ingenieursdisziplinen der Fall ist. Ad-hoc getriebene Ansätze hingegen erwecken zwar mitunter anfangs die Illusion eines rasanten Fortschritts, scheitern dann aber an der Komplexität der Problemstellung, die den Beteiligten schon bald hoffnungslos über den Kopf wächst.

Natürlich muss das Verhältnis von Planung und Umsetzung in einem vernünftigen Verhältnis stehen. Man kann sich auch zu Tode planen, wie einige Großprojekte aus jüngster Zeit beweisen. Der Architekt sollte über ein ausreichendes Fundament an Erfahrung und Wissen verfügen, das sich von der Domänenexpertise über Technik- und Methodenkenntnisse bis zu sozialen Fähigkeiten erstreckt.

Und zu guter Letzt sollten Softwarearchitekten nicht nach Innovation, sondern nach Lösungen streben. Der erste Trägheitssatz der Softwarearchitektur postuliert nicht umsonst die ausgiebige Nutzung von Softwaremustern und anderen bewährten Praktiken, um die Produktivität und Effektivität zu steigern. Und ganz nebenbei verbessert sich dadurch Bobs Work-Life-Balance, aber das ist eine andere Geschichte.

Quellen: