Agile Softwarearchitektur im Team – Mit Selbstorganisation zum Erfolg
Vor einiger Zeit arbeitete ich als technischer Projektleiter zusammen mit einem agilen Team an der Entwicklung eines neuen Finanzdatenportals. Auch wenn ich in meiner Rolle nicht direkt an der Entwicklung beteiligt war, konnte ich es mir nicht verkneifen, hier und da einen Blick auf den Code zu werfen. Dabei stolperte ich über eine Komponente, die im Programmablauf dynamisch Javascript-Dateien ausführte und die ich so in einer JEE-Applikation nicht erwartet hatte.
Verwundert wollte ich mehr über die Hintergründe dieser Architekturentscheidung erfahren und fragte die Entwickler nach den Beweggründen hinter ihrer Entscheidung. Sie erklärten mir, dass es mit dieser Komponente möglich sei, schnell und ohne zeitaufwändige Deployments Änderungen an der Businesslogik vornehmen zu können. Das Erstaunliche jedoch war, dass der Product Owner von einer solchen Anforderung nichts wusste – und auch einigen Entwicklern war das neue Modul nicht bekannt. Zudem fühlten sie sich bei dem Gedanken, Teile des Codes in Javascript entwickeln zu müssen, nicht wohl. Kurzum entschloss man sich daher, diese Änderung wieder rückgängig zu machen und erst bei Bedarf neu zu prüfen.
Da sich das Projekt noch in einem frühen Stadium befand, war der entstandene Mehraufwand überschaubar. Dennoch fragte ich mich, wie es dazu kommen konnte, dass die Architektur trotz einer agilen Vorgehensweise diesen Irrweg eingeschlagen hatte und ob diese Entwicklung hätte vermieden werden können. Wessen Verantwortung wäre es gewesen, ein Auge darauf zu haben?
Selbstorganisation statt "historischer Wildwuchs"
Die Antwort auf diese Frage findet sich in einem der zwölf Prinzipien des agilen Manifestes [1]: "Die besten Architekturen, Anforderungen und Entwürfe entstehen durch selbstorganisierte Teams."
Entwickler sind demnach in der Pflicht, die für sie passenden Arbeitsabläufe und Strukturen selbst zu definieren, um die optimale Architektur entwickeln zu können. Wie ich jedoch in meiner Projektpraxis immer wieder beobachten muss, ist genau dies für viele agile Teams die größte Herausforderung. Doch woran liegt das? Zwei Gründe scheinen mir ausschlaggebend zu sein.
Zum einen finden sich in den Leitfäden der etablierten agilen Frameworks wie Scrum, Kanban oder XP kaum Hinweise zum Umgang mit Softwarearchitektur. Bei oberflächlicher Betrachtung kann man daher zu dem Schluss kommen, dass die Best Practices und Artefakte dieser Vorgehensmodelle ausreichend sind, um eine tragfähige Architektur des Produktes zu gewährleisten. Insbesondere Teams, die gerade erst mit der agilen Softwareentwicklung begonnen haben, laufen jedoch Gefahr, sich allein auf die Praktiken und Artefakte dieser Frameworks zu verlassen und den wichtigen Aspekt der Selbstorganisation zu vernachlässigen.
Zum anderen wird zu Beginn eines Projektes oft nur ein Minimum Viable Product (MVP) definiert. Dieses erfüllt lediglich die notwendigsten Anforderungen, sorgt aber dafür, dass das Produkt möglichst schnell live gehen kann. So erhält das Team zwar schnell Feedback, das in die weiteren Entwicklungen einfließen kann, jedoch lässt sich am MVP in der Regel nicht vollständig erkennen, ob alle Qualitätsmerkmale ausreichend abgedeckt sind und die gewählten Lösungsansätze und damit die ganze Architektur tragfähig sind. Defizite werden somit erst spät im Projekt sichtbar und Effektivität und Konsistenz der Softwarearchitektur leiden darunter.
Spricht man die Entwickler auf die daraus resultierenden Mängel in der Architektur an, so höre ich häufig als Erklärung, die Software sei "historisch gewachsen" – oder wie ein Kollege es gern formuliert: "hysterisch gewachsen". Doch diese Fehlentwicklungen lassen sich vermeiden.
Um eine solch mangelhafte Architektur von Beginn an zu verhindern – auch oder wenn das Team erst wenig agile Erfahrung hat – ist meiner Ansicht nach die Bearbeitung von vier Kernaufgabengebieten (s. Abb.1) nötig. Lassen Sie uns diese im Folgenden näher betrachten.
Nicht-funktionale Anforderungen erfassen und quantifizieren
In agilen Projekten ist es üblich, die Anforderungen an das Produkt in einem sogenannten Backlog zu erfassen und über dieses die Entwicklung zu planen und zu steuern. Die Anforderungen definieren Product Owner und Entwickler gemeinsam in Form von User Stories. Da diese jedoch einen anwendungsfallorientierten Fokus haben, werden nicht-funktionale Anforderungen, wie beispielsweise Internationalisierung oder Suchmaschinenoptimierung, in der Regel außer Acht gelassen – es sind jedoch genau diese Qualitätsmerkmale, die die Architektur des Systems im Wesentlichen bestimmen. Werden sie erst spät im Projekt erkannt, kann es zu erheblichen Mehraufwänden und zeitlichen Verzögerungen kommen.
Werden Qualitätsanforderungen jedoch, wie im eingangs erwähnten Beispiel, übererfüllt, können ebenfalls Probleme auftreten: Auch in diesem Fall sind erhöhte Komplexität und zusätzliche Aufwände die Folge. Umso wichtiger ist es, sowohl funktionale als auch nicht-funktionale Anforderungen zu erfassen und zu quantifizieren – und auch die damit verknüpften Kosten transparent zu machen.
Nicht zuletzt müssen alle Lösungsansätze auch gegen die vorab definierten Anforderungen geprüft werden. Nicht selten beobachte ich Performanceoptimierungen zu Kosten der Wartbarkeit des Codes – jedoch ohne, dass es explizite Messungen und Prüfungen gibt. Hiervor warnte schon Donald Knuth mit seiner bekannten Aussage: "Premature optimization is the root of all evil[2]."
Entscheidungen vorbereiten und treffen
Die Architektur eines Systems ergibt sich aus der Summe aller getroffenen Entscheidungen, wobei jede Entscheidung den Freiheitsgrad des Systems weiter einschränkt. Spätere Änderungen dieser Entscheidungen sind zudem meist mit erheblichen Aufwänden verbunden. Teams sind daher gut beraten, jede Entscheidung systematisch und bedacht zu treffen, möglichst viele Aspekte und Alternativen einfließen zu lassen und den richtigen Zeitpunkt für die Entscheidung zu finden. Auch wenn Vorgehensmodelle wie Scrum und Kanban für diesen Aspekt der agilen Softwareentwicklung leider keine konkreten Hilfestellungen liefern, sollten Entwicklungsteams diese Entscheidungen auf keinen Fall der Willkür und dem Zufall überlassen, sondern diese bewusst gemeinsam treffen.
Entscheidungen und insbesondere ihre Herleitung sollten des Weiteren unbedingt festgehalten und dokumentiert werden. Geschieht dies nicht und man hinterfragt zu einem späteren Zeitpunkt den gewählten Lösungsansatz, erhält man nicht selten die Antwort: "Ich kann dir nicht mehr genau sagen, warum wir uns dafür entschieden haben, aber es gab einen guten Grund." Veränderte Rahmenbedingungen und entsprechende Alternativen können so nicht gegengeprüft werden – eine Dokumentation hingegen würde Abhilfe schaffen.
Architektur dokumentieren und kommunizieren
Generell kommt der funktionierenden Software in der agilen Softwareentwicklung ein höherer Stellenwert zu als einer umfangreichen Dokumentation. Komplett verzichten sollten Entwickler auf diese jedoch nicht. "Der Code ist unsere Dokumentation", höre ich häufig als Argument. Sicherlich ist dieser die zuverlässigste Informationsquelle – daher ist es auch so wichtig, dass seine Lesbarkeit nach höchsten Maßstäben entwickelt wird. Denn, wie Martin Fowler so treffend sagt: "Any fool can write code that a computer can understand. Good programmers write code that humans can understand [3]."
Doch es gibt – gerade in Hinblick auf die Architektur – Aspekte, die sich nur schwer aus dem Code ableiten lassen. Um konzeptionelle Muster, auf die sich das Team geeinigt hat und denen es bei der Entwicklung folgt, Rahmenbedingungen und Protokollspezifikationen von Schnittstellen nachvollziehen zu können, ist eine gute Dokumentation unabdingbar. Für neue Entwickler im Team und Stakeholder wie die Betriebsabteilung oder unterschiedliche Fachbereiche ist es wichtig, einen schnellen Überblick zu wichtigen Details des Gesamtsystems bekommen zu können und ihr wichtiges Feedback einfließen zu lassen.
Technische Schulden erkennen und begleichen
Trotz aller Umsicht lässt es sich im Laufe der Entwicklung nicht vermeiden, dass technische Altlasten die Entwicklungsgeschwindigkeit Stück für Stück verringern. Da gibt es zum Beispiel Frameworks, die nicht weiterentwickelt werden und für die immer öfter aufwändige Workarounds gefunden werden müssen. Oder aber die Rahmenbedingungen, unter denen Technologieentscheidungen getroffen wurden, haben sich verändert und die einstmals vielversprechenden Lösungsstrategien erweisen sich als Sackgasse. Was auch immer die Gründe für diese technischen Schulden sind, sie müssen über kurz oder lang abgebaut werden, möchte man die gewohnte Entwicklungsgeschwindigkeit nicht verlieren. Auch wenn diese Baustellen bekannt sind, wissen Entwickler oft nicht, wie sie die damit verbundenen Arbeitspakete in die Entwicklungsplanung einbringen sollen. Dabei ist es für die Nachhaltigkeit des Produktes wichtig, dass für technische Schulden die gleiche Transparenz herrscht, wie für funktionale Anforderungen. Nur so können alle Aufwände gegeneinander aufgewogen und bei der Weiterentwicklung berücksichtigt werden. Das erfordert vor allem vom Entwicklungsteam, dass Aufwände und Geschäftswert der Lasten ermittelt und für alle verständlich dargelegt werden.
Mit Ritualen zum Erfolg
Doch wie ist es zu schaffen, dass all diese Aspekte und Aufgaben durch das Team wahrgenommen werden? Einen Weg, das eigene Verhalten nachhaltig zu verändern, kennen wir aus unserem privaten Umfeld: Sollen bestimmte Aktivitäten, wie mehr Sport zu treiben oder mehr Wasser zu trinken, zur Gewohnheit werden, müssen sie konsequent in den Alltag eingebaut und regelmäßig wiederholt werden. Auf die Aufgaben der agilen Softwarearchitektur bezogen bedeutet dies, dass diese dementsprechend vom gesamten Team verinnerlicht und zu Ritualen gemacht werden müssen. Agile Vorgehensweisen wie Scrum bieten hierfür bereits einen idealen Rahmen in Form von festen Regelmeetings und Artefakten.
Eine gute Gelegenheit, die Kernaufgaben in Form von Ritualen zu etablieren, bietet eine Team-Retrospektive [4]. Zunächst sollte sich das Team einen Überblick darüber verschaffen, nach welchen Prinzipien die oben beschriebenen Aufgabenfelder angegangen werden sollen, so dass alle ein gemeinsames Verständnis der Aufgaben und Ziele haben. Möglich ist dies zum Beispiel durch eine Tabelle wie Abb.2.
Auf dieser Grundlage können dann konkrete Aktivitäten abgeleitet und wiederum mit den Regelmeetings und Artefakten verknüpft werden. Abb.3 zeigt ein mögliches Ergebnis für das Backlog Refinement Meeting.
Mit Führung zum Ziel
Damit es nicht nur bei guten Vorsätzen bleibt, muss sich das Team die Beschlüsse immer wieder ins Gedächtnis rufen und die Umsetzung gegebenenfalls einfordern. Leider führen geteilte Verantwortungen häufig dazu, dass sich jeder auf den anderen verlässt und sich schließlich niemand um die Themen kümmert. Um dem entgegenzuwirken hat es sich bewährt, wenn ein oder mehrere Teammitglieder die Rolle des "Architecture Guide" übernehmen und die Einhaltung der beschlossenen Rituale im Auge behalten. Durch diesen klaren fachlichen Fokus können sie außerdem ihre Expertise auf diesem Gebiet kontinuierlich vertiefen und dem Team wichtige Impulse zur Verbesserung der Softwarearchitektur geben.
Fazit: Gesteigerte Effektivität und Effizienz durch agile Softwarearchitektur
Durch den vorgestellten Lösungsansatz lässt sich sicherstellen, dass die Architekturarbeit in den Fokus des Teams rückt und die Kernaufgaben systematisch angegangen werden. Durch die Etablierung und Nutzung von Ritualen wird zusätzliche Komplexität vermieden und die nachhaltige Verankerungen neuer Aufgaben im Team ermöglicht.
Im Gegensatz zum klassischen Vorgehensmodell in der Softwareentwicklung, bei dem ein Architekt das gesamte Aufgabenspektrum abdecken und im Blick haben muss, wird bei der agilen Herangehensweise die Arbeit durch das gesamte Team geleistet. Die Abstimmung zwischen Architekt und Entwicklern wird durch ein kollektives Verständnis der Softwarearchitektur ersetzt. Ralph Johnson hat dieses Bild sehr treffend beschrieben:
"In most successful software projects, the expert developers working on that project have a shared understanding of the system design. This shared understanding is called ‚architecture’.[5]"
Durch die Verlagerung der Architekturverantwortung auf das gesamte Team eröffnen sich noch weitere Vorteile: Die individuellen Fähigkeiten, Erfahrungen und Blickwinkel lassen sich für eine differenziertere und umfänglichere Betrachtung der Architektur nutzen, denn wie heißt es so schön: "Du glaubst nur solange, eine gute Architektur entworfen zu haben, bis du sie jemandem erklärst." Zudem wird jeder Einzelne motiviert, die Architekturprinzipien umzusetzen, wenn das gesamte Team an der Entwicklung mitarbeitet.
Zu guter Letzt löst dieser Ansatz auch noch ein organisatorisches Problem. Der klassische Softwarearchitekt begleitet in der Regel mehrere Entwicklungsteams, da seine Unterstützung phasenweise oder punktuell benötigt wird. Im ungünstigen Fall wird er daher zum Flaschenhals, sobald mehr als ein Team zeitgleich seine Hilfe in Anspruch nimmt. Ist das gesamte Team in der Architektenrolle, ist der Fortschritt des Projektes nicht nur von einer Person abhängig – Engpässen kann besser begegnet und der Zeitplan eingehalten werden.
Die Kernaufgaben der agilen Softwarearchitektur bringen zusätzliche Aufwände für das Entwicklerteam mit. Die Vorteile, die sich daraus für die Qualität des Produkts ergeben, sorgen jedoch langfristig für eine effizientere und effektivere Softwareentwicklung, die schlussendlich Zeit und Geld spart.
- Das agile Manifest
- Wikiquote: Donald Knuth
- Wikiquote: Martin Fowler
- Informatik Aktuell: Judith Andresen - Retrospektiven im Projektmanagement
- Ralph Johnson / Martin Fowler: Who Needs an Architect?
weitere Hintergrundinformation: S. Toth, 2015: Vorgehensmuster für Softwarearchitektur: Kombinierbare Praktiken in Zeiten von Agile und Lean