Große Softwareprojekte und Lernen
23.06.2010 Permalink Die halbe Wahrheit ist: ein Softwareprojekt erzeugt ein Softwareprodukt. Die andere Hälfte ist: notwendigerweise entsteht dazu immer eine Projektorganisation, also eine Struktur aus Rollen und Teams und den Prozessen, die von Mitarbeitern ausgeführt werden, damit am Ende ein auslieferfähiges Release entsteht. Große Softwareprojekte sind komplex, und folgerichtig ist auch die Organisation komplex. Außerdem sind Softwareprojekte per Definition einzigartig, jedes Projekt "erfindet" also seine individuelle Projektorganisation, obwohl es Ähnlichkeiten gibt.Einzigartig und Komplex. Das klingt nicht danach, als würden die beteiligten Menschen sofort alles richtig machen können. Und daher ist es keine Überraschung, dass kaum ein Drittel aller Softwareprojekte, die der CHAOS Report 2009 der Standish Group untersucht, die ursprünglichen Ziele trifft. Alle anderen Projekte verpassen die Ziele oder erbringen gar kein nutzbares Ergebnis. Die Ursachen von Schwierigkeiten entstammen der Gemengelage aus Zeit- und Kostendruck, unklarer oder unrealistischer Zielsetzung, sich ändernden Rahmenbedingungen, mangelndem Rückhalt in der durchführenden Organisation oder auch Qualifikationsdefiziten der beteiligten Projektmitarbeiter.
Fakt ist: diese Gemengelage existiert schon lange, und wir beklagen sie, aber sie wird auch in der Zukunft immer bleiben. Wir -- als Softwareingenieure -- können mit dem Finger auf andere zeigen und behaupten: unter diesen Bedingungen kann man keinen Erfolg haben. Aber ändern wird sich dadurch nichts.
Nehmen wir es daher hin: große Softwareprojekte sind riskant, weil sie in widriger Umgebung starten, schwierig zu organisieren sind, und praktisch niemand der Beteiligten mit diesem individuellen Vorhaben Erfahrung hat, denn ein Projekt ist eine einmalige Angelegenheit. Aber wir sind dieser Situation nicht ausgeliefert, ganz und gar nicht. Sie entspricht grundsätzlich all jenen Situationen, in denen wir lernen müssen. Und da Menschen zumindest in ihren jungen Jahren ständig lernen, besitzen wir alle längst die Schlüsselqualifikation, um große Projekte in den Griff zu kriegen.
Wie funktioniert praktisches Lernen? In meinen eigenen Worten etwa so:
- Begreifen, was wir wollen
- Abgucken, wie andere dort hinkommen
- Selbst handeln
- Vergleichen unseres Ergebnis mit unserem Ziel
- Verändern unserer Handlungsidee, damit's beim nächsten Mal besser klappt
- Wiederholen
Bis hierher habe ich nur eine abstrakte Idee genannt, was auch große Projekte beherrschbar macht. Ich möchte nun mit ein paar Beispielen zeigen, wie konkrete Rückkopplungen aussehen und wirken:
Schätzungen und Ist-Aufwandserfassung
Aufwandsschätzungen, die auf Basis einer Grobbeschreibung eines künftigen
Softwaresystems entstehen, besitzen eine Genauigkeit von
[0,25;4], mit anderen Worten: jede von
einem Entscheider akzeptierte Aufwandszahl ist mit extremer Unsicherheit
behaftet. Man könnte auch sagen: wir wissen nicht, wie teuer es wird. Zum Teil
rührt diese Unsicherheit aus all den in dieser frühen Phase noch nicht
getroffenen Entscheidungen her, zum Teil aber auch, weil das Team seine
Produktivität, d.h. wieviel nutzbare Funktionalität pro PT herausspringt,
nicht kennt. Unterschiedliche Teams sind unterschiedlich produktiv, sehr
schlechte Teams verbrauchen ca.
fünfmal mehr Aufwand
als sehr gute. Um eine vernünftige
Idee zu bekommen, ob ein Budget reicht, muss das Team früh eine
Teilfunktionalität schätzen, erstellen, den tatsächlichen Aufwand festhalten
und auf dieser Datenbasis die Budgethöhe plausibilisieren. Diese Rückkopplung
kann sehr viel Geld sparen, wenn man z.B. durch sie feststellt, dass der
Business Case nicht mehr aufgeht. Läuft das Projekt weiter, so lernt das Team
mit dieser Rückkopplung, besser zu schätzen. Das Projekt wird vorhersagbar.
Benutzertests
Wenige Softwareentwickler haben ein Talent, Benutzerschnittstellen so zu
bauen, dass Nicht-Technik-Verliebte sie als intuitiv bedienbar empfinden. Hat
man eine große Zahl von Benutzern als Zielgruppe für ein Softwaresystem, so
ist Benutzertauglichkeit kritisch: lehnen die Benutzer die Software ab, droht
dem System das frühe Aus. Das Team muss also lernen, wie eine gute UI
aussieht, und dazu braucht es als Rückkopplung Benutzertests. Und zwar sehr
früh, denn UI-Entwicklung ist erstaunlich aufwändig und mit UI-Prototypen
findet man nicht selten wesentliche Anforderungen an das System, die sonst
übersehen würden. Wartet man zwei bis drei Iterationen, bis genügend
Funktionalität durch Benutzer erreichbar ist, hat man vielleicht wertvolle
Zeit verschenkt.
Continuous Integration
Große Software besteht aus vielen tausend Artefakten, von denen einige wenige
eng mit der Arbeitsumgebung des Entwicklers verknüpft sind. Ein Entwickler
kann sicherstellen, dass die Funktionalität, die er überblickt, auch nach
seiner Codeänderung in seiner Umgebung in Ordnung ist, aber er kann kaum
umfassend garantieren, dass nach seinem Checkin sämtliche Funktionalität auch
in einer vollkommen unabhängigen Umgebung vorhanden ist.
Continuous Integration
hilft: hat sich etwas im Versionskontrollsystem geändert, dann wird das System
wenige Minuten später vollständig gebaut und automatisiert getestet, und zwar
in einer eigenständigen Umgebung. Fällt hierbei ein Fehler auf, wird der
Entwickler automatisch informiert. Diese Rückkopplung erfolgt in weniger als
einer Stunde, und der Entwickler kann ohne Rüstzeit die Fehlerbeseitigung
vornehmen.
Frühe Lasttests
Ob ein System der Last im Wirkbetrieb gewachsen ist, kann man nur spät auf
einer wirkbetriebsnahen Testumgebung feststellen. Es gibt allerdings eine
ganze Reihe von Architekturschwächen und Programmierfehlern, die sich erst
unter Last bemerkbar machen, aber sehr viel früher aufzudecken sind. Da reicht
heute i.d.R. der PC des Entwicklers und ein OpenSource Lastgenerator (z.B.
JMeter), damit das Projekt früh lernt, wie
die Architektur verbessert werden muss. Diese Rückkopplung verhindert, dass
späte weitreichende Umbaumaßnahmen erforderlich werden, um das gewünschte
Skalierungsverhalten zu erzielen.
Ich könnte diese Beispielbeschreibungen fortsetzen, doch ich beschränke mich auf ein paar weitere Schlagworte zu Maßnahmen, die uns beim Lernen helfen: Code Reviews, Unittests, Softwaremetriken, Lessons Learned Meetings, Feedbackgespräche unter vier Augen, kurze Releasezyklen, System- und Integrationstests, Security Audits, Architekturdurchstich, Laufzeitmonitoring, ja selbst so etwas Selbstverständliches wie ein Compiler erzeugt laufend Rückkopplungen Richtung Entwickler.
Nur wenige Maßnahmen sind an ein Iterationsende gebunden, manches kann als fester Prozessschritt eingeführt, anderes als Einzelaufgabe behandelt oder gar durch geeignete Werkzeuge automatisiert werden. Als Projektleiter habe ich eine Ahnung, wo die Fallstricke liegen können, doch erst die konkreten Rückkopplungen retten mein Team vor dem Unfall.
Große Softwareprojekte sind schwierig, aber nicht unbeherrschbar. In jedem einzelnen muss das Team erst lernen, es zu beherrschen. Das Team muss sich also die Frage stellen, wie es effizient lernen kann. Und das wichtigste Mittel dazu sind gezielt gesetzte Rückkopplungen.