Software-Architektur

Eine kurze Einführung in das Thema Software-Architektur
von Dana Bredemeyer

Dana betreibt die Website „Resources for Software Architects“. Mit seiner Firma (Bredemeyer Consulting) veranstaltet er weltweit Seminare für Software-Architekten und ist eine anerkannte Autorität in seinem Fachgebiet. Der folgende Text ist eine auszugsweise Übersetzung von Material von dieser Website. Das Thema ist sehr komplex und kann deshalb hier nur angerissen werden.

Verwendet mit freundlicher Genehmigung des Autors. Übersetzung von Andreas Göbel.

Was ist Software-Architektur?

Software-Architektur ist die oberste Strukturebene eines Software-Systems. Zu den wichtigen Eigenschaften einer Software-Architektur gehören:

  • Die Abstraktionsebene ist so beschaffen, dass man das System als Ganzes betrachten kann.
  • Die Struktur muss die für das System geforderte Funktionalität tragen. Deswegen muss beim Design der Software-Architektur auch das dynamische Verhalten des Systems berücksichtigt werden.
  • Die Struktur – oder Architektur – muss den geforderten Systemeigenschaften (auch „nicht-funktionale Anforderungen“ genannt) entsprechen. Dazu zählen zum Beispiel Anforderungen an die Performanz (Antwort/Zeitverhalten) und die Stabilität der aktuellen Ausbaustufe oder der Schutz vor unbefugter Benutzung, sowie Anforderungen bezüglich der Flexibilität oder Erweiterbarkeit beim Umsetzen zukünftiger Funktionalität zu vertretbaren Kosten. Zwischen diesen Anforderungen können Konflikte entstehen, und Abwägungen und Kompromisse zwischen den möglichen Alternativen sind ein wesentlicher Bestandteil beim Entwickeln einer Software-Architektur.
  • Auf der Ebene der Software-Architektur bleiben alle Implementierungsdetails verdeckt.

Eine Software-Architektur wird durch die Beschreibung von Software-Komponenten und deren Verbindungen und Interaktionen untereinander definiert. Komponenten werden ermittelt und ihnen werden Fähigkeiten zugeordnet, auf die benutzende Komponenten über definierte Schnittstellen zugreifen können. Die Verbindungen der Komponenten eines Systems untereinander definieren dessen Kommunikations- und Kontrollmechanismus und die über diese Verbindungen ablaufenden Interaktionen zwischen den Komponenten ermöglichen das geforderte Systemverhalten.

Beim Entwickeln einer Software-Architektur beschäftigt man sich mit:

  • Meta-Architektur: Das ist die Architekturvision, der Architekturstil, die Prinzipien, die grundlegenden Kommunikations- und Kontrollmechanismen und die Konzepte, die das Architekten-Team bei der Entwicklung der Architektur anleiten.
  • Architektursichten: Architekturentwürfe von Häusern kann man sich am besten anhand von unterschiedlich strukturierten, sich einander ergänzenden Plänen und Modellen verdeutlichen. Das Gleiche gilt für Software-Architekturen:
    • Strukturansichten verdeutlichen die Architektur durch die Dokumentation der Komponenten und ihrer Beziehungen untereinander. Sie helfen auch, die Systemeigenschaften, zum Beispiel bezüglich Erweiterbarkeit, zu untersuchen.
    • Darstellungen des Verhaltens des Systems sind hilfreich, wenn durchdacht wird, wie die Komponenten zusammenspielen müssen, damit sie die Ihnen zugeordneten Aufgaben erfüllen können. Sie unterstützen die Architekten bei der Bewertung der Auswirkungen von „Was wäre wenn?“-Szenarios auf die Architektur. Verhaltensmodelle werden auch eingesetzt, wenn die Laufzeiteigenschaften des Systems betrachtet werden sollen.
    • Ausführungssichten helfen die Alternativen bei der physikalischen Struktur des Systems zu untersuchen. Sie dokumentieren und kommunizieren die entsprechenden Entscheidungen.
  • Architekturmuster: In verschiedenen Systemen immer wiederkehrende strukturelle Muster. Dazu gehören die verschiedenen Schichten des Systems (GUI, Logik, Datenbank) oder Client/Server-Beziehungen und auch Mechanismen, wie zum Beispiel Broker oder Bridges.
  • Zu den wichtigsten Design-Prinzipien gehören die Abstraktion, das Herauslösen von Problemen und das Zurückstellen von Entscheidungen. Eine gute Software-Architektur ist einfach zu verstehen und darzustellen und beschränkt sich auf das Wesentliche. Nützliche Techniken sind zum Beispiel die Kapselung von Funktionalität und das Bilden von Schnittstellen.
  • Schneiden von Komponenten und Interface-Design für Komponentenschnittstellen.

Was gehört nicht zur Software-Architektur?

Das Low-Level-Design eines Software-Systems gehört nicht zur Software-Architektur. Zum Low-Level-Design gehören zum Beispiel die Beschreibung von Abläufen innerhalb einer Komponente und die Festlegung der zur Realisierung von Funktionalität verwendeten Algorithmen. Man sollte die Software-Architektur auch nicht mit dem Datenmodell des System verwechseln, obwohl für die Software-Architektur Typinformationen aus dem Datenmodell zur Beschreibung von Schnittstellen verwendet werden können. Die Software-Architektur beschreibt auch nicht die System-Hardware auf denen das Software-System abläuft, also zum Beispiel die Netzwerke und die darüber angebundenen Computer. Sie nutzt diese Informationen zur Bewertung der Auswirkungen von Architekturentscheidungen bezüglich Performanz und Stabilität. Auch die Hardware-Architektur eines zu entwickelnden Produktes oder Gerätes ist nicht Bestandteil der Software-Architektur (sic!). Diese verwandten Architekturen werden normalerweise von Spezialisten entworfen. Allerdings stehen sie in einem dialektischen Verhältnis zur Software-Architektur: Sie beeinflussen die Software-Architektur und werden gleichzeitig selber von dieser beeinflusst. Deswegen sollten diese Architekturen nicht unabhängig voneinander entworfen werden. Das fällt in den Aufgabenbereich von System-Architekten.

Eine Randbemerkung: Wenn man die besonderen Techniken zur Software-Modellierung außer Acht lässt, kann ein guter Software-Architekturprozess auch mit Erfolg auf die System-Architektur, die Hardware-Architektur oder völlig fachfremde mehrdimensionale Probleme wie die Strukturierung von Wirtschaftsunternehmen angewandt werden.

Wozu benötigt man eine Software-Architektur?

Die Software-Architektur dient sowohl technischen als auch organisatorischen Zwecken. Auf der organisatorischen Seite wird die Software-Architektur zu den folgenden Aufgaben eingesetzt:

  • Kommunikation des High-Level-Designs. Eine Reihe von „Stakeholdern“ müssen sich einen groben Überblick über die Funktionsweise des Systems verschaffen können. Dazu gehören das höhere Management, projektübergreifende Teams (Marketing, Qualitätssicherung, Schulung, Anwenderdokumentation usw.) und manchmal auch die internen oder externen Auftraggeber. Die Verdichtung der Software-Architektur in ein High-Level-Modell ermöglicht das Verständnis der wesentlichen Elemente der Architektur („der Blick aufs Wesentliche“). Obwohl das trivial klingt, hat es doch wichtige Auswirkungen auf die Kommunikation: Bei geeigneter Aufteilung und Verknüpfung kann man selbst die Konzepte eines sehr großen Software-Systems mithilfe weniger Overhead-Folien transportieren bzw. auf wenigen Seiten Papier dokumentieren.
  • Vermitteln der Gesamtzusammenhänge. Auch die Software-Entwickler benötigen den Überblick über die Gesamtzusammenhänge („Roter Faden“). In einem großen System kann nicht von jedem einzelnen Entwickler erwartet werden, dass er jedes Detail des Gesamtsystems kennt und versteht. Natürlich benötigt jeder Entwickler die für seine Arbeit notwendigen Detailkenntnisse. Aber ohne das Verständnis der Aufgaben und Abhängigkeiten der High-Level-Strukturen entstehen bei den Entwicklungs- und Optimierungsarbeiten an den einzelnen Komponenten häufig suboptimale Ergebnisse. Das bezieht sich sowohl auf die Eigenschaften des Gesamtsystems (Performanz), wie auch auf Erweiterbarkeit und Wartung der einzelnen Komponenten.
  • Aufteilung in Arbeitsblöcke. Da durch die Architektur das Gesamtsystem in relativ unabhängige Unterstrukturen (Komponenten) mit klaren Aufgaben und wenigen wohl definierten Schnittstellen zerlegt werden kann, können auch die Entwicklungsarbeiten anhand der Komponentenzerlegung aufgeteilt werden („Teile und Herrsche“). So können einzelne Teams parallel und zwischen den notwendigen Integrationspunkten unabhängig an der Implementierung des Systems arbeiten. Das ist besonders dann wichtig, wenn in sehr großen Projekten die Teams räumlich voneinander getrennt sind oder wenn die Realisierung von einzelne Komponenten an externe Firmen vergeben wird. Innerhalb der Arbeitsteams wird die Spezialisierung und Fokussierung der einzelnen Mitarbeiter gefördert, da die einzelnen Komponenten die inhaltlich zusammengehörige Funktionalität und damit auch das Fachwissen der Entwickler zentralisieren. Zusammen fördern diese beiden Aspekte, also unabhängige Entwicklung mit fokussierten Mitarbeitern, die Effizienz der Software-Entwicklung. Das sollte sich auch in der Organisation der Entwicklungsteams widerspiegeln. Wenn diese Dualität ignoriert wird und die organisatorischen Strukturen nicht kompatibel mit denen der Software-Architektur sind, kann das Gesamtprojekt nicht effektiv arbeiten.

Auf der technischen Seite ermöglicht eine gute Software-Architektur das Design von besserer Software:

  • Erfüllen von Systemanforderungen und Zielen: Sowohl funktionale als auch nicht-funktionale Anforderungen können mittels eines einfachen Schemas (Muss-, Soll- und Kann-Anforderungen) priorisiert werden. Mit Hilfe der Architektur können diese häufig miteinander konfliktierenden Anforderungen ausbalanciert werden, indem Muss-Anforderungen bei der Entwicklung der Architektur stärker berücksichtigt werden. Obwohl nicht-funktionale Anforderungen mit Fortschritt der Entwicklungsarbeiten häufig abgeschwächt werden müssen, werden sie nie erfüllt, wenn sie nicht explizit auf der Ebene der Architektur berücksichtigt werden.
  • Flexible Aufteilung und Verteilung des Systems: Das Resultat einer guten Architektur ist ein flexibles System, das auch ohne Redesign der einzelnen Komponenten auf unterschiedlichen physischen Rechnerkonfigurationen eingesetzt werden kann.
  • Reduzierung der Wartungs- und Weiterentwicklungskosten. Eine gute Architektur versucht den gesamten Lebenszyklus eines Software-Systems, inklusive der wahrscheinlichsten Änderungen und Erweiterungen, abzudecken. Das Gesamtdesign muss solche Wartungsarbeiten und Erweiterungen unterstützen, indem die Auswirkungen dieser Arbeiten auf existierenden Code, Dokumente oder andere Artefakte lokal begrenzt werden. Das kann durch die Begrenzung und Kontrolle der gegenseitigen Abhängigkeiten der Software-Komponenten erreicht werden.
  • Förderung der Wiederverwendung und Einbindung von bereits existierenden bzw. zugekauften Bestandteilen. Eine Architektur kann so designed werden, dass die (Wieder-)Verwendung von bereits existierenden oder zugekauften Frameworks, Komponenten, Klassenbibliotheken, Legacy-Code etc. unterstützt wird.