Erinnern Sie sich? Softwarearchitektur hatte ich in Folge 1 dieser Serie als Summe wichtiger Entscheidungen definiert, die im weiteren Verlauf nur schwer zurückzunehmen sind. Um solche Architekturentscheidungen geht es in diesem Schnipsel. Sie fundiert zu treffen (und festzuhalten) ist ein zentraler Erfolgsfaktor für eine nachvollziehbare Softwarearchitektur.

arc42-Starschnitt, Teaser-Bild, Folge_5

Also wieder: Schere raus und losgeschnippelt …

Aus dem Hintergrund müsste Rahn schießen …

Fussball-WM 1954 in der Schweiz. Bei der Aufstellung zum 2. Gruppenspiel der deutschen Mannschaft rieben sich viele die Augen. Kein Toni Turek? Kein Hans Schäfer? Kein Max Morlock? Trainer Sepp Herberger trat mit einer Reservemannschaft an, und die auch damals schon zahlreichen selbsternannten Nationalcoachs fragten sich: „Warum hat er das gemacht? Ich hätte ja …“ — Die Aufstellung war auf den ersten Blick nicht nachzuvollziehen. Deutschland verlor das Spiel gegen Ungarn erwartungsgemäß 3:8. Na toll.

Aus dem Hintergrund müsste Rahn schießen … (Tipp Kick)

Allerdings blieb die haushohe Niederlage ohne Konsequenz, und Herberger wusste das. Deutschland hatte trotz der Schlappe aufgrund des Turniermodus gute Möglichkeiten zum Weiterkommen. Und das Ende ist bekannt, im Finale in Bern schlug eine an sieben Positionen veränderte deutsche Mannschaft wiederum Ungarn 3:2 (Siegtreffer bei Youtube). Um die Aufstellung des verlorenen Gruppenspiels inklusive der einkalkulierten Niederlage nachvollziehen zu können, muss man das große Ganze sehen, die Rahmenbedingungen (wie z.B. den ungewöhnlichen Turniermodus) und die Ziele („Das Spiel ist aus. Deutschland ist Weltmeister“).

Die Mannschaftsaufstellung zählt übrigens zu den Dingen, die ein Trainer im Spielverlauf nur noch schwer revidieren kann. Das galt 1954 noch viel mehr als heute. Denn Auswechseln durfte man beim Fußball in Pflichtspielen erst ab 1967, und selbst dann nur einmal im Spiel (vgl. Wikipedia: Auswechslung).

Warum habt Ihr das eigentlich so gemacht?

„Würde man das nicht eigentlich eher so machen? Ich hätte ja …“ – Neue Mitarbeiter in Softwareentwicklungsprojekten stellen viele Fragen. Nachdem sie arbeitsfähig geworden sind (und etwas mutiger) sogar so spannende wir diese. Der ultimative Test für die Nachvollziehbarkeit Ihrer Architektur eröffnet Ihnen die Chance zu erläutern, warum die gewählten Konzepte und Technologien genau die richtigen, oder zumindest angemessen sind. Wer hier mit „Historisch gewachsen …“ antwortet erntet ggf. Verständnis. Der Ausspruch ist Folklore in IT-Projekten wie der Torschrei beim Fußball. Schlussendlich aber nur das Bekenntnis, dass die Lösung eher zufällig entstanden ist.

Software architecture is the set of design decisions which, if made incorrectly, may cause your project to be cancelled.

(Eoin Woods)

Wo Scheitern keine Option ist, treffen Sie Entscheidungen lieber bewusst. Wesentliche Punkte des Entscheidungsprozesses halten Sie explizit fest.

Wie finden Sie die entscheidenden Fragestellungen?

Jedes Softwarevorhaben ist anders, nichts desto trotz gibt es typische Fragestellungen für Architekturentscheidungen. Dort wo das Risiko groß ist, ist Aufwand für Softwarearchitektur besonders gerechtfertigt. Da das Anbinden von Fremdsystemen beispielsweise oft mit Unsicherheiten verbunden ist, liefert der Systemkontext (siehe Schnipsel #2) oft Ideen. Fragestellungen, die kritisch für die Erreichung der Qualitätsziele sind (siehe Schnipsel #3) , sind ebenfalls Kandidaten für Architekturentscheidungen.

Hier einige typische Fragestellungen zur Illustration:

  • Welche Oberflächen erhalten die unterschiedlichen Benutzer?
  • Wie binden wir Fremdsystem XY an?
  • Welches Produkt/welche Technologie verwenden wir für XY?
  • Wie kommunizieren Bestandteile unseres Systems untereinander?
  • Wie adressieren wir querschnittliche Themen (zum Beispiel Persistenz, Verteilung …)?
  • Implementieren wir eine geforderte Funktionalitat selbst, oder verwenden wir eine bestehende Lösung („Make or Buy“, „Make or Take“)?

Beispiel: Fragestellungen für Gradle

Bei der Konzeption und Entwicklung von Gradle stand das Team vor einer Reihe von Fragestellungen. Hier einige Beispiele, die für Gradle vermutlich relevant waren.

  • In welcher Programmiersprache entwickeln wir Gradle?
  • Wie entwickeln Dritte Erweiterungen („Plugins“) für Gradle? (in Java, in Groovy, …?)
  • Entwickeln wir ein eigenes Dependency Management, oder nutzen wir ein Bestehendes („Make or Buy?“)
  • In welchem Form werden Buildskripte verfasst?

Entscheidungen treffen und nachvollziehbar festhalten

Um derartige Entscheidungen zu bearbeiten und später festzuhalten habe ich gute Erfahrungen mit einer Gliederung gemacht, die ich erstmals in einer Kolumne das Java Magazins in Form einer Mindmap veröffentlicht hatte. Für jede zentrale Entscheidung fragt sie die gleichen Dinge ab. So stellen Sie in einer Dokumentation alle Architekturentscheidungen der Lösung gleichförmig dar.

Mittlerweile konnte ich die Struktur mit ihren zugehörigen Leitfragen in weiteren Projektsituationen und Workshops testen und weiterentwickeln, siehe folgende Abbildung.

Mindmap Architekturentscheidungen (klicken zum Download als PDF)

Die gezeigte Gliederung kann sowohl zur Orientierung beim Treffen der Entscheidung verwendet werden (etwa in einem Workshop), als auch zum Festhalten der Ergebnisse. Letzteres beginnt idealerweise bereits während der Bearbeitung der Entscheidung. Die Punkte 1. – 5. werden in der Dokumentation zu Kapitelüberschriften z.B. innerhalb eines Dokumentes, oder auf einer Wiki-Seite — je nachdem, wo Sie die Entscheidung dokumentieren. An den einzelnen Ästen sind Fragen angehängt, die Sie in eine Vorlage (z.B. ein Wiki-Template) mit aufnehmen können. Sie müssen diese Leitfragen aber nicht sklavisch beantworten. Vielmehr sollen diese Sie und Ihr Team bei einer konkreten Architekturentscheidung, etwa in einem Workshop, leiten, anregen und unterstützen.

Fragestellungen und Annahmen

Auf die Inhalte aller Mindmap-Äste möchte ich hier nicht im Detail eingehen (siehe kostenlose Lesetipps unter „Zum Weiterlesen“ am Endes des Beitrags). Zwei Punkte verdienen aber in Hinblick auf die Dokumentation besondere Aufmerksamkeit: Fragestellung und Annahmen.

Entscheidungen im Projekt gibt es viele. Stellen Sie überzeugend dar, warum die hier betrachtete Fragestellung tatsächlich eine Architekturentscheidung ist. Testen Sie, ob die Entscheidung schwierig zurückzunehmen ist, und/oder das Ergebnis selbst starken Einfluss auf spätere Entscheidungen hat!

Die beschriebenen Einflussfaktoren grenzen die Fragestellung nicht völlig ein, sondern lassen Ihnen Entscheidungsspielraum. Sie treffen Annahmen, welche die möglichen Optionen weiter reduzieren oder sich auf die Bewertung der Optionen auswirken. Im Grunde wird jede Architekturentscheidung unter gewissen (oft impliziten) Annahmen getroffen. Teilweise im Dunkeln, wie Phillip Kruchten so schön sagt:

The life of a software architect is a long (and sometimes painful) succession of suboptimal decisions made partly in the dark.

(Philippe Kruchten)

Annahmen zählen zu den Dingen, die im Nachhinein beinahe unmöglich zu rekonstruieren sind. Halten Sie sie fest!

Doch nun zu unserem Serienstar! Und zum Schnipsel dieser Folge: Eine Architekturentscheidung von Gradle, dargestellt in der vorgeschlagenen Struktur.

– – – 8< – – –

Schnipsel #5 (Architekturentscheidung): Eine zentrale Entscheidung von  Gradle

In welchem Form werden Buildskripte verfasst?

Der Build-Manager beschreibt den projektspezifischen Build, d.h. die von Gradle zu verabeitenden Daten und Dateien, die nötigen Verarbeitungsschritte inkl. der Abhängigkeiten, die Ergebnisse des Builds, … . Dieses sogenannte Build-Skript ist sein wichtigstes Kommunikationsmittel mit dem Build-System, zudem teilt er es mit den beteiligten Entwicklern. In welcher Form wird es verfasst?  Verschiedene Build-Lösungen (etwa make, Maven, Rake) wählen sehr unterschiedliche Formate. Grundsätzlich lassen sich strukturierte Datenformate, etwa XML oder JSON,  und ausführbare Skripte, etwa formuliert in einer Skriptsprache, unterscheiden. Form und Format haben großen Einfluss auf die Akzeptanz von Gradle. Und würden Form und/oder Format im Rahmen der Gradle-Weiterentwicklung grundlegend geändert, müssten bestehende Gradle-Builds migriert werden, entwickelte Erweiterungen vermutlich ebenfalls angepasst. Die Antwort auf diese Fagestellung entscheidet schlussendlich über Erfolg und Misserfolg des Build-Systems.

EinflussfaktorenSchnipsel Nr. #5

Bei der Entscheidung ist zu beachten, dass Gradle als JVM-basiertes Build-System konzipiert ist. Weiterhin unterliegt es der Apache Apache License 2.0. Ausserdem sollte das Risiko im Auge behalten werden, dass das ausgewählte Format und/oder die verwendete Technologie langfristig an Akzeptanz verlieren könnte. Folgende Qualitätsziele sind bei der Entscheidung maßgeblich:

  • Erweiterbarkeit (die Wahl des Formates fördert das Hinzufügen neuer Funktionalität zu Gradle)
  • Erlernbarkeit (das Format ist für die Hauptzielgruppen leicht zugänglich)
  • Skalierbarkeit (auch umfangreiche Projekte lassen sich mit den Build-Skripten leicht beschreiben)

Annahmen

Wir nehmen an, dass die Akzeptanz von XML als Datenformat in der Java-Gemeinde generell abnimmt. Groovy bleibt auf lange Sicht am Markt relevant. Buildmanager sind bereit eine neue Skriptsprache zu lernen. Die Freiheiten, die durch ausführbare Skripte im Build entstehen, werden akzeptiert, und nicht als Gefahr gesehen.

Betrachtete Alternativen

Grundsätzlich lässt sich zwischen strukturierten Datenformaten (z.B. XML) und ausführbaren Skripten unterscheiden, auch ein Mix ist denkbar.

Für Dateiformate wie XML und JSON sprechen der bestehender Tool-Support (Editoren in IDEs, Parser) und im Falle von XML gute Validierungsmöglichkeiten (Stichwort: Schema). Die Erfahrung mit Ant und Maven hat allerdings gezeigt, dass XML-basierte Skripte – zumindest wie dort verwendet – einfache adhoc-Aufgaben (z.B. Fallunterscheidungen) erschweren. Auch für Kleinigkeiten ist die Programmierung von Plugins erforderlich.

Ein reines Skript (also ein direkt in einem Skriptsprache formuliertes Programm) könnte ebenfalls vom vorhandenen Tool-Support profitieren. Aber diese Form erschwert es die nötigen Inhalte (z.B. Abhängigkeiten zwischen Taks) ausdrucksstark zu formulieren. Deshalb wird dieser Ansatz nicht verfolgt.

Ziel ist daher eine Skriptform, die deskriptiv ist (also die Elemente des Build beschreibt), und gleichzeitig ausführbare Elemente beinhalten kann.

Auszuwählen ist dann noch die zu verwendende Sprache. Ein klares Bekenntnis für eine Sprache sorgt für Orientierung, und erleichtert vieles. Der Ansatz, mehrere Sprachen zu untertützen (JSR 223, Scripting for the Java TM Platform), und die Wahl dem Buildmanager zu überlassen, wird daher nicht verfolgt.

Als Kandidaten kommen auf der JVM verfügbare Skriptsprachen in Frage, z.B.:

 

Sprache TIOBE RedMonk auf JVM (Lizenz) Erlernbarkeit (*)
Groovy #47 #18 Groovy (Apache License 2.0) Sehr leicht
JavaScript #10 #2 Rhino (Mozilla Public License) mittel
Python #8 #4 Jython (Python Software Foundation License) leicht
Ruby #13 #5 JRuby (CPL, GPL und LGPL) mittel

 

Der TIOBE-Index (Stand hier: Dezember 2013) und das RedMonk Programming Language Ranking (Stand hier: Juni 2013) sind Versuche, die Popularität und Verbreitung von Programmiersprachen über die Zeit zu beobachten, und zu messen.

(*) Die Einschätzung bezieht sich ausschließlich auf die Erlernbarkeit für Java Entwickler und ist subjektiv.

Entscheidung

Gradle-Buildskripte basieren auf Groovy.

Das Hauptargument für Groovy ist die betont einfache Erlernbarkeit für Entwickler mit Java-Background. Weiterhin ermöglichen die DSL-Features von Groovy deskriptive Build-Skripte und eine gute Erweiterbarkeit.

Auch wenn das RedMonk Ranking nicht allgemein anerkannt ist, und der TIOBE-Index sogar häufig in der Kritik steht – die Zahlen weisen daraufhin, dass Groovy verglichen mit den anderen Optionen wenig(er) verbreitet ist. Die Wahl fiel trotzdem auf Groovy, die leichte Erlernbarkeit wurde höher bewertet.

JavaScript ist für Java-Entwickler weniger zugänglich, und hatte zum Zeitpunkt der Entscheidung (vor 2009) noch nicht die Relevanz und Akzeptanz in der Java-Welt wie heute. Für JavaScript spräche allerdings, dass es in der Java SE mitgeliefert wird (ab Java Version 6), die Lizenz wäre daher kein echtes Hindernis.

Die Art und Weise, wie Build-Skripte in Groovy grundsätzlich aufgebaut sind, wird in einem separaten Konzept beschrieben.

– – – >8 – – –

An dieser Stelle sei noch bemerkt, dass natürlich nicht ich die Entscheidung getroffen habe, und ich auch nicht im Detail weiss, ob sie in der Form wie oben dargestellt bearbeitet wurde. Sie ist ein Beispiel, wie Sie eine Architekturentscheidung nachvollziehbar darstellen, und auch abgesicherern können.

Wie verwenden Sie die Struktur?

Die Struktur ist zur Ablage von Ideen in Workshops geeignet, und später zur Gliederung beim Festhalten. Auch wenn die fünf Punkte eine sinnvolle Reihenfolge zur Bearbeitung vorgeben — hangeln Sie sich nicht zu sklavisch daran entlang. Oft fallen Ihnen auf dem Weg Dinge ein, die in der Struktur eher nach vorne gehören. Wenn Sie beispielsweise Alternativen bewerten, treffen Sie ggf. Annahmen und entdecken weitere Einflussfaktoren.

Wo kleben wir den Schnipsel hin?

Architekturentscheidungen finden in arc42 in Abschnitt 9 („Entwurfsentscheidungen“) ihren Platz. Pro Entscheidung ist ein Unterabschnitt vorgesehen. Mein Vorschlag mit der oben gezeigten Struktur pro Entscheidung ist mittlerweile in arc42 eingeflossen (vgl. arc42-Template), worauf ich ein bisschen stolz bin. Die generischen Überschriften „Entwurfsentscheidung 1“, „Entwurfsentscheidung 2“, … tauschen Sie gegen aussagekräftige Titel aus, um die Benutzbarkeit des Inhaltsverzeichnisses zu erhöhen. Ich persönliche empfinde die Fragestellung der Entscheidung (z.B. „In welchem Form werden Buildskripte verfasst?“) als Titel sehr lebendig.

 Abheften des Schnipsel #5 in arc42

Im 4. Abschnitt („Lösungsstrategie“) greifen Sie typischerweise vor und nennen bereits zentrale Entscheidungen, die Sie in Abschnitt 9 ausführlicher darstellen. Weisen Sie in Ihrer Strategie auf die genauere Begründung hin, ggf. (je nach Werkzeug) per Link.

Noch mehr Entscheidungen?

Im Rahmen eines Architekturüberblicks halte ich nur wenige, zentrale Archtekturentscheidungen in der vorgeschlagenen Form fest. Abschnitt #9 ist nicht der einzige Platz in arc42, in dem sich Entscheidungen niederschlagen. Strukturentscheidungen landen typischerweise in der Bausteinsicht (siehe Schnipsel #4), Verteilungsaspekte in der Verteilungssicht, usw. Und oft wird eine Architekturentscheidung in einem technischen oder übergreifenden Konzept weiter verfeinert.

Zum Weiterlesen

Ausblick

Den fünften Gradle-Schnipsel zum farbig ausdrucken, ausschneiden und aneinanderkleben können Sie hier herunterladen. 😉

In der nächsten Folge werde ich mich einer stiefmütterlich behandelten Zutat widmen: dem Glossar. Und zeigen, dass Sie sowas peppiger aufziehen können als mit einer schnöden Tabelle. Neugierig? Dann lesen wir uns im neuen Jahr wieder! Eine frohe Weihnachtszeit und einen guten Start in 2014!

Ich hoffe, Sie finden weiterhin Gefallen an dieser kleinen Serie und freue mich auf Ihre Fragen und Rückmeldungen. Kommentieren Sie einfach hier im Blog oder schreiben Sie mir (E-Mail: stefan[ät]swadok.de). Wünsche greife ich gerne in den nächsten Folgen auf, Fragen beantworte ich direkt hier.

Sie haben einen Schnipsel des arc42-Starschnitts zu Gradle verpasst? Hier finden Sie alle bisherigen Folgen.