Kein technisches Problem

Viele Praktiken von Softwareentwicklung und -architektur versprechen Hilfe in dieser Situation – allerdings helfen sie in der Regel nicht gegen knappe Budgets und drängelnde Manager.

Die ursprüngliche Ordnung im System geht immer mehr verloren. Ausnahmen werden zur Regel, Code wird immer schwerer verständlich. Das Entwicklungsteam beginnt von „historisch gewachsen“ zu sprechen – weil kaum jemand nachvollziehen kann, wie es zu dieser kontinuierlichen Verschlechterung kommen konnte.

Aber wo liegen die Gründe? Verlernen Teams über die Zeit das saubere Arbeiten? Keinesfalls: Aller Erfahrung nach liegt die Legacy-Hölle sehr häufig in der Kombination verschiedener Umstände begründet: dies sind Zeitdruck, schlechte Kommunikation im Team, Wechsel von Teammitgliedern, unterschiedliches Know-how, Altlasten, inkonsistenter Code, mangelnder Fokus auf langfristige Ziele wie Wartbarkeit oder Verständlichkeit.

Um dieser Hölle zu entkommen, müssen Teams sowohl technische wie auch organisatorische Herausforderungen in Angriff nehmen. Der Autor und Kollegen haben hierzu etablierte Praktiken gesammelt, die sie iterativ einsetzen. Dieses Verfahren nennen sie „Architecture Improvement Method“, kurz „aim42“ [1][2], und veröffentlichen es als Open Source. Da Entwicklungsteams die Vielzahl von Problemen kaum alleine bewältigen können, richtet sich diese Initiative sowohl an technische wie auch an betriebswirtschaftliche Stakeholder. aim42 schlägt dazu ein iteratives Vorgehen in drei Phasen vor, die sich nahtlos in bestehende Entwicklungsprozesse integrieren lassen.

Ein erster Überblick

aim42 erfindet keine neuen Ideen, sondern bindet bestehende Praktiken in ein definiertes Vorgehen ein. Dabei bewähren sich die drei Phasen, die Bild 1 zeigt: analyze, evaluate, improve. Dabei gehen Sie so vor:

Bild 1: Die drei Phasen (Kreis) beim aim42-Prozess
Bild 1: Die drei Phasen (Kreis) beim aim42-Prozess

Kosten schätzen hilft!

Bis auf das vermeintlich lästige Schätzen von Kosten klingt dies sicher logisch. Warum aber sollen sich Entwickler beim Verbessern von Systemen ausgiebig mit Geld und Kosten beschäftigen? Der Grund ist das Unverständnis fachlicher oder betriebswirtschaftlicher Stakeholder für eher technische oder methodische Argumentation: Für „lose Kopplung“, „hohe Kohäsion“ oder „verbesserte Modularisierung“ mag kein Fachbereich und kaum ein Projektleiter Geld bereitstellen. Werden allerdings die tatsächlichen Kosten der vorhandenen Probleme offengelegt, wie aim42 es ausdrücklich fordert, erleichtert dies die Kommunikation mit Budget- oder fachlich Verantwortlichen. Dann müssen Softwareentwickler und -architekten endlich nicht mehr über die schwer vermittelbaren inneren Qualitäten, Kopplung, Kohäsion oder Implementierungsdetails streiten, sondern können in der universellen Sprache von Business-Experten argumentieren: Geld.

Problem, Ursache, Maßnahme

Nach Erfahrung des Autors stürzen sich Entwicklungsteams zu oft auf scheinbar offensichtliche Lösungsansätze, ohne zuvor angemessen über Alternativen und Konsequenzen nachzudenken.

Bild 2 stellt die Zusammenhänge der Begriffe dar, mit denen aim42 arbeitet. „Issue“ ist ein freundliches Wort für ein beliebiges Problem: Es verursacht Kosten (Cost of Problem) und könnte Symptom einer Ursache (Cause) sein.

Bild 2: Die Terminologie von aim42
Bild 2: Die Terminologie von aim42

Zu einem Problem gibt es eine oder mehrere verschiedene Maßnahmen, die es lösen (Improvement), wie Bild 3 nahelegt. Jede dieser Maßnahmen adressiert möglicherweise mehrere Issues. Natürlich kostet es etwas, eine Lösung umzusetzen (Cost of Improvement).

Damit stehen Probleme und Lösungen in einem bestimmen Verhältnis zueinander. Das allein wäre nun nicht schlimm, wären da nicht noch die möglichen Wechselwirkungen von Verbesserungsmaßnahmen untereinander: Ein Entwickler hat beispielsweise durch Caching und Denormalisierung das Laufzeitverhalten seiner DB-Abfragen deutlich gesteigert, das vorherige Problem damit vielleicht sogar vollständig behoben. Leider ist dabei die Komplexität im Code deutlich gestiegen – was wiederum die Wartungs- und Änderungsfreundlichkeit des Systems verschlechtert.

So ist es mit vielen Maßnahmen, die beim Entwickeln getroffen werden: Sie führen zu negativen Konsequenzen an anderen, oftmals a priori nicht bekannten Stellen.

Bild 3: aim42 sammelt Probleme (Issues) und leitet folgerichtig daraus Maßnahmen (Improvements) ab
Bild 3: aim42 sammelt Probleme (Issues) und leitet folgerichtig daraus Maßnahmen (Improvements) ab

Analyze: Breitensuche

Nun zu den drei erwähnten zentralen Phasen, in die sich der Verbesserungsprozess einteilen lässt. Systematische Verbesserung sollte mit einer Bestandsaufnahme beginnen, um eine Übersicht der Situation, insbesondere der Probleme zu gewinnen. Dazu zählen natürlich die bekannten Fehler und „Workarounds“ aus dem Issue-Tracker, andererseits auch die Ergebnisse statischer Codeanalysen, also Abhängigkeiten, Komplexität, Einhalten von Codekonventionen, Testabdeckung und so weiter.

Zusätzlich ist es besonders wichtig, auch einmal die beteiligten Personen nach den aus ihrer Sicht wichtigen Problemen zu befragen. Die Kollegen wissen in der Regel viel über das System, seinen Aufbau und insbesondere die dazugehörigen Entwicklungs- und Betriebsprozesse. Die Erfahrung des Autors aus zahlreichen Analysen und Reviews zeigt, dass die Suche nach Problemen gleichzeitig eine Menge über deren Lösung lehren kann. Insbesondere in Gesprächen mit den beteiligten Stakeholdern kommen oft konkrete Vorschläge zur Sprache, wie sich die bestehende Situation verbessert ließe. Das sind gute Kandidaten für das „Improvement Backlog“.

aim42 hält eine Vielzahl von Praktiken bereit, um die Suche nach Problemen zu unterstützen; der Kasten „Beispiele für Analyze-Praktiken“ gibt einen Überblick.

Beispiele für Analyze-Praktiken

Die Analyze-Phase besteht aus einer breit angelegten Suche nach Problemen. Beginnen Sie mit einer Analyse der wesentlichen Stakeholder und der externen Schnittstellen des Systems. Untersuchen Sie Code, aber betrachten Sie auch weitere Qualitäten des Systems wie Sicherheit, Laufzeitverhalten oder Robustheit, siehe Bild 6.

Einige stichwortartige Beispiele der aim42-Praktiken zur Analyse vermitteln einen Eindruck, wie Sie Probleme finden können:

  • Stakeholder-Analyse
  • Kontextanalyse
  • Analyse des statischen Codes
  • Laufzeitanalyse
  • Analyse des Entwicklungsprozesses
  • Analyse der Dokumentation
  • qualitative Analyse (ATAM [6])
  • Sicherheitsanalyse
Die analyze-Phase ist von der breit angelegten Suche nach Problemen geprägt
Die analyze-Phase ist von der breit angelegten Suche nach Problemen geprägt

Evaluate: Kosten schätzen

Eingangs ging es bereits um die Schwierigkeiten, betriebswirtschaftlich orientierte Stakeholder von Verbesserungen der inneren Qualität von Software zu überzeugen. Da diese Änderungen nur selten direkt „von außen“ wahrnehmbar sind, mangelt es im Management oft an Verständnis.

Vergleichen Sie also systematisch Probleme und Lösungen, indem Sie deren betriebswirtschaftliche Werte schätzen, etwa in Euro oder in Aufwandsgrößen. Auf diese Weise können Sie Probleme und mögliche Maßnahmen priorisieren – und auch das Management wird diese Prioritäten gut verstehen. Der Erfahrung des Autors nach tun sich viele Entwickler mit dem Thema „Kosten schätzen“ sehr schwer, insbesondere bei den Kosten der Probleme (Issue Cost). Eine einfache Abhilfe ist das Schätzen in Intervallen (Minimum, Maximum), wobei die Breite des Intervalls die Unsicherheit der Schätzung ausdrückt: Große Intervalle drücken hohe Unsicherheit aus, enge Intervalle hohe Zuversicht. Bild 4 zeigt das Vorgehen schematisch. Sie erkennen darin die Kosten sowohl für Probleme wie auch für Maßnahmen.

Bild 4: Das Schätzen von Kostenintervallen zeigt, wo in einem Projekt die Unsicherheiten liegen
Bild 4: Das Schätzen von Kostenintervallen zeigt, wo in einem Projekt die Unsicherheiten liegen

Annahmen offenlegen

Bei Schätzungen sind zuerst die Einflussgrößen (Parameter) einer Schätzung zu ermitteln: Was und wer ist überhaupt betroffen? Legen Sie Ihre Annahmen darüber offen und bechaffen Sie sich im Zweifel die Ansichten anderer Stakeholder.

Ein Beispiel aus der Erfahrung des Autors: Ein Entwicklungsteam klagte über unsäglich lange Build-, Deploy-, und Testzyklen. Die Entwickler mussten für jeden Feature-Test zehn bis fünfzehn Minuten auf das Re-Deployment des Systems warten. Um die Kosten dieses Problems zu schätzen, waren zunächst mögliche Parameter zu sammeln:

Für das Team kamen bei geschätzten Personalkosten von 400 bis 800 Euro pro Tag „Problemkosten“ (Cost of Problem) von 2000 bis 8000 Euro täglich zusammen. Das Management hatte das zugrunde liegende Problem lange Zeit als Luxusproblem der Entwickler abgetan. Doch nach der Schätzung stellte es plötzlich auch ein Budget für Verbesserungen zur Verfügung (hier: Anschaffung von Lizenzen für ein Hot-Code-Replace-Framework, das die Build-/Deploy-/Testzyklen in der Entwicklung auf unter drei Minuten gesenkt hat). Die teuren Lizenzkosten hatten sich innerhalb einer einzigen Woche amortisiert.

Sie sollten jetzt für einige Ihrer gravierenden oder größeren Probleme jeweils eine (Intervall-)Schätzung der Problemkosten haben – und diese mit dem Management, zum Beispiel den Product Owner, diskutieren.

Improve: Probleme angehen

In der Improve-Phase von aim42 geht Sie ein oder mehrere Probleme mit konkreten Maßnahmen an. Das ist für die meisten Entwickler der interessanteste Teil, weil es um die Umsetzung konkreter, oft technischer Dinge geht.

Allerdings ist auch das Verbessern selbst in der Praxis oft schwierig, weil das leidige Tagesgeschäft ja ebenfalls erledigt werden muss. Die Krux der Verbesserung liegt also darin, die notwendigen Maßnahmen mit den Notwendigkeiten des Entwicklungsalltags so zu verzahnen, dass sich in beiden Bereichen ein deutlicher Fortschritt ergibt. Der Autor hat Teams erlebt, die beispielsweise 10 bis 20 Prozent der Scrum-Sprints für reine Verbesserungsmaßnahmen reserviert hatten und damit auf längere Sicht ziemlich gute Resultate erzielten.

aim42 differenziert die Improve-Phase in kurzfristige Praktiken und langfristige Ansätze (siehe Bild 5) – man könnte es auch taktische oder strategische Ansätze nennen. Zusätzlich formuliert aim42 noch einige Grundprinzipien, die analog zu den klassischen Entwurfsprinzipien (lose Kopplung, geringe Komplexität, hohe Kohäsion und so weiter) stets gelten sollten, die an dieser Stelle aber keine Rolle spielen.

Bild 5: Kurzfristige Praktiken und langfristige Ansätze bilden die Improve-Phase
Bild 5: Kurzfristige Praktiken und langfristige Ansätze bilden die Improve-Phase

Taktische Praktiken

Zuerst ein kurzer Blick auf die kurzfristigen Verbesserungsansätze: aim42 führt auch hier wiederum Kategorien zur Strukturierung ein. Einige Beispiele:

Strategische Planung: Approaches

Manche Verbesserungen lassen sich nur durch langfristige Umbauten, die im großen Stil angegangen werden, erreichen. Auch dafür hält aim42 Praktiken bereit. Der Autor warnt aufgrund vieler Risiken vor einem Neuschreiben des Codes von Grund auf, sozusagen einem „Big Bang“ (siehe dazu Joel Spolsky [3]), aber es geht zum Glück auch anders. Einige Beispiele:

Es gibt noch weitere Praktiken (zum Beispiel Keep Data, Toss Code, Chicken Little, Butterfly) und wahrscheinlich werden Sie für Ihre Organisation und das System eine spezifische Strategie entwickeln müssen. Die genannten Ansätze haben dem Autor zumindest öfter als Gedankenanstöße geholfen.

Fazit

Eine systematische Verbesserung von Softwaresystemen funktioniert auch unter Zeitdruck und sogar mit wenig Budget. Eine methodische Vorbereitung, Iteration und die Übersetzung von Problemen in betriebswirtschaftliche Größen (also Geld) können dabei helfen. Der Open-Source-Ansatz aim42 berücksichtigt dies und bündelt eine Vielzahl etablierter Praktiken, aus denen Sie sich auch für Ihre Systeme und Situationen frei bedienen können.

Verbessern von Architektur und Code

Die wohl umfangreichste Sammlung konkreter Praktiken in aim42 gehört zu den Verbesserungsvorschlägen für Code und Architektur, siehe Bild 7. Sie finden hier neben den klassischen Refaktorisierungsansätzen auch Ansätze zur verbesserten Modularisierung sowie zur Optimierung querschnittlicher Konzepte. Hier einige Beispiele:

Prepare Change: Bereiten Sie Code auf Umbauten vor, etwa durch automatisierte Tests oder durch interne Schnittstellen. Extract Domain Model: Manchmal ist die Fachlichkeit (Domäne) von Systemen durch technische Bausteine, etwa Schichten oder Layer, verborgen. Machen Sie das Domänenmodel sichtbar, separieren Sie Entities, Dienste oder andere fachliche Bestandteile von technischen Teilen. Improve Consistency: Viele IT-Systeme lösen wiederkehrende Probleme auf viele unterschiedliche Arten und sind deswegen insgesamt schwer verständlich und schwer zu ändern. Vereinheitlichen Sie solche Konzepte. Verbessern Sie die konzeptionelle Integrität, sodass der Code danach wirkt, als wäre er aus einem Guss. Improve better Technology: Teilweise verwenden Systeme Infrastrukturen oder Frameworks nur noch aus historischen Gründen, obwohl es inzwischen bessere Alternativen gibt. Entledigen Sie sich dieser Altlasten.

Sie finden in Bild 7 außerdem die Kategorie Restructure Code. Dahinter verbirgt sich wiederum eine Vielzahl von Praktiken im Sinne von Refactoring oder Restrukturierung, etwa Introduce Interfaces, Extract Component, Hide unmaintainable Code, Anticorruption Layer, Remove unused Parts, Deprecate obsolete Parts und weitere.

Bild 7: An Verbesserungsvorschlägen bietet aim42 ein umfangreiches Arsena
Bild 7: An Verbesserungsvorschlägen bietet aim42 ein umfangreiches Arsena

Links & Literatur

  1. http://aim42.org/  ↩

  2. https://github.com/aim42/  ↩

  3. Joel Spolsky: Things You Should Never Do, Part 1  ↩

  4. Murer, Bonati, Furrer: Managed Evolution. A Strategy for Very Large Information Systems,ISBN 978–3–642–01632–5  ↩

  5. Paul Hammant: Legacy Application Strangulation – Case Studies  ↩