Skalierbarkeit als Gläserne Decke in der Agilität

Erstellt am 1. April 2011 von Ralfwestphal @ralfw

Agile Softwareentwicklung fokussiert sich auf verlässliche Lieferung von Nutzen. Je schneller sie den liefert, desto besser. Meistens. Die Frage ist nur, wie die Geschwindigkeit erhöht werden kann. Wie skaliert Softwareproduktion?

Skalieren ganz allgemein

Skalieren oder skalierbar sein heißt, auf mehr Bedarf so reagieren zu können, das er gedeckt wird. Wenn ein Website normalerweise 10 Transaktionen in der Sekunde verarbeitet, zu Weihnachten aber 1000 Transaktionen pro Sekunde anfallen würden, die Technik die jedoch nicht verarbeiten kann, dann skaliert der Website schlecht.

Einen Produktionsschritt wie “Transaktion verarbeiten” oder “Supportanfrage beantworten” oder “Briefe zustellen” können Sie skalieren, indem Sie die Ausführung beschleunigen (scale-up) oder mehr Ressourcen für die Ausführung bereitstellen (scale-out).

Supporter könnten schneller sprechen oder weniger lange überlegen müssen für eine Antwort, Briefzusteller könnten schneller radeln oder weniger mit Passanten plaudern. Beides würde die jeweiligen Produktionsschritte beschleunigen, so dass in derselben Zeit mehr Anfragen beantwortet oder mehr Briefe zugestellt würden.

Oder der steigende Bedarf wird auf mehr Ressourcen verteilt; die Supporter und Briefträger werden nicht schneller, aber es gibt einfach mehr. Wenn 1000 Briefe nicht mehr von einem, sondern 10 Briefträgern zugestellt werden, dann braucht das sicherlich nur noch ein zehntel der Zeit.

Skalieren durch scale-up (Aufbau) ist eigentlich immer grundsätzlich möglich. Bessere Ressourcen schaffen einfach mehr weg.

Skalieren durch scale-out (Ausbau) ist jedoch nicht immer möglich. Manche Tätigkeiten lassen sich nicht auf mehr Ressourcen verteilen. Einen Roman zu schreiben, lässt sich z.B. nicht dadurch beschleunigen, dass man 5 Autoren damit beschäftigt statt einem.

Was nicht heißt, dass man die Romanproduktion nicht mit mehr Ressourcen beschleunigen könnte. Die “Produktionswerkstatt” von Ken Follett macht es vor.

Daraus folgt, dass es noch einen weiteren Weg gibt, zu skalieren: Fokussierung. Ressourcen schaffen mehr, wenn sie sich auf ihre eigentliche Tätigkeit besser konzentrieren können.

Ich nenne das mal scale-in, um auszudrücken, dass hierfür eine Wendung nach innen, eine Besinnung auf das Wesentliche nötig ist.

Die Softwareproduktion skalieren

Auf die Softwareentwicklung als Produktionsprozess lassen sich die Skalierungsmuster natürlich übertragen.

Was tun, um mehr “Packerl” zu produzieren? Wenn der Bedarf steigt, dann müssen die Kaufwilligen befriedigt werden. Jeder Kunde bekommt ein “Packerl”. Natürlich müssen diese “Packerl” nicht alle gleich aussehen. Der erste Kunde kann als “Packerl” die Softwareversion 1.0.0.0 bekommen, der nächste die Version 1.0.0.1, der übernächste ebenfalls 1.0.0.1, der vierte 1.0.0.2 usw. Manche Kunden bekommen einfach die aktuelle Version, für andere wird speziell ein Feature eingebaut, ohne das sie nicht kaufen würden.

Nochmal: Wie kann die Softwareproduktion eine steigende Nachfrage befriedigen? Auf dieser Abstraktionsebene kann die Antwort nur lauten: scale-up. Die Softwareproduktion als ganzes muss schneller werden. Sie muss neue Wünsche schneller in “Packerl” transformieren oder sie muss einfach nur mehr “Packerl” hinten rausschieben (also Kunden mit einer existierenden Softwareversion befriedigen).

Und wie kann die Softwareproduktion als Ganzes schneller werden? Keine Ahnung. Für eine Antwort ist mehr Detail nötig. Wie funktioniert die Produktion im Einzelnen?

Jetzt gibt es Ansatzpunkte. Zum Beispiel könnte der Vertrieb beschleunigt werden, am ehesten wohl durch scale-out. Aber das lohnt natürlich nur, wenn es genug zu verkaufen gibt, d.h. die Softwareentwicklung mehr liefert als bisher in den existierenden Bedarf hinein abgesetzt werden konnte.

Wenn die das aber nicht tut, wenn sie der Engpass ist, wie könnte die Softwareentwicklung skalieren?

Die Softwareentwicklung skalieren

Mein Gefühl ist, dass Unternehmen sich mit der Skalierung der Softwareentwicklung schwer tun. Sie erkennen sie zwar als Engpass – doch sie reagieren unangemessen.

Kann nicht sein – Scale-in

Das die Softwareentwicklung skalieren könnte, dass sie mehr Kapazität hätte und schneller wäre, wenn sie sich denn mehr auf ihr eigentlichen Geschäft konzentrieren könnte, das haben viele Entscheider nicht im Blick. Es kann doch nicht sein, dass die Softwareentwicklung heute etwas Kontraproduktives tut; alles, was sie tut, muss sie tun. Das ist nötig. Support durch Softwareentwickler muss sein. Teilnahme an vielen Besprechungen muss sein. Statusreports und Timetracking muss sein. Dokumentationen müssen gepflegt werden.

Da ist einfach kein Fett, was weggeschnitten werden könnte.

So sehen es viele Entscheider und können also nicht denken, dass ein scale-in hilfreich wäre.

Allerdings denken Sie das, wenn ein Training oder andere Fortbildungsmaßnahme vorgeschlagen wird. Da haben sie das Gefühl, dass das etwas Unnötiges ist.

Darf nicht sein – Scale-up

Wo jedoch Fortbildung (oder gar Ausbildung) fehlt, da kann auch kein scale-up stattfinden. Denn nur durch Lernen kann die Softwareentwicklung mit den gegebenen Ressourcen ja schneller werden. Das kostet zwar erstmal Zeit, doch dann wird noch mehr Zeit gespart.

Flüssigere Technologiebedienung, bessere Prozesse, geschmeidigere Kommunikation: all das kann man lernen, all das bringt höhere Produktivität. Doch das kostet Zeit und Geld. Also sind Entscheider, die in der “Kostendenke” stecken, sehr unwillig, scale-up-Maßnahmen zu bewilligen.

Muss sein – Scale-out

So bleibt denn nur ein scale-out, um die Softwareentwicklung zu beschleunigen. Die Softwareentwicklung muss sozusagen multipliziert werden:

Das bedeutet, die Anforderungen werden von mehreren “Entwicklungsinstanzen” parallel bearbeitet.

Hört sich plausibel an, oder? Entspricht auch der Sichtweise auf Software. Die wird nämlich meist als ein Ganzes, als ein Programm, eine Anwendung so gesehen, wie der Auftraggeber sie ordert.

“Entwickeln Sie für uns eine Faktura!” – also kommt am Ende eine EXE (mit ein paar DLLs) heraus.

Dasselbe Spiel bei einer AVA-Software, einer Warenwirtschaft, einer Branchensoftware für den Rolladen- und Jalousiebau… der Markt will eine Lösung, also wird eine EXE produziert.

Die Erfüllung des Kundenwunsches hängt von einer Anwendung ab. Die wiederum hängt davon ab, dass alle Anforderungen erfüllt werden. Und die hängen davon ab, dass sie in einer EXE (mit zugehörigen DLLs) platziert werden.

Scale-out als Gläserne Decke

Die Softwareentwicklung mit scale-out zu beschleunigen, hört sich plausibel an, oder? In jedem Fall ist das das übliche Vorgehen. Wo 5 Entwickler sind, da werden 5 Anforderungen (Features) gleichzeitig in Angriff genommen. Na, vielleicht 4, denn manchmal ist eine Anforderung so schwierig umzusetzen, dass sich besser zwei Entwickler darum kümmern.

In jedem Fall wird bei Produktionsengpässen in der Softwareentwicklung reflexhaft zu scale-out gegriffen. Damit scheinen alle Probleme gelöst. Erstens kann man so alle Entwickler auslasten. Zweitens geht es doch so am schnellsten voran. Oder? Drittens kann man das quasi aus dem Stand. Und umso besser, je mehr Anforderungen schon vorliegen. Man muss dann nur noch ein paar mehr Entwickler dran setzen. Am besten solche, die billiger sind.

Leider entstehen die erwarteten Vorteile dabei – wenn überhaupt – nur kurzfristig. Scale-out auf der Basis von Anforderungen führt nämlich zu einigen Problemen:

Problem #1: Konflikte

Anforderungen sind Durchstiche. Für jede Anforderung muss daher potenziell an allen Schichten einer Codebasis geändert werden. Das kann zu Konflikten führen. Das können physische Konflikte in den Quelldateien sein, die ein Versionskontrollsystem anzeigt. Das können aber auch noch schlimmere Konflikte bei logischen Abhängigkeiten sein.

Problem #2: Verzahnung

Wo Anforderungen parallel umgesetzt werden ohne nähere Planung - Warum sollte es die auch geben, denn ein scale-out auf dieser Ebene soll sie ja gerade vermeiden? Wer mehr plante, der müsste kein scale-out nach Anforderungen betreiben. – da entstehen schnell viele Abhängigkeiten im Code. Code der einen Anforderung nimmt Bezug auf Code, der von einer anderen stammt, weil zwischen beiden ja keine Barriere existiert. Entwickler, die auf Anforderungen konzentriert sind, durchforsten die gesamte Codebasis nach hilfreicher, schon existierer Funktionalität und binden sich daran.

Problem #3: Geringe Geschwindigkeit

Jede Anforderung wird nur von einem Entwickler bearbeitet. Der mag das zwar so schnell tun, wie er kann, doch auf das Gesamtsystem gesehen, ist das nicht die maximale Geschwindigkeit. Bei 5 Entwicklern wird jede Anforderung nur mit 20% der Kapazität bearbeitet. Ihre Umsetzung dauert also 5 mal so lange wie (theoretisch) nötig.

Anforderungen parallel in einem Team bearbeiten entspricht Multithreading-Code. Mehrere Threads im Hintergrund nehmen dem Vordergrundthread Arbeit ab; der friert nicht ein. Doch dafür werden die einzelnen Aufgaben nicht mit maximaler Geschwindigkeit bearbeitet. Der Nutzen: es wird Latenz verborgen.

Ist das aber, was Softwareentwicklung soll? Soll sie möglichst schnell mit vielen Aufgaben beginnen, um den Kunden (oder die Anforderungsdefinition) wieder frei zu geben für anderes Kaum.

Softwareentwicklung soll vielmehr jede Anforderung so schnell wie möglich umsetzen. Erstens, um dem Kunden möglichst schnell Nutzen zu bieten. Es geht also nicht um Entlastung von upstream Produktionsschritten, sondern um Bedienung von downstream Produktionsschritten bzw. des Marktes.

Zweitens um so schnell wie möglich Feedback darüber zu bekommen, ob überhaupt erfolgreich umgesetzt wurde. Denn das wissen wir ja: Nur weil irgendwo Anforderungen stehen, kommt am Ende nicht unbedingt Code heraus, der Gefallen beim Kunden findet. Also muss die Softwareentwicklung daran interessiert sein, mit höchster Geschwindigkeit zu jeder Anforderung Feedback zu generieren. Latenz ist mithin nicht zu verbergen, sondern zu reduzieren.

Problem #4: Hoher WIP

Jede Anforderung wird also nur mit ein Anteil von 1/n bei n Ressourcen umgesetzt. Das heißt, jede Anforderung verweilt sehr lange in der Softwareentwicklung. Immer sind also viele verschiedene Anforderungen in Produktion (work in progress, WIP).

Ob diese Produktion ein Erfolg ist und Geld bringt, stellt sich allerdings erst am Ende heraus, wenn der Kunde sie abgenommen hat. Viele Anforderungen gleichzeitig zu bearbeiten, ist zwar sehr geschäftig, verdient an sich jedoch kein Geld, sondern kostet erstmal nur welches.

Jede Anforderung, die begonnen, jedoch noch nicht fertiggestellt und abgenommen ist, kann potenziell Geld verbrennen. Deshalb ist der WIP zu minimieren. Am besten ist der WIP sogar 1.

Bis eine Anforderung fertiggestellt und abgenommen ist, ist sie auf Halde produziert. Sie ist im System und kostet gerade Geld, weil an ihr gearbeitet wird. Oder sie liegt fertig herum, ohne abgenommen worden zu sein und hat damit Geld gekostet. In beiden Fällen ist es ungewiss, ob der ganze Aufwand gelohnt hat; Kapital ist in ihr gebunden. Das ist betriebswirtschaftlicher Quatsch.

Ob es in besonderen Fällen betriebswirtschaftlich günstig sein kann, Anforderungen auf Halde zu produzieren, um einen Puffer zu haben für nachfolgende Produktionsschritte, lasse ich mal außen vor. Darüber kann man reden. Ich glaube nur nicht, dass daran jeman denkt, der scale-out für die Softwareentwicklung anordnet.

Grenze für die Agilität

Wenn Agilität schnell Kundennutzen herstellen will, wenn Agilität daran glaubt, dass häufiges Feedback nötig ist, um zufriedenstellende Software zu entwickeln, dann kann scale-out nicht der richtige Weg sein.

Scale-out auf Anforderungsebene widerspricht der Agilität oder begrenzt sie zumindest. Das heißt, wer Scrum o.ä. einführt in der Hoffnung, nun endlich maximal schnell Software zu produzieren, der lügt sich in die Tasche, solange er die Features im Sprint parallel entwickeln lässt.

Zu einem agilen Vorgehen muss also noch mehr kommen, um das Ziel der Agilität wirklich zu erreichen. Das geht nur, wenn jede Anforderung mit maximal möglicher Geschwindigkeit bearbeitet wird und der WIP minimal ist.

Architektur erhöht Teamskalierbarkeit

Ich verstehe, dass scale-out so verführerisch ist. Es scheint einfacher zu implementieren zu sein als scale-up oder scale-in. Bei scale-up und scale-in geht es ans Eingemachte, an die Kultur eines Unternehmens. Bei scale-out kann (scheinbar) alles/viel mehr beim Alten bleiben. Deshalb ist als erstes zu fragen, ob scale-out nicht doch irgendwie möglich ist?

Aus meiner Sicht lautet die Antwort ja. Scale-out ist möglich, wenn man ein wenig Architektur betreibt. Statt nämlich die Anforderungen des Kunden einfach nur in eine Anwendung umzusetzen, sollte überlegt werden, wie daraus mehrere Anwendungen werden können.

Die Zerlegung eines großen Wunschkonvolutes kann im Rahmen der architektonischen Planung über die Zerlegungsebenen Bounded Context und Partition/App geschehen. Jede App steht dann für eine EXE, die einer Nutzerrolle dient.

Mit scale-out kann dann gleichzeitig an Anforderungen verschiedener Apps gearbeitet werden. Das macht einen gewissen Sinn, weil die Zielgruppen verschieden sind. Gegenüber jeder Zielgruppe beginnt die Arbeit an einer Anforderung also möglichst schnell; die Latenz zu verbergen schafft Zufriedenheit.

Dass die Umsetzung der Anforderungen dann immer noch langsam ist, ist nicht so schlimm (Problem #3), denn die Probleme #1, #2 und #4 verschwinden. Ja, selbst #4 verschwindet, weil WIP pro Anwendung gerechnet werden kann, da die Abnahme pro Anwendung erfolgt.

Der Agilität ist damit durchaus Genüge getan. Pro App wird maximal schnell gearbeitet und Feedback eingeholt. Gleichzeitig kommt aber auch das Gesamtsystem voran.

Eine Zerlegung des großen Ganzen in Bounded Contexts und Apps bringt aber nicht nur für die Skalierbarkeit des Teams Vorteile. Auch die Evolvierbarkeit und die Usability steigen.

A little architecture can go a long way ;-)

Arbeitsorganisation erhöht Teamskalierbarkeit

Was aber, wenn sich das Ganze nicht gut in Apps zerlegen lässt? Oder was, wenn es weniger Apps als Entwickler gibt?

Für noch mehr scale-out Effekt reicht es nicht, die Anforderungen in Apps zu gruppieren. Wirklich höchste Geschwindigkeit pro Anforderung erreicht die Softwareentwicklung nur, wenn sie alle Entwickler (soweit sinnvoll) an eine Anforderung setzt. WIP=1 und Minimierung der Latenz sollten im Sinne agiler Softwareentwicklung das Ziel sein.

Das lässt sich erreichen durch Zerlegung der Anforderungen in Aufgaben. Soweit allerdings nur ein erster Schritt. Probleme #3 und #4 mögen damit gelöst sein. Um jedoch auch noch #1 und #2 in den Griff zu bekommen, ist als zweiter Schritt Komponentenorientierung unverzichtbar.

Mit Komponenten können alle Entwickler ungestört an ihren Aufgaben arbeiten. Ob dann ein Entwickler immer in einer Komponente Aufgaben umsetzt oder nur Aufgaben für eine App realisiert, das sei dahingestellt. Hier ist nur wichtig, dass komponentenorientierte Aufgaben der Schlüssel zu maximaler Teamperformance ist.

Nur mit Komponenten lassen sich Anforderungen echt parallel realisieren, um Kunden schnellstmöglichen Nutzen zu bieten und von ihnen Feedback zu bekommen. Ohne Komponenten stoßen Teams an eine gläserne Decke bei der Skalierbarkeit.

Mit Komponenten jedoch bekommt die Softwareentwicklung nicht nur echtes scale-out Potenzial, sondern macht den Code einfacher testbar, erhöht die Evolvierbarkeit und hat bessere Chancen auf Wiederverwendung von Funktionseinheiten.

Aber das bedeutet natürlich nicht, dass deshalb scale-up und scale-in vernachlässigt werden sollten. Auch da gilt es Potenzial zu aktivieren, um schneller und kostengünstiger Software produzieren zu können.