Mittwoch, 20. August 2014

Konstruktivistische Softwareentwicklung für mehr Wandelbarkeit

imageCode sei ein Mittel, um die Realität abzubilden. Zumindest scheint mir das ein wesentlicher Antrieb hinter der Objektorientierung zu sein. Mit Objekten sollte es endlich möglich sein, Dinge und Verhältnisse der Welt möglichst 1:1 in Code zu fassen.

Das ist eine platonische Sichtweise der Welt. Sie geht davon aus, dass es etwas unabhängig von Code gibt, das irgendwie ist. Und dieses So-sein kann man mehr oder weniger getreu in Code abbilden. Und je getreuer es abgebildet wird, desto besser ist das für die Software in irgendeiner Weise.

Ich glaube, dieses Weltbild sollten wir nun hinter uns lassen. Es hat uns zu der Software geführt, die wir haben. Die funktioniert, die skaliert - aber die ist nur schwer wandelbar.

Vom Platonismus sollten wir zum Konstruktivismus wechseln.

imageWenn wir konstruktivistisch Software entwickeln, dann ist es nicht mehr wichtig, eine Realität getreu abzubilden.

Bei der platonischen Softwareentwicklung gibt es drei Bereiche, die in Deckung sind: die Realität (Domäne), unsere Wahrnehmung der Realität (Entwickler), Code. Als Entwickler einer Buchhaltungssoftware sehe ich eine Rechnung (Domäne) und lege dafür eine Klasse Rechnung und eine RDBMS-Tabelle Rechnungen an.

Bei der konstruktivistischen Softwareentwicklung hingegen, muss das, was ich als Entwickler in der Realität erkenne, nicht im Code auftauchen. Auch wenn ich eine Rechnung als Gegenstand in der Hand halte, führt das nicht Zwangsläufig zu einer Klasse oder einer einer Tabelle.

Leider muss ich hier von drei Bereichen sprechen, weil Software sich nicht selbst anpassen kann. Wir als Entwickler müssen das als Mittler tun. Deshalb haben wir bisher auch versucht, unsere Sicht der Welt in der Software zu manifestieren.

Aber es geht gar nicht um uns. Wenn wir für unser Überleben Rechnungen, Autos, Katzen, Götter, ein Ich in der Welt sehen wollen, dann ist das unsere Sache. Das ist unsere Konstruktion, die über das gelegt ist, was irgendwie ist.

imageDer Stoff aus dem die Konstruktionen sind, sind unsere sinnlichen Wahrnehmungen und a priori Grundkonzepte. Die haben wir uns nicht ausgesucht, sondern sie definieren uns. Die Evolution hat dazu geführt, dass wir als Organismen so sind, wie wir sind. Mit unserer Form und unseren Wahrnehmungen haben wir größere Stabilität in einer bestimmten Umwelt erreicht als mit einer anderen Form und anderen Wahrnehmungen.

So ist das mit Evolution. Es geht um größere Stabilität von Strukturen in einer (Um)Welt.

Und so ist es auch mit der Softwareevolution. Es geht darum, wie Software größere Stabilität erreicht in einer stetig im Wandel befindlichen Umwelt.

Wir haben es nun einige Jahrzehnte versucht, die Lebensfähigkeit durch getreuer Abbildung von durch uns wahrgenommener “dinglicher” Realität zu erhöhen. Das hat nicht so geklappt, wie gewünscht, würde ich sagen. Und nur das zählt.

Also sollten wir es anders versuchen. Befreien wir Software vom Abbildungszwang. Das einzige was zählt ist, dass Software als Ganzes ihren Zweck erfüllt (Funktionalität + Qualität) und sich zügig an eine gewandelte Umwelt anpassen lässt (Investitionssicherheit).

Die Struktur von Software muss also nicht zwangsläufig irgendetwas widerspiegeln, was wir als Menschen als Dinge in der Welt erkennen. Wenn wir ein Formular auf dem Tisch liegen haben, dann mag es noch hilfreich sein, das Formular in der Software als geDialog wiederzufinden. Ja, vielleicht ist das so. Vielleicht aber auch nicht. Machen wir uns da mal ganz locker.

Vor allem sollte uns ein Formular auf dem Tisch nicht dazu verleiten, unterhalb der Oberfläche im Code das Formular nochmal zu erschaffen. Und dann ein weiteres Mal auf der Festplatte - weder als Verbund von RDBMS-Tabelle noch als NoSql Dokument.

Damit will ich nicht sagen, dass das nicht so sein darf. Vielleicht ist es hier und da vorteilhaft, das Formular im Code wiederzufinden. Aber wir sollten das sich ergeben lassen und nicht im Sinne eines Weltbildes an den Anfang setzen.

Wenn wir schon mit dem Paradigma unserer Hauptwerkzeuge, den Programmiersprachen, Softwarestrukturen einem platonischen Weltbild unterwerfen, dann schränken wir die Freiheit der Evolution von Software ein. Wir machen es ihr schwer, in einer fluktuierenden Umwelt zu überleben, weil wir sie massiv fixieren.

“Abbildung der Realität” ist aber nicht, worum es geht. Einziger Markstein ist Zufriedenheit des Kunden - zu der gehört, dass Software quasi unsterblich ist, weil sie sich auf ewig anpassen lässt.

Natürlich haben wir wenig Erfahrung mit der Herstellung von Unsterblichen. Wer hat solche Erfahrung schon? ;-) In jedem Fall scheint mir jedoch ein schlechter Ausgangspunkt dafür, die Abbildung von objektbeladener Realität. Denn: Wenn sich diese Objekte in der Realität andauernd ändern, dann muss sich ja auch die Software andauernd ändern. Das umso häufiger und breiter, je tiefer die Objekte der Realität in der Software verankert sind.

Mir scheint, wir brauchen für evolvierbare Softwareentwicklung nicht mehr Objektorientierung, sondern das Gegenteil: Anti-Objektorientierung.

Java und C# und Ruby müssen wir deshalb nicht sofort auf den Müll werfen. Letztlich sind die Sprachen unschuldig. Auf den Müll muss das kontraproduktive platonische Weltbild. Denn das Weltbild steuert, wie wir die Sprachen einsetzen.

Mit einem neuen Weltbild können wir auch mit den überkommenen Werkzeugen durchaus neue, besser passende Strukturen schaffen. Konstruktivistische Softwareentwicklung ist mit C#, Java, Ruby, JavaScript, F# usw. möglich. Mal leichter, mal schwerer.

imageHören wir also auf, das Innen der Software so zu strukturieren, wie wir meinen, dass die dingliche Realität aussieht. In Ihrem Gehirn finden Sie den Computer nicht, auf den Sie schauen. Es darin auch nicht den Stuhl, auf dem Sie sitzen. Oder den Raum, in dem Sie sich befinden. Weder die Anatomie des Gehirns noch die Signale zwischen den anatomischen Strukturen haben irgendeine Ähnlichkeit mit der Umwelt. Innen ist nicht wie außen.

Allerdings befähigt Sie der Aufbau Ihres Gehirns (plus Körper), als Ganzes in der Umwelt zu überleben. Nur das ist es, was zählt.

Genau das müssen wir für Software auch erkennen. Ein erster Schritt: EventSourcing und EventStores.

Ein EventStore löst realweltliche Strukturen auf. Sie finden sich in der Software nicht mehr so wieder, wie wir sie als Entwickler in der Domäne gezeigt bekommen. Aber das ist nur der Anfang.

Ein nächster Schritt: Bounded Contexts und Aggregate.

Bounded Contexts und Aggregate lösen die Vorstellung von dem einen Datenmodell, von der einen Datenstrukturrealität auf.

Und noch ein Schritt: Inkrementelle Architektur. Das ist für mich die grundlegende Orientierung von Softwarestruktur an Durchstichen und Nutzen statt an Technologien, Infrastruktur und überkommenen Patterns (z.B. MVC, Layers).

Inkremente lösen die Vorstellung auf, dass es um Dinge ginge bei der Softwareentwicklung. Nicht jedoch das Dokument ist das Wichtigste, sondern der Prozess. Der ändert sich zuerst, ihm folgt ein eventuelles Dokument. Aber der Prozess, die Tätigkeit, das Verhalten sind weniger greifbar, sind keine Dinge. Deshalb tut sich die platonische Softwareentwicklung mit ihnen schwer.

Weitere Schritte werden wir noch erkennen, denke ich. Wenn wir uns darauf einlassen, unser Weltbild bzw. das von Software umzubauen.

In der Psychologie hat der Konstruktivismus “gewonnen”. Ich denke, davon sollten wir lernen als Softwareentwickler.

Was außerhalb von Software existieren mag, ist eine Sache. Eine ganz andere ist es, wie Software intern organisiert ist. Ähnlichkeit muss es zum Außen nicht geben. Nur Überlebenstauglichkeit. Dafür braucht es vor allem… Wandelbarkeit.

Sonntag, 17. August 2014

Warnung vor dem Microservice – Versuch einer Definition

Services sind wieder im Trend. Jetzt unter der Bezeichnung Microservice oder kurz: µService. Das empfinde ich grundsätzlich als Fortschritt. Schon vor einer “Moore-Periode” :-) (also 18 Monaten) habe ich das als konsequente Entwicklung beschrieben unter dem Titel “Software als Web of Services”. Und noch weiter zurück, im Jahr 2005, hatte ich mir in einer Artikelserie unter der Überschrift “Software Cells” Gedanken über eine grundsätzliche Anatomie von Software bestehend aus autonomen Einheiten gemacht, die heute aus einem gewissen Blickwinkel auch µService genannt werden könnten.[1]

Dennoch bin ich nicht ganz glücklich mit dem aktuellen Trend. Hatten vor 10 Jahren Services unter der Überschrift “Service Oriented Architecture” (SOA) etwas Politisches und schienen vor allem Sache von Managern und teuren Beratern. So sind Services heute als µServices demgegenüber eine Bewegung an der Softwareentwicklerbasis; nicht Manager interessieren sich dafür, sondern Geeks. Und damit ist der Schwerpunkt von der Politik zur Technologie geschwungen.

Das finde ich misslich. Denn so läuft die eigentlich gute Idee Gefahr, zu einem Cargo-Kult zu verkommen: Wenn es noch nicht recht klappt mit den Microservices, dann muss man nur noch RESTfuller werden oder mehr Netflix Open Source Infrastruktur zum Einsatz bringen. Oder?

Nein, mir scheint eine gewisse Warnung vor dem Microservice-Konzept angebracht. Es ist ein Werkzeug - und wie mit jedem Werkzeug kann man es zu Nutzen oder Schaden einsetzen. Die Gefahr, sich damit gehörig in den Fuß zu schießen, ist groß.

Es lohnt sich deshalb - wie so oft im Leben - vor dem enthusiastischen Einsatz ein bisschen nachzudenken.

Warum Microservices?

Als erstes stelle ich mal die Frage: Warum überhaupt µServices? Was bezwecken Netflix, otto.de, thoughtworks und andere damit?

Wenn ich Martin Fowler zum Thema lese, dann steht da zum Beispiel:

In short, the microservice architectural style is an approach to developing a single application as a suite of small services, each running in its own process and communicating with lightweight mechanisms, often an HTTP resource API. These services are built around business capabilities and independently deployable by fully automated deployment machinery.

Ah, es ist ein Architekturstil. Ja, aber warum? Der weitere Text redet viel über alles Mögliche - von Conway´s Law über Bounded Contexts bis “RESTish protocols” -, aber ich finde darin keine knackige Aussage zum Warum, d.h. zum Hauptantrieb hinter der Bewegung.

Hier und da kann man etwas heraushören wie hier:

Monolithic applications can be successful, but increasingly people are feeling frustrations with them - especially as more applications are being deployed to the cloud. Change cycles are tied together - a change made to a small part of the application, requires the entire monolith to be rebuilt and deployed. Over time it’s often hard to keep a good modular structure, making it harder to keep changes that ought to only affect one module within that module. Scaling requires scaling of the entire application rather than parts of it that require greater resource.

Aber was ist auf den Punkt gebracht der Hauptzweck? Oder anders: Welche Anforderungen des Kunden sollen µServices lösen helfen? Denn wie RDBMS, OOP, XML, MVC, WPF, Agilität usw. haben auch µService nur eine Berechtigung, wenn sie dem Kunden dienen.

Mein Unwohlsein mit der aktuellen µService-Diskussion rührt vor allem daher, dass mir genau dieser Punkt nicht geklärt zu sein scheint. Viele Köche rühren mit unterschiedlichen Vorstellungen am µService-Brei herum. Das ist kein Rezept für einen Erfolg der Idee, würde ich sagen.

Was Kunden wollen, hat für mich immer drei Aspekte:

  • Funktionalität, d.h. korrekte Operationen
  • Qualität, z.B. Performance, Skalierbarkeit, Usability, Security
  • Investitionssicherheit, d.h. hohe Produktivität des Teams und hohe Wandelbarkeit des Codes

Ausführlich habe ich das in meinem Buch “The Architect’s Napkin - Der Schummelzettel” und ein der Artikelserie “The Incremental Architect’s Napkin” erklärt.

Welchem dieser Aspekte sollen nun µServices dienen? Geht es um Qualität, sollen durch µServices nicht-funktionale Anforderungen wie Skalierbarkeit, Robustheit, Verfügbarkeit besser erfüllt werden? Oder geht es um Investitionssicherheit, indem µServices Code wandelbarer und Teams produktiver durch Wiederverwendbarkeit machen?

Mir ist das nicht klar nach dem, was ich bisher in der µService-Diskussion gehört habe. Deshalb glaube ich, dass es dazu keine einhellige Meinung gibt. Wahrscheinlich sind sich die meisten Diskutanten darüber selbst nicht klar.

Na gut, wenn das so ist, dann mache ich mal klar, was aus meiner Sicht der Zweck von Microservices sein sollte. Das kann nämlich nur einer sein. Auch als Konzept sollten µServices dem Single Responsibility Principle folgen.

Der Zweck von µServices ist, die Wandelbarkeit von Software zu erhöhen.

That´s it. Nicht mehr, nicht weniger. Vor allem: nur dies.

Microservices sollen es einfacher machen, Software über lange Zeit an neue Anforderungen anzupassen. Der Kunde mag sich neue Funktionalität oder bessere Qualität wünschen. Technologien mögen sich wandeln und sollen Eingang finden in eine Software. Der Arbeitsmarkt mag sich ändern. All diesen Fluktuationen soll Software möglichst leicht nachgeführt werden. Dabei sollen µServices helfen.

Eingegrenzt wird die Zweckerfüllung natürlich durch andere Anforderungen. Wie immer µServices aussehen mögen, sie dürfen Funktionalität und Qualitäten nicht einschränken. Denn eine wunderbar wandelbare Software, die entscheidende Operationen nicht beherrscht oder die zu langsam oder unsicher ist, wird kaum Gnade finden beim Kunden.[2]

µService dienen der Wandelbarkeit. Das bedeutet umgekehrt: µService sollten nicht zum Einsatz kommen, wenn es um Qualitäten geht. Wer z.B. denkt, “Die Skalierbarkeit unserer Web-Anwendung sollte besser werden. Lass uns doch mal µServices ausprobieren.”, ist aus meiner Sicht also auf dem besten Weg, sich mit µServices in den Fuß zu schießen.

Wenn zufällig und als Nebeneffekt durch Microservices auch noch eine Qualität steigt, dann ist das natürlich willkommen. Ziel sollte das jedoch nicht sein. Im “Softwarebaum” befinden sich µServices auf dem Evolvability Branch.

image

Sie sind Container, die zur vor allem dazu da sind, Code zur Entwicklungszeit zu kapseln. Dass sie auch noch gleichzeitig als Betriebssystemprozesse Hosts sind, also irgendwie im Quality Branch auftauchen… das ist halt so. Das muss dann auch bei der Erfüllung von Qualitätsanforderungen berücksichtigt werden. Wie gesagt, denen dürfen µServices nicht im Weg stehen.

Definitionsversuch

Nun da - aus meiner Sicht - geklärt ist, was Microservices eigentlich sollen, kann die Frage angegangen werden, wie sie ihre Aufgabe erfüllen können. Was sind die Charakteristika von µServices, wie lautet ihre Definition?

Aus dem Zweck leitet sich dafür eine Prämisse ab: Alle Microservice-Merkmale sollen dem Zweck dienen. Wer sagt, zu einem µService gehöre Merkmal X, der muss klar machen, wie X hilft, Wandelbarkeit zu erhöhen, ohne Qualitäten (über Gebühr) zu kompromittieren.

Wie am Softwarebaum abzulesen, sind Microservices nicht allein. Es gibt weitere Container, von denen sie sich unterscheiden müssen. Diese Container sollte jeder Entwickler auch im Blick haben, um abwägen zu können, ob sich µServices schon lohnen, oder Wandelbarkeit mit weniger Aufwand herstellen lässt. Denn soviel sollte schon jetzt klar sein: µServices sind technologisch keine Kleinigkeit und können leicht unerwünschten Einfluss auf Qualitäten haben. Warnung also davor, µServices “einfach mal” und “nebenbei” einzuführen. Mit ihnen angemessen umzugehen bedarf Übung. Und üben sollte man nicht am Produktionscode und nicht am Produkt, sondern in einem Übungsraum. Das Coding-Dojo der Clean Code Developer School bietet dafür eine Menge Aufgabenstellungen.

Die Container des Wandelbarkeitsastes sind für mich in wachsener “Größe”:

  • Funktion
  • Klasse
  • Bibliothek
  • Komponente
  • µService

Klassen enthalten Funktionen, Bibliotheken enthalten Klassen usw. Jede “Größenordnung” unterscheidet sich dabei von kleineren durch ein Merkmal. Bibliotheken z.B. sind opaque (oder gar binär), während Klassen noch als Quellcode vorliegen. Dadurch wird die Wiederverwendbarkeit stark erhöht. Komponenten hingegen haben wie Bibliotheken einen Kontrakt, doch der ist separat. Das ermöglicht quasi industrielle Arbeitsteilung bei der Entwicklung.

Und inwiefern gehen µServices über Komponenten hinaus? Der Kern der Definition von µServices sieht für mich so aus:

µServices sind Komponenten mit plattformneutralem Kontrakt.

Es sind also opaque Container (wie Bibliotheken) mit einem separaten Kontrakt (wie Komponenten), der aber eben auch noch plattformneutral ist.

Komponentenkontrakte sind plattformspezifisch. Eine CLR-Komponente kann eine andere CLR-Komponente benutzen, eine JS-Komponente kann eine andere JS-Komponente benutzen. Aber eine JVM-Komponente kann keine Ruby-Komponente benutzen.

Mit Komponenten zu arbeiten, bietet schon eine gehörige Portion Wandelbarkeit und Produktionseffizienz durch die Separation der Kontrakte von der Implementation. Solche Kontrakte entkoppeln mehr als die impliziten von Bibliotheken. Und sie ermöglichen eine parallele Implementation auf beiden Seiten des Kontrakts.

µServices gehen darüber hinaus. Indem die Kontrakte plattformneutral gehalten werden, können Client wie Server, Producer wie Consumer mit unterschiedlichen Plattformen entwickelt werden. Ein CLR-Microservice kann einen JVM-Microservice benutzen, ein JS-Microservice kann einen Ruby-Microservice aufrufen.

Plattformneutrale Kontrakte entkoppeln noch weitergehend. Sie eröffnen mehr Optionen für die Implementierung eines Containers. Plattformen und Sprachen können nach Zweckmäßigkeit, Toolverfügbarkeit, Frameworkangebot usw. gewählt werden. Oder man entscheidet sich nach Arbeitskräftelage dafür.

Alle µServices eines Softwaresystem können heute auch mit derselben Plattform realisiert sein - und erst im Laufe der Zeit wird man hier und da polyglott. In anderen Fällen mag man gleich z.B. auf der CLR mit C# und F# beginnen.

Ein plattformneutraler Kontrakt ist natürlich keine C++ .h-Datei und keine CLR Assembly mit Interfaces darin. Aber eine REST-Schnittstelle, über die Json-codierte Daten fließen, die ist plattformneutral. Oder eine WSDL-Servicedefinition. Oder eine Protokolldefinition wie SMTP oder POP3.

Ist das nun aber schon die ganze µService-Definition? Hm… ich würde sagen, ja. Alles andere ist Kommentar und Auslegung.

Kommentare

Kommentar #1: µServices sind Prozesse

Dass µServices in eigenen Betriebssystemprozessen laufen, ist eine Folge der Definition. Über Plattformen hinweg kann nicht im selben Prozess kommuniziert werden. Insofern sind µServices relevant für den Qualitätsast des Softwareuniversums.

Auf Qualitäten Einfluss zu nehmen, ist nicht der Zweck von µServices, aber es lässt sich auch nicht vermeiden. Von einer Komponentenarchitektur, die (zumindest konzeptionell) neutral in Bezug auf Qualitäten ist, zu einer µService-Architektur überzugehen, ist also kein Selbstgänger.[3]

Weil µServices Prozesse sind, muss natürlich dafür gesorgt werden, dass die überwacht werden. Und bei Bedarf neu gestartet. Und einfach zu deployen sind. Doch Achtung! Das ist kein Selbstzweck, sondern nur eine Folge der Form von µServices, die wiederum eine Folge ihres Zweckes ist.

µServices dienen dazu, monolithische Software aufzubrechen. Wo heute vielleicht ein Fat Client mit einem Fat Backend spricht, reden morgen ein Dutzend µServices im Frontend und Backend miteinander. Aus geringer Verteilung von Code wird hohe Verteilung von Code. Das bedeutet, auch wenn bisher die Fallacies of Distributed Computing noch kein großes Thema gewesen sein mögen, dann werden sie es jetzt. Wieder: Achtung! µServices sind kein Kinderspielzeug, sondern eine geladene Waffe.

Kommentar #2: Kontrakthürden

Besonderes Augenmerk verdient der Kontrakt von µServices. Er repräsentiert ihren “Zuschnitt”. Er definiert, wie oft in welchem Umfang Daten fließen. Das hat unmittelbare Auswirkung auf die Änderungsanfälligkeit und die Performance. Kein Wunder also, dass schon gebeten wird, “Please avoid our mistakes!”.

Wer bisher keine Erfahrung hat, mit verteilten Systemen, wer bisher keine Erfahrung hat mit expliziten Kontrakten… der wird keinen schmerzfreien Einstieg in µServices-Architekturen finden.

Soviel lässt sich über µService-Kontrakte sagen: sie sind zentrale Erfolgsfaktoren. Eines lässt sich jedoch aus meiner Sicht nicht sagen, dass es dringend RESTful-Kontrakte sein sollten oder dass Json oder Atom zu Einsatz kommen müssten. Und ich gehe noch weiter: Auch die Kommunikation über TCP halte ich nicht für definitionsrelevant.

Es ist Vorsicht geboten, bei der Diskussion über und der Planung von konkreten µService-Architekturen nicht über Bord zu gehen angesichts technologischer Wellen. Technologien oder gar Produkte sollten keine Triebfedern für µServices sein. Auch bei Microservices gilt: Keep it simple, stupid.

µServices sind Mittel zur Erhöhung von Wandelbarkeit. Dieser Zweck darf nicht durch Spaß am technologischen Feuerwerk vereitelt werden.

Kommentar #3: Asynchrone Kommunikation

µServices sollten asynchron kommunizieren, heißt es hier und da. Das sehe ich ähnlich. Es ist für mich eine Folge ihrer Form als Prozess. Zwischen Threads (auf denen Prozesse basieren) kann nur asynchron kommuniziert werden. Da sollte man ehrlich bis in den API sein.

Allerdings gefällt mir der technologische Unterton bei diesem Merkmal nicht. Deshalb ist Asynchronizität für mich derzeit auch nur ein Kommentar und Teil der Definition. Wichtiger noch als Asynchronizität finde ich auch Messaging, d.h. die Kommunikation über Einwegnachrichten zwischen unabhängigen Funktionseinheiten.

Zwischen µServices gibt es keinen Kontrollfluss mehr, sondern nur Datenfluss. Jeder µService läuft ja in einem anderen Prozess, hat also seinen eigenen Kontrollfluss in seinem Thread. Das sollte sich im Schnitt der µServices und damit in ihren Kontrakten niederschlagen. Ansonsten droht schnell eine Verletzung von Martin Fowlers First Law of Distributed Objects, vor der er selbst im Zusammenhang mit µServices warnt.

In diesem Zusammenhang stellt sich auch die Frage, was eigentlich der Unterschied zwischen µServices und den guten alten Servern ist. Bisher haben wir Client/Server-Anwendungen geschrieben - mit zunehmender Zahl an Servern. Sind µServices nicht einfach Server mit neuem Titel?

Nein. Das wäre eine Kategorienvermischung. Server gehören zur Kategorie der Hosts - jedenfalls in meiner Vorstellung vom Softwarebaum. Server dienen der Herstellung von Qualitäten. µServices hingegen sind Container und dienen der Herstellung von Wandelbarkeit.

Server und µServices passen aber gut zusammen: µService sind die Bausteine von Servern (und Clients). Um Qualitäten zu erfüllen, wird für gegebene Funktionalität im Rahmen des Architekturentwurfs zunächst bestimmt, wie die auf Hosts zu verteilen ist. Ist eine Verteilung überhaupt erforderlich, wenn ja, auf wieviele Server?

Erst anschließend sollte darüber nachgedacht werden, ob und welche Clients bzw. Server in µServices zerlegt werden. Nur dann ist sichergestellt, dass µServices nicht die Erfüllung von Qualitätsanforderungen behindern. Der Rahmen für Container sind immer Hosts. Der Softwarebaum wächst mithin nicht in alle Richtungen gleichzeitig, sondern in Phasen, die über seine Äste laufen:

image

Kommentar #4: Einfaches Deployment

Schon mit Bibliotheken wird die physische Codebasis auseinandergerissen. Es entstehen mehrere separat deploy- und versionierbare Einheiten. Komponenten machen das deutlicher. µServices legen hier nochmal nach. “Nur” möchte ich sagen, denn das Problem ist ja nicht neu. Deshalb gehört “easy deployment” auch nicht zur Definition von µServices.

“Easy deployment” von einzelnen sich immer öfter wandelnden Containern ist eine Folge ihres Zwecks und ihrer Definition. Hierin besteht ein Teil des Preises, den man für mehr Wandelbarkeit zahlen muss. “Easy deployment” von µServices ist technologisch aufwändiger als das von Komponenten, allemal, wenn womöglich dafür das Gesamtsystem nicht offline genommen werden soll. Also: Achtung!

Welcher Deployment-Aufwand rechtfertigt welchen Wandelbarkeitsnutzen?

Das ist sicherlich auch eine Infrastruktur und Plattformfrage. Wenn es im .NET-Ökosystem dafür weniger Unterstützung gibt als im JVM-Ökosystem, dann fällt bei CLR-Softwaresystemen die Entscheidung für µServices vielleicht schwerer. Aber lohnt deshalb ein Umstieg auf JVM? Oder ist die JVM-Welt später eine Hürde für weitere Flexibilisierung, weil die dortige Infrastruktur es schwer macht, sie noch weiter zu öffnen für non-JVM Sprachen in der Zukunft?

µServices sind eine Waffe zur Bekämpfung und Vermeidung von systemrelevanten Größen. Keine Sprache, keine Plattform, keine Datenbank, keine Technologie, kein Konzept usw. soll so groß und mächtig werden, dass sinnvolle Veränderung behindert wird. Also Vorsicht beim enthusiastischen Wechsel von Plattform A zu Plattform B, weil dort heute µServices irgendwie besser gehen. Der Wechsel kostet Zeit - Jahre womöglich - und wer weiß, wer dann den Preis für die beste Plattform hält.

Jede Form von Plattformfokus steht für mich im Widerspruch zur Grundbotschaft von Microservices. Wer sich für µServices also plattformmäßig strategisch einschränkt, läuft Gefahr, das Ziel zu verfehlen.

Kommentar #5: Die Größe von Microservices

Am Anfang der Diskussion stand der Umfang von µServices als ein Definitionskriterium. Sie sollten - sagen manche - nicht länger als 100 LOC sein.

Ich finde ein solches hartes Kriterium nicht hilfreich. Es fördert den Cargo-Kult. Besser gefällt mir “fits inside your head”. Damit wird nämlich betont, dass es um eine Sinneinheit geht.

Eine solche Umfangbeschreibung ist andererseits zu schwammig, um in die Definition aufgenommen werden. Stattdessen also Kommentar: Wenn Wandelbarkeit durch geringen Codeumfang begünstigt wird, dann sollten µServices natürlich nicht zu groß werden.

Aber wie groß? Verständlichkeit ist ein Kriterium. Ein anderes ist für mich der Aufwand, um einen µService komplett neu zu schreiben.

Wir haben ein Problem mit Software, wenn wir mehr und mehr refaktorieren müssen, um Änderungen anzubringen. Refaktorierung zeigt an, dass ein Sauberkeitsleck existiert. Das ist wie mit einem Speicherleck.

Darauch kann man auf zweierlei Weise reagieren. Man kann das Leck versuchen zu stopfen: Einfürallemal den Code korrigieren, der dafür sorgt, dass Speicher nicht wie gewünscht freigegeben wird. Einfürallemal die Unsauberkeit beheben und dann am besten nie wieder dreckigen Code schreiben.

Oder man kann auf das Stopfen verzichten und startet das Programm periodisch neu, bevor der Speicher “ausgelaufen” ist. In Bezug auf die Sauberkeit bedeutet das, man schreibt den unsauberen Code neu.

Wenn ich mich nicht irre, ist es Netflix, die ihre Hosts herunterfahren und neu starten, um gar nicht erst in Speicherlecks zu laufen. Sie anerkennen, dass es “irgendwie” immer wieder zu Speicherlecks kommen kann - in eigenem Code oder Infrastruktur - und dass es sehr teuer sein kann, diese Lecks zu stopfen. Viel teurer, als Hosts gelegentlich neu zu starten.[4]

Insofern glaube ich, dass wir zu Architekturen kommen müssen die uns erlauben, öfter Code neu zu schreiben: rewrite over refactor. Dafür sind µServices nicht nötig, das kann man auch schon mit Komponenten erreichen. Doch µServices fügen dem noch ein Level an Flexibilität hinzu. Denn mit µServices gibt es noch mehr Freiheit beim Rewrite. Und die Neuentwicklung kann zur Laufzeit in das System eingebracht werden.

Ein Rewrite kostet natürlich auch Geld. Wie groß kann ein µService also werden, damit ein Rewrite noch möglich ist? Das hängt von vielen Faktoren ab: Entwicklerkompetenz, Domänenkomplexität, Budget usw.

Ich glaube aber, dass eine gewisse Obergrenze bei einem Aufwand von 1–2 Monaten liegt. Für diesen Zeitraum kann ein Projekt zur Not mal die Füße still halten. Dabei bedenke man: Was in dieser Zeit neu geschrieben werden kann, hat wahrscheinlich 2 bis 10 Mal soviel Aufwand in der Erstentwicklung inklusive aller Refaktorisierungen gekostet. Und der resultierende Umfang ist 30% bis 80% geringer.

Rewrites sind aus meiner Sicht das beste Mittel, um die LOC einer Software zu reduzieren. Nur müssen dafür abgeschlossene Einheiten vorhanden sein, die man eben neu schreiben kann mit überschaubarem Aufwand. Das sind µServices.

Refactoring wird damit nicht verschwinden. Ein Rewrite soll ja nicht bei jeder kleinen Änderungen stattfinden. Das halte ich auch für unökonomisch. Bis zum Rewrite mag es mehrere Refactorings geben. Aber immer gibt es die Option, alternativ neu zu schreiben. Diesen Freiheitsgrad hat ein Projekt normalerweise nicht, weil es immer als Ganzes betrachtet wird. Mit µServices jedoch wird ein Horizont eingezogen, innerhalb dessen es sich anbietet, anders zu verfahren als auf das Ganze gesehen.

Und Refactoring wandert natürlich auf eine höhere Ebene. Das Gesamtsystem bestehend aus allen µServices lässt sich immer noch nicht neu schreiben. Das Zusammenspiel der µServices ist deshalb über die Zeit sicherlich zu refaktorisieren.

Es ist wie bei einem Organismus: Der ist ein Ganzes, dessen Struktur sich immer wieder anpasst (Refaktorisierung) und dessen Teile ständig ausgetauscht werden (Zelltod, Zellteilung).

Mit µServices bleiben Anwendungen als Ganzes bestehen, passen sich an - bestehen nach einer gewissen Zeit jedoch nicht mehr aus denselben Teilen wie zu Anfang. µServices unterliegen einer ständigen Erneuerung. Eine gewisse Zeit werden sie gepflegt; dann “sterben” sie und werden ersetzt durch eine komplett neu geschriebene Version.

Wie gesagt, das geht auch grundsätzlich schon mit Komponenten. Microservices bringen aber eben noch eine Portion Entkopplung und Autonomie mit - die auf der anderen Seite ihren Preis hat.

Kommentar #6: Scope

Was soll die Aufgabe von µServices sein? Ist sie dieselbe wie die von bisherigen Servern? Das kann nicht sein, weil µServices Bausteine von Servern sind (s.o.). Ein Teil kann nicht das Ganze sein.

Client/Server-Beziehungen werden aus Gründen der Qualitätssteigerung eingeführt. In µServices muss Software hingegen aus anderen Gründen zerschnitten werden. Ihr Zweck ist ja die Steigerung der Investitionssicherheit. Es geht vor allem um Wandelbarkeit. Deren Kernvoraussetzung ist Entkopplung.

Bei µServices müssen daher zwei Dinge zusammenkommen: 1. Der Schnitt durch die Anforderungen muss so gesetzt sein, dass ein mehr an Wandelbarkeit entsteht. 2. Der Schnitt muss so verlaufen, dass der erhöhte Kommunikationsaufwand zur Laufzeit insb. die primären Qualitäten Performance und Skalierbarkeit nicht beeinträchtigt.

Für mich folgt daraus, dass µServices Inkremente sind. µServices stehen für Interaktionen (im Sinne des Softwarebaums) oder für Use Cases (als Gruppen von Interaktionen) oder für Features, d.h. anwenderrelevante Aspekte von Interaktionen.

In jedem Fall repräsentiert ein µService eine Untermenge des Anwendungsscope. Er stellt ein vertikales Teilstück dar, eine Scheibe - womöglich sogar einen “kopflosen” Durchstich.

Damit ist ein µService eben kein Server. Denn Server sind horizontale Schichten. Schichten werden übereinander gelegt, um Inkremente herzustellen. Mit einer Schicht allein, kann ein Anwender nichts anfangen. Dazu kann ein Kunde kein Feedback geben. Schichten interessieren Kunden nicht, Scheiben hingegen schon.

Server im Sinne von Schichten als tiers, also als verteilte Funktionseinheiten, sind Sache der Qualitätsherstellung. Server sind Hosts. µServices sind keine Hosts, sondern Container. Als solche könnten sie zwar grundsätzlich auch als Schicht gedacht sein. Denn das Schichtenmodell ohne Verteilung war als Architekturmuster als Hilfe zur Steigerung der Wandelbarkeit gedacht. Doch ich glaube, dass das eben nicht die Aufgabe von µServices sein darf. Dafür gibt es Komponenten. Nein, µServices sollten für weitergehende Entkopplung vertikale Teilstücke einer Software repräsentieren.

Zwischen schichten gibt es vielfältige funktionale Abhängigkeiten. Zwischen Inkrementen jedoch sind die funktionalen Abhängigkeiten viel geringer oder gar ganz abwesend. Die Abhängigkeit zwischen Inkrementen wie Dialog, Interaktion und Feature reduzieren sich womöglich auf logische Abhängigkeiten, die sich in Daten manifestieren.

Deshalb ist es interessant, µServices nicht einmal von denselben physischen Daten abhängig sein zu lassen. Jeder µService kann sein eigenes Domänenmodell haben oder gar seine eigene Datenbank. Das führt zu Redundanz - aber deren Preis ist langfristig womöglich kleiner als der hoher Abhängigkeiten von einem gemeinsamen Modell und einer zentralen Datenbank.

Das eine Domänenmodell und die eine Datenbank sind im Grunde die Hauptsymptome von monolithischer, d.h. schwer wandelbarer Software. Wenn der Zweck von µServices darin besteht, die Wandelbarkeit nach vorne zu bringen, dann sollten sie es also genau in dieser Hinsicht anders machen.

Zum Datenmodell gehört auch das Thema Zustand im allgemeinen und Session im Speziellen. Dürfen µServices Zustand und/oder Sessions haben?

Ich sage Ja. Warum nicht? Unter einer Bedingung: Zustand und Session sollten die Wandelbarkeit nicht beeinträchtigen. Tun sie das, dann raus damit oder den µService anders schneiden.

Wenn über Zustand und Sessions gemeinhin kritisch nachgedacht wird, dann nicht mit Blick auf die Anforderung Wandelbarkeit. Es normalerweise um Qualitäten, d.h. Merkmale von Hosts. Sessions wirken sich z.B. negativ auf die Skalierbarkeit aus.

Wenn über µServices nachgedacht wird, sollten solche Fragen jedoch schon geklärt sein. µServices strukturieren Software im Rahmen von Hosts.

Was aber, wenn die Verteilung eines Host auf mehrere µServices neuerlich Qualitätsfragen aufwirft? Dann muss man sie in Balance bringen mit dem Zweck von µServices.

Das gilt für alle Fragen nach dem Motto “Darf/soll ein Microservice so und so aussehen?” Es ist immer sofort zurückzufragen: Widerspräche das dem Zweck von µServices? Widerspräche es der Definition von µServices?

Ableitungen

Was geeignete Schnitte durch den Scope eines Softwaresystems sind, muss im Einzelfall ausgetüftelt werden. Der Rahmen für die Schnitte ist nun jedoch klar:

  • Was herausgetrennt und zu einem µService gemacht wird, darf nur so groß sein, dass es sich vergleichsweise schnell immer wieder neu schreiben lässt.
  • Es soll ein Inkrement darstellen, das Hoheit über seine eigenen Datenmodelle hat.
  • Es muss per Messaging in das große Ganze eingebunden werden können.
  • Seine Autonomität als Prozess darf Performance und Skalierbarkeit des Ganzen nicht beeinträchtigen.

Das sind für mich Ableitungen aus der Zweck und Definition. Dass die möglichst simpel und klar gehalten werden, ist aus meiner Sicht sehr wichtig. Wir verlieren sonst Freiheitsgrade und laufen Gefahr, technikverliebt durch die Gegend zu entwickeln.

Dass simple Definitionen nicht immer einfach umzusetzen sind, steht auf einem anderen Blatt. Auch über ganz Simples lässt sich lange trefflich streiten. So kommt es dann zu Kommentaren, Auslegungen und unterschiedlichen Schulen. Im Kern sollten sich jedoch alle einig sein. Deshalb sollte der Kern klein und leicht fasslich sein.

Hier ist mein Vorschlag für einen Kern des µService-Konzepts:

  • Der Zweck von µServices besteht darin, die Wandelbarkeit von Software zu erhöhen. Sie gehen dabei über andere Container wie Komponenten hinaus.
  • Ein µService liegt formal vor, wenn ein opaquer Container durch einen separaten plattformneutralen Kontrakt beschrieben ist.

Der Rest ergibt sich… Aber immer Vorsicht: µServices haben ihren Preis.


  1. Seitdem hat sich allerdings meine Vorstellung von Softwarezellen weiterentwickelt. Ihre Struktur ist detaillierter geworden, ihr Einsatzgebiet für den Entwurf von Software spezifischer. Und insgesamt sind sie “untechnologischer” als das, worüber in der µService-Diskussion gesprochen wird.

  2. Anders herum ist es jedoch scheinbar kein Problem für Kunden: Software, die funktional, performant, skalierbar usw. auf Kosten der Wandelbarkeit ist, findet sich überall. Ich möchte fast sagen, sie ist die Norm. Warum das so ist, darüber lässt sich trefflich diskutieren. Aber es ist so und dem muss etwas entgegengesetzt werden - allerdings ohne denselben Fehler wieder zu begehen. Nur mit Balance lässt sich zukunftsfähige Software langfristig ökonomisch bauen. Die Anforderungsaspekte müssen sich in der Implementation die Waage halten. Auch deshalb: Vorsicht beim Aufspringen auf den µService-Trendzug.

  3. Dass viele Teams Erfahrung mit Komponentenarchitekturen haben, bezweifle ich. Das Denken in solchen Containern ist nicht weit verbreitet. Selbst Bibliotheken werden vergleichsweise selten eingesetzt, um Softwaresysteme mehr aus Black Boxes zusammenzusetzen. Insofern bin ich skeptisch, dass landauf-landab schon bald µServices mit Erfolg eingesetzt werden. Da hilft auch alle Open Source Infrastruktur nicht. Es fehlt einfach an Architektursystematik.

  4. Von außen betrachtet gibt es keinen Unterschied zwischen einem periodischen Neustart und einem Crash oder einer Nichtverfügbarkeit aufgrund von Leitungsproblemen. Die Gesamtarchitektur muss ohnehin darauf ausgelegt sein. Warum also diesen Umstand nicht nutzen, um ein Problem pragmatisch zu lösen? Softwareentwicklung ist eben eine ökonomische Tätigkeit. Wer Perfektion sucht, ist auf dem sicheren Pfad zu Frust.

Donnerstag, 14. August 2014

Software systematisch wachsen lassen

Mir gefällt die Metapher von der “wachsenden Software”. Ein schöner bildlicher Gegenentwurf zur Hausbaumetapher. Aber bisher hat mir dabei immer etwas gefehlt. Wie funktioniert denn das mit dem Wachsen genau? Software wächst ja nicht von allein, sondern durch unseren Eingriff von außen.

Das Buch “Growing Object-Oriented Software Guided by Tests” (GOOS) hat versucht, diesen Wachstumsprozess, nein, eher die Wachstumstätigkeit zu konkretisieren. Tests sollen das Wachstum antreiben und ausrichten.

Das ist sicher richtig, insofern Tests für Anforderungen stehen. Alles beim Wachstum von Software sollte durch konkrete Anforderungen motiviert sein. Doch was tun, nachdem ein Test definiert ist? Die Struktur des Produktionscodes ergibt sich ja nicht von allein, sobald man einen automatisierten Test hat.

Da greift das Buch bzw. die ganze Metapher bisher für mich zu kurz.

Heute morgen jedoch ist mir aufgegangen, wie das, was ich bisher als Softwareuniversum bezeichnet habe, eigentlich eine Anleitung zum Wachstum ist, also sozusagen die DNA für einen Softwareorganismus.

Eine ausführliche Beschreibung des Softwareuniversums finden Sie in meinem Buch The Architect’s Napkin - Der Schummelzettel. Im Weiteren benutze ich die Begriffe aus dem Softwareuniversum ohne ausführliche Erklärung. Ich möchte mich auf ihre Neuordnung konzentrieren.

Anforderungen als Nahrung

Getrieben wird das Wachstum von Software durch Anforderungen. Doch die sollten nicht allen in einen Topf geworfen werden. Eine differenzierte Sichtweise lohnt sich, denn unterschiedliche Arten von Anforderungen müssen beim Wachsen auch unterschiedlich behandelt werden.

Ich unterscheide drei Kategorien von Anforderungen:

image

Funktionale Anforderungen beschreiben, was Software tun soll, z.B. rechnen oder Auktionsangebote zugänglich machen. Qualitätsanforderungen geben vor, wie diese Funktionalität vollbracht werden soll, z.B. wie schnell, wie sicher usw.

Mit diesen Anforderungen werden Sie normalerweise durch den Kunden konfrontiert. Doch es gibt noch eine weitere Kategorie, die dem Kunden wichtig ist, auch wenn er meist dazu schweigt. Er hat nämlich auch noch Anforderungen im Hinblick auf die Investitionssicherheit seiner Software. Er möchte, dass Funktionalität und Qualität sich stets zügig wandeln lässt.

Wenn wir Software wachsen lassen wollen, müssen wir also darauf achten, dass sie in Richtung aller Anforderungen wächst. Und das systematisch. Und auch noch diskutierbar und kommunizierbar.

Wie das nur durch eine “guidance by tests” gehen soll, ist mir schleierhaft. Dem GOOS-Ansatz fehlt schlichtweg jedes Meta-Modell.

Der Softwarebaum

Anders sieht es aus, wenn ich die Dimensionen des Softwareuniversums in Form eines Baumes anordne:

image

Jetzt gibt es einen klaren Weg. Jetzt gibt es ein big picture. Jetzt gibt es “Wachstumsbausteine”.

Der Stamm

Am Anfang des Wachstums steht der Stamm. Hier liegen die Anforderungen unmittelbar an. Der Stamm wird im Dialog mit dem Kunden entwickelt. Das ist wichtig, denn auf ihm ruht am Ende die Krone mit all ihren Ästen.

image

Beim Stamm geht es darum, die Gesamtanforderungen immer feiner zu zerlegen in Inkremente. Das sind kundenrelevante Zuwächse in Form von Durchstichen. Zu denen kann der Kunde klares Feedback geben. Zu denen kann er natürlich auch Akzeptanzkriterien formulieren, die sich (hoffentlich) in automatisierte Tests übersetzen lassen.

Das größte solche Inkrement ist ein Bounded Context, das kleinste eine Interaktion.

Im Bild sehen Sie, dass der Stamm aus mehreren Ebenen besteht. Jede beschreibt ein anderes Abstraktionsniveau und besteht wiederum aus Artefakten der nächsten Ebene.

Der Funktionalitätsast

Aus dem Stamm entwickelt sich als erster Hauptast die Funktionalität. Für jede Interaktion des Stamms wird durch Zerlegung in einer Hierarchie von Datenflüssen bestimmt, wie das gewünschte Verhalten erzielt werden soll.

image

Im Bild steht, dass das zur Codierungszeit geschieht. Das ist insofern richtig, als dass dann mittels des Integration Operation Segregation Principle und des Principle of Mutual Oblivion die Herstellung von Datenflüssen gesichert werden muss. Aber natürlich sollen diese Flüsse vorher (in angemessenem Umfang) entworfen werden.

Die Länge und Verzweigungstiefe des Funktionalitätsastes ist beliebig. Er wird so ausladend, wie es nötig ist. Die Schachtelungstiefe seiner Funktionseinheiten ist unbegrenzt - wenn auch in der Praxis natürlich sehr endlich ;-) Die Knoten in diesem Teilbaum sind Integrationen, die Blätter Operationen.

Der Qualitätsast

Auch wenn Funktionalität das erste ist, was sich aus dem Stamm entwickeln soll, ist es weder das Einzige noch das Wichtigste. Software wird ja nicht für Funktionalität gemacht, sondern für Qualität.

image

Sobald also die Funktionalität soweit heruntergebrochen ist, dass sie sich in dünnen Inkrementen ausliefern lässt (Produktionseffizienz), und auch noch klar ist, was dann intern passieren muss, ist daran zu denken, wie die Qualitätsanforderungen eingehalten werden können. Es geht dann um Laufzeitcharakteristika wie Performance, Skalierbarkeit oder Robustheit.

Dazu sind andere Bausteine in den Blick zu nehmen. Bei der Funktionalität ging es im Wesentlichen um Funktionen, bei der Qualität geht es nun um Threads, Prozesse, Geräte usw. Die wiederkehrende Frage lautet: Wie sollten die Funktionen des funktionalen Entwurfs auf diese so genannten Hosts verteilt werden, um die geforderten Qualitäten herzustellen?

Der Wandelbarkeitsast

Last but not least das Thema Evolvierbarkeit. Auch wenn (oder gerade weil) der Kunde dazu nur eine diffuse Vorstellung hat, müssen Sie sich darum explizit beim Softwarewachstum kümmern.

image

Wenn klar ist, welche Funktionen die Funktionalität herstellen und wie die auf Hosts verteilt werden, ist zu überlegen, zu welchen so genannten Containern sie zusammengeschnürt werden sollen.

Welche Klassen, Bibliotheken, Komponenten, µServices sollte es geben, damit die Wandelbarkeit über lange Zeit erhalten bleibt?

Kohäsion und Kopplung sind die treibenden Kräfte bei der Containerfindung. Sie ist damit ein Thema der Entwurfszeit.

Wachstumsphasen

Der Softwarebaum wächst vom Stamm zu den Ästen. Die Reihenfolge dabei ist jedoch nicht so streng zu sehen, wie ich bisher vielleicht suggeriert habe. Je nach Umfang des zu entwickelnden Softwaresystems kann auf den Stamm auch der Qualitätsast folgen und dann erst der Funktionalitätsast. Der Evolvierbarkeitsast jedoch ist meist der letzte, der sprießt.

Doch auch das geschieht nicht nicht nur einmal, sondern wiederholt. Der Softwarebaum wächst in Phasen: ein bisschen Stamm, dann der Funktionalitätsast, dann der Qualitätsast, dann der Evolvierbarkeitsast - und schließlich geht es wieder von vorne los.

Wachstum ist mithin im Grunde immer überall am Werk. Stamm und Äste wachsen im Umfang und in der Breite.

Dass der Softwareorganismus nicht wie ein Schwamm wächst, sondern strukturierter, differenzierter, steckt im Meta-Modell. Das gilt, so denke ich, grundsätzlich für jedes Softwareprojekt. Denn die drei Anforderungskategorien sind ja universell. Und deren systematischer Bearbeitung dient die anatomische Grundstruktur des Softwarebaums. Keine Anforderung darf unter den Tisch fallen.

Auch wenn die endgültige Architektur einer Software über die Zeit emergieren mag, so sollte das nicht planlos geschehen. Tests können ruhig am Anfang jeder Umsetzung eines Inkrements stehen. Doch wie kommen Sie zu Inkrementen? Sie lassen sie nach dem Schema des Stamms wachsen. Und wie dann weiter, wenn die Tests für ein Inkrement definiert sind? Dann treiben Sie das Wachstum entlang der drei Äste Funktionalität, Qualität und Evolvierbarkeit weiter. Mit klaren Vorstellungen von Bausteinen und Regeln.

Softwareentwicklung ist keine Sache, die aus dem Handgelenk und intuitiv funktioniert. Da braucht es schon etwas mehr Systematik. Die liefert der Softwarebaum, finde ich. Er verbindet Klarheit und Struktur mit organischer Entwicklung.

Montag, 21. Juli 2014

Zeitmanagement für Softwareentwickler

Warum kommt Clean Code oft gar nicht oder nur mit Mühe im Tagesgeschäft von Entwicklerteams an? Warum fühlen sich Entwickler oft überlastet?

Abgesehen von fachlichen Problemen liegt das, so scheint mir, häufig an einer gut gemeinten, aber unsystematischen Arbeitsweise. Selbst wo man schon an Agilität geschnuppert hat, ist das persönliche Zeitmanagement weithin unterentwickelt.

Deshalb hatte ich vor einiger Zeit die Idee, für diesen Aspekt der Entwicklerarbeit ein Angebot mit Prinzipien und Praktiken zu formulieren. Prinzipien und Praktiken für das Zeitmanagement für Softwareentwickler.

Allgemeine Angebote zum Thema Zeitmanagement gibt es natürlich viele. Doch wenn man die wahrnimmt, dann ist der Transferaufwand in die eigene Arbeitspraxis hoch. Außerdem ist die Softwareentwicklung in einigen Aspekten recht eigen. Wenn allgemeines Zeitmanagement z.B. über Priorisierung spricht - Stichwort: Eisenhower-Prinzip - dann ist das nicht nur für Studenten und Sachbearbeiter relevant, sondern auch für Softwareentwickler. Doch es bleibt eine Lücke. Speziell für die Softwareentwicklung lässt sich eben mehr zur Priorisierung sagen.

Diese Lücke zu schließen, war mein Anliegen. Ich wollte das Thema Zeitmanagement für Softwareentwickler zugänglicher, leichter anwendbar machen.

Nicht unerheblich an dieser Idee beteiligt war allerdings meine Partnerin Andrea “Mrs. Paperless” Kaden. Denn sie gab schon Zeitmanagement-Seminar der allgemeinen Art im Rahmen ihrer Arbeit als Professional Organizer. So war meine Idee denn auch, das Angebot für die Softwareentwicklung als Komplementärtraining zu formulieren.

Das haben wir dann getan und im Juli 2014 das erste Seminar gehalten. Das Ergebnis sehen Sie hier :-)

image

Ja, tatsächlich war dieser power nap eines Teilnehmers in der Mittagspause ein Ergebnis des Seminars. Nachdem wir einen Tag an Zielen, Prinzipien und Praktiken gearbeitet hatten, war für ihn am zweiten Tag klar, dass es für ihn zu einem professionellen Umgang mit seinen Kräften und seiner Zeit gehört, zwischendurch kurz mit einem power nap aufzutanken.

Ein systematischer Umgang mit Zeit lässt sich aber natürlich nicht im Schlaf erlernen ;-) Wir haben zwei Tage lang einigen Stoff “gepaukt”. Hier das Kanban-Brett unserer Themen:

image

Neben praktischen Übungen war uns dabei wichtig, Denkprozesse anzustoßen. Das Zeitmanagement kommt ja nicht einfach in Ordnung, indem man z.B. plötzlich seine Arbeit mit der Pomodoro Technique taktet oder Nein sagen geübt hat. Das sind nur Werkzeuge, die man zu einem Zweck im Rahmen von Prinzipien und “Naturgesetzen” einsetzen kann. Was aber ist der Zweck? Worum geht es eigentlich im persönlichen Leben? Worum geht es bei der Arbeit wirklich? Warum sollte wofür welche Zeit überhaupt aufgewandt werden? Und wie beeinflusst die Softwareentwicklung als Arbeitsrahmen die Antworten auf diese Fragen?

Solche Fragen galt es auch zu diskutieren. Und gerade da hat es sich als besonders hilfreich erwiesen, dass Andrea und ich einen unterschiedlichen Hintergrund haben. Ihrer ist die allgemeine Arbeitsorganisation, bei ihr geht es um Prozesse und “das Menschliche”; meiner ist die Technik, die konkrete Organisation der Softwareproduktion, die Entwickler- und Stakeholder-Sicht.

Das Seminar war für uns inhaltlich ein Experiment und in der Zusammenarbeit. Beides hat gut funktioniert, wie wir finden. Es hat uns Spaß gemacht und den Teilnehmern auch, wie uns das Feedback zeigt.

imageIch freue mich, dass meine Idee aufgegangen ist. Also machen wir weiter. Im November 2014 sind wir wieder in Hamburg am Start, im Januar 2015 in München. Genaueres finden Sie hier.

Überlegen Sie einmal, ob Sie mit dabei sein wollen. Wir versprechen zwei erhellende und ungewöhnliche Tage inklusive online Nachlese. Denn wir sind ja daran interessiert zu hören, wie der Transfer in die Praxis gelingt.

Wer will schon immer nur Technologieseminare besuchen? ;-) Systematisches Zeitmanagement ist auch eine coole Sache - und die Grundlage für technische Erfolge.

Wir freuen uns auf Sie!

image

Andrea und Ralf

Mittwoch, 9. Juli 2014

Erfolgreich in der Unvorhersagbarkeit, oder: Softwareglück ohne Schätzungen

imageBahnfahren erinnert mich an Softwareentwicklung: Regelmäßig werden Versprechen nicht eingehalten. Der ICE von Hamburg nach Wien hat schon beim Start 6 Minuten Verspätung. Daraus werden 10 bis Würzburg. Das sind ca. 5% Verzug und hört sich nicht viel an. Nur verpasse ich dadurch meinen Anschlusszug. Ich muss 45 Minuten warten - und komme mit 60 Minuten Verspätung am Ziel an. Der Gesamtverzug der für mich interessanten End-to-End Verbindung beträgt damit über 20%.

Wenn die Bahn bei Direktverbindungen sich also womöglich für nur geringe Verzögerungen rühmt, dann lügt sie sich in die Tasche. Für mich als Fahrgast, der fast immer ein- oder zweimal umsteigen muss, ist die Verlässlichkeit der Deutschen Bahn inakzeptabel. Die Differenz zwischen Versprechen und Leistung ist zu groß. Da verliere ich das Vertrauen…

Oder ich passe einfach meine Erwartung der Realität an. Wenn die Bahn nicht verlässlich liefert, dann muss ich meine Planung und mein Verhalten ändern.

Let´s get real: Aufwandschätzung funktioniert nicht

Zu derselben Einsicht sollten Kunden und Manager der Softwareentwicklung kommen. Nach 50 Jahren unzuverlässiger Lieferung von Software, sollten sie ihre Erwartungen und ihren Umgang mit der Softwareentwicklung dieser Realität anpassen.

Eine Lieferung von Funktionalität + Qualität + Wandelbarkeit innerhalb einer engen Zeitvorgabe funktioniert nicht verlässlich.

Softwareentwicklung ist kein Brotbackautomat, bei dem man vorhersagen kann, wann er nach Einfüllen der Zutaten das Brot fertiggestellt haben wird.

Die Schätzung der Dauer von Softwarevorhaben - von der relativ kleinen Änderung bis zur Neuentwicklung - im Sinne einer Vorhersage ist unmöglich.

Mit “unmöglich” meine ich hier: Vorhersagen werden regelmäßig, d.h. in mehr als 80% der Fälle, um 10%, 20% oder mehr verfehlt. Da hilft es auch nicht, beim nächsten Mal mehr Puffer einzurechnen.

Wenn sich bei Ihnen jetzt Widerstand regt, weil es in Ihrem Unternehmen, bei Ihren Projekten doch immer funktioniert… dann nehmen Sie meine Glückwünsche entgegen. Freuen Sie sich an diesem Erfolg. Überlegen Sie, ob Sie ein Buch über Ihr Rezept schreiben. Ich bin sicher, die Softwarewelt lechzt danach. Sie können reich werden.

Aber Spaß beiseite: Mir geht es weniger darum, ob es objektiv unmöglich ist, die Dauer von Softwareentwicklung vorhersagen zu können. Es mag möglich sein - nur kenne ich niemanden, der das verlässlich beherrscht.[1]

Ebenso will ich Ihnen Ihren Erfolg nicht ausreden. Wenn Sie das für mich Unmögliche schaffen sollten, dann erkenne ich das an - nur nützt das all den anderen Projekten nichts, in denen es nicht funktioniert.

Die schlichte Praxisrealität ist - zumindest in meiner Wahrnehmung über viele Projekte/Teams pro Jahr hinweg -, dass Aufwandschätzung in der Softwareentwicklung für die Vorhersage (!) nicht funktioniert. Sie ist entweder nicht in praxisrelevanter Breite möglich oder sie so schwierig, dass es wieder nicht praxisrelevant ist.

Wenn ich also dazu rate, es mit den Voraussageversuchen zu lassen, dann halte ich das für eine realitätsinformierte erwachsene Reaktion. Wenn es 50 Jahre lang nicht funktioniert, mit dem Kopf durch die Wand zu kommen, sollte man anfangen, die Tür zu suchen.

Ja, Manager und Kunden der Softwareentwicklung - wie auch viele Softwareentwickler selbst - scheinen mir manchmal in dem Witz gefangen, wo der Betrunkene nachts seinen Schlüssel unter der Laterne sucht - und nicht da, wo er ihn verloren hat.

Also: Vergessen Sie die Aufwandschätzung zur Vorhersage. Schätzung für den Vergleich sind hingegen ok - wenn Sie denn einen Vergleichswert, also Erfahrung haben.

  • “User Story A schätzen wir auf 5 Story Points, Story B auf 8.”
  • “System Y scheint grob mit System X vergleichbar. X haben wir in 5 Monaten realisiert. Dann wird Y wohl auch in überschaubaren Monaten umsetzbar sein und keine Jahre brauchen.”

Das sind vergleichende Schätzungen. Die können funktionieren - wenn man sich überhaupt ein Urteil erlauben darf. Aus Vergleichen leiten sich aber keine Termine ab. Hier geht es “nur” um Größenordnungen. Darum, ob zu erwartende Aufwände zur selben oder einer anderen Liga gehören.

Und selbst wenn man sich nur auf den Vergleich beschränkt, gibt es keine Gewissheit. Egal, wie klein man die zu schätzende Größe herunterbricht.[2]

Aber ich will endlich aufhören, mir den Mund fusselig zu reden. In diesem Artikel geht es mir ja um etwas anderes. Nämlich darum, wie Kunden und Manager mit dieser dreckigen Realität umgehen können.

Ein realistischeres Weltbild

Ok, also Schluss mit der Wahnidee “Softwareaufwände lassen sich verlässlich vorhersagen.” Schluss mit der ewigen Frage, “Wann könnt ihr X liefern?” Vor allem Schluss mit der Forderung, “Y muss bis dann und dann auf jeden Fall fertig sein.”

Ja, das tut weh. Ohne diese Pseudosicherheit - denn nicht mehr als das ist es ja - stellt sich ein Gefühl der Hilflosigkeit ein.

imageWelchen Gewinn der Wechsel des Fokus von “Fertigstellung” (completion) auf “Fortschritt” (progress) jedoch bringt, habe ich an anderer Stelle ausführlich beschrieben. Siehe dazu meine Artikelserie zu Spinning als Kern agilen Vorgehens. Wenn Software inkrementell “einfach wächst”, dann entsteht ein Strom von Releases, in den man jederzeit hineingreifen kann, um immer wieder Nützliches abzuschöpfen. Die Flexibilität, auf Prioritätenänderungen zu reagieren, steigt. Es entsteht plötzlich die Möglichkeit, sogar Geld zu sparen. Denn wer kleinschrittig in Inkrementen vorgeht, der kann nicht nur jederzeit seinen Kurs ändern, sondern auch anhalten, wenn der erreichte Stand gut genug ist.

Wer hingegen nur “alles und zwar sofort” denken kann… der muss auch immer für alles (und noch viel mehr) bezahlen. Gier und Ungeduld haben ihren Preis. Das war immer schon so. Die Softwareentwicklung kann dieser Wahrheit nicht entfliehen.

Aber auch Spinning möchte ich hier nicht noch einmal erklären. Mich hat vielmehr ein Bild ereilt, das ich Ihnen mitteilen möchte. Neulich habe ich für mich eine tauglichere Analogie für die Softwareentwicklung gefunden.

Das vorherrschende Bild von Softwareentwicklung vergleicht sie mit irgendeiner Form von Produktion. Da mögen andere das Gärtnern oder die Bergbesteigung dagegen halten. Es nützt nichts. Management und Kundschaft glauben, es handle sich bei der Softwareentwicklung - entgegen ihrer Bezeichnung als Entwicklung - um eine Form von Handwerksleistung. Ja, sogar Softwareentwickler wollen das glauben und bezeichnen sich lieber als craftsmen denn als engineers.

Aber auch wenn es selbstverständlich wahr ist, dass in der Softwareentwicklung handwerklich gut gearbeitet werden muss, ist die Analogie fundamental falsch. Weder ist Softwareentwicklung eine handwerkliche Einzelfertigung, noch eine industrialisierte Massenfertigung. Beides ist nämlich per definitionem Reproduktion und daher im Aufwand vorhersagbar.

In den letzten 100 Jahren scheinen wir in der westlichen Hemisphäre in einer durch Vorhersagbarkeiten gesicherten Welt gelebt zu haben. Allemal die aktuellen Entwicklergenerationen können sich an nichts anderes erinnern.

Der Trimuph des skalierten Handwerks, genannt Industrialisierung, ist offensichtlich. Da ist es verständlich, wenn nicht nur der Laie, sondern auch der Fachman glaubt und glauben will, dass Softwareentwicklung zu dieser Kategorie gehört.

Dabei besteht keine Not, alles der Reproduktion und Verlässlichkeit zu subsummieren. Menschen können mit Unverlässlichkeit umgehen. Historisch gesehen ist es wohl sogar die absolute Neuheit und damit Ausnahme, dass wir in so viel Verlässlichkeit eingebettet sind.

Ich habe also überlegt, ob es Beispiele für alternative Analogien für die Softwareentwicklung gibt. Können wir nicht mit einem Weltbild erfolgreicher sein, dass die real existierende Unvorhersagbarkeit umarmt? Gibt es vielleicht Beispiele dafür, dass Menschen auch in Unvorhersagbarkeit erfolgreich gewesen sind?

Und siehe da… tatsächlich können Menschen mit Unwägbarem, Unsicherem, gar hoch Risikobehaftetem umgehen.

Beispiel 1: Baseball

imageBeim Baseball wird ein Ball mit einem Schläger so geschlagen, dass er möglichst weit fliegt und nicht gefangen wird. Das versuchen Fänger im Spielfeld zu vereiteln. Wo ist die Unvorhersagbarkeit? Im Abschlag des Balls und in den Windverhältnissen. Wie der Schläger den Ball trifft - Geschwindigkeiten von Ball, Schläger, Winkel - und wie der Ball während des Fluges beeinflusst wird, ist für die Fänger nicht messbar. Sie müssen sich überraschen lassen. Die Fänger im Spielfeld können sich also nicht einfach dorthinstellen, wo der Ball landen wird. Auch wenn es sich um einen ballistischen Flug handelt, steckt das Ergebnis voller Überraschungen. Das macht den Reiz des Baseballspiels aus.[3]

Beispiel 2: Wetter

Das Wetter folgt einem Rhythmus (Jahreszeiten, Tag & Nacht). Wir haben also zumindest grobe Erwartungen an seine Entwicklung. Es gibt eine gewisse Vorhersagbarkeit. Im Detail - für die nächsten Stunden oder Tage - hat die sich sogar in den letzten Jahrzehnten erheblich verbessert.

Grundsätzlich jedoch ist das Wetter unvorhersehbar. Regenwahrscheinlichkeiten von 20% oder 50% sind keine Seltenheit, wenn man in seine Wetter-App schaut. Was soll man damit machen? Regenschirm mitnehmen oder nicht?

Aber wir haben gelernt, damit zurechtzukommen. Wir können einen Urlaub “erfolgreich durchführen”, auch wenn wir nur grob wissen, wie das Wetter sein wird.

Klar, es gibt Erwartungen: Wer im Sommer nach Italien fährt, erwartet dort keine drei Wochen Regen bei 15°. Und das wahrscheinlich zurecht. Dennoch… ununterbrochener Sonnenschein bei angenehmen 28° ist nicht garantiert. Heute in Zeiten des Klimawandels sogar weniger als früher, da das Wetter im Sommer immer schön war, wie wir uns alle erinnern.

Und nicht nur den Urlaub bewältigen wir trotz des Wetters. Wir können uns sogar ernähren. Wir haben gelernt, selbst mit größten Wetterüberraschungen zurechtzukommen. Wo früher Hungersnöte Landstriche leergefegt haben, da bleiben Menschen heute ungerührt.

Beispiel 3: Auktion

Bei einer Auktion ist ungewiss, wie hoch am Ende der Preis für einen Gegenstand sein wird. Ist das Fahrrad bei der Versteigerung im Fundbüro für 5€ oder 50€ zu haben? Kann man das Haus in der Zwangsversteigerung für 50.000€ oder 150.000€ “schießen”?

Das Auktionshaus mag einen Einstiegspreis setzen. Darunter geht es nicht - doch nach oben gibt es keine Grenze. Der Preis entwickelt sich vielmehr unvorhersagbar während der Auktion, selbst wenn man nach einer Vorbesichtigung eine Idee der “Preis-Liga” gewonnen hat. Und damit können alle Bieter leben.

Beispiel 4: Der Markt

Ist der Markt, auf dem Ihr Unternehmen agiert vorhersagbar? Kaum. Sie mögen Erwartungen haben… aber es gibt keine Garantie. Da können sich Manager Quartalsziele setzen wie sie wollen. Am Ende ist der Markt immer unzuverlässig.

Für den Absatz von Nutella mag er weniger schwanken als für den Absatz von Autos. Oder umgekehrt. Letztlich gibt es aber keine Garantie, nichts kann erzwungen werden. Und dennoch überleben Lieferanten - allerdings umso schlechter, je unflexibler sie sind. Mehr “Planwirtschaft” erzeugt mehr Schmerzen.[4]

Beispiel 5: Aktienbörse

imageNach all diesen Beispielen nun noch mein Lieblingsbeispiel, das Bild, das mich ereilt hat.

An der Aktienbörse ist Vorhersagbarkeit notorisch abwesend - und dennoch zieht es ständig Menschen dorthin. Denn wo viel Unvorhersagbarkeit, da viel Gewinn, wenn es doch mal klappen sollte. Das Risiko lockt.

Wer sich an der Börse behauptet, der agiert jedoch nicht ignorant. Der lernt, mit Risiko umzugehen. Er weiß, dass er nicht auf den einen großen Coup setzen kann, sondern seine Gewinne und Verluste ausbalancieren muss.

Natürlich gibt es wie beim Wetter und dem Markt an der Aktienbörse Muster. Doch die scheinen nur vergleichsweise wenigen bekannt. Die Masse bewegt sich dort wahrscheinlich eher im Unvorhersehbaren - und hat gelernt, trotzdem erfolgreich zu sein.

Von Siegern und Überlebenden lernen

Menschen können erfolgreich sein im Angesicht von Unvorhersagbarkeit. Manchmal suchen sie die Unwägbarkeit sogar auf. Sie verlassen die Geborgenheit der Berechenbarkeit bewusst, weil die ihre Chancen begrenzt. In anderen Fällen gibt es keine Alternative. Da ist das Leben trotz aller Bemühungen eben unvorhersagbar. Wie zum Beispiel in der Softwareentwicklung.

Auch in der Softwareentwicklung gibt es Muster. Um Feiertage herum oder in der Urlaubszeit wird wahrscheinlich weniger geschafft als zu anderen Zeiten. Die Softwareentwicklung hat also auch eine Jahreszeitlichkeit. In diesen Rhythmus grätschen dann allerdings z.B. Krankheiten hinein.

Und es lässt sich natürlich auch eine gewisse “Wetterentwicklung” feststellen: Wenn es an einem Feature schon 2–3 Tage gut voran gegangen ist, dann ist es vielleicht recht wahrscheinlich, dass es auch zügig weitergeht. Morgen ist mit 60% Wahrscheinlichkeit wieder solches Wetter wie heute - mit 40% Wahrscheinlichkeit jedoch eben nicht. Und so kann sich das Blatt bei der Featureumsetzung auch von heute auf morgen wenden. Wie lange es bis zu Fertigstellung braucht… nicht vorhersagbar. Genausowenig, wieviele Tage hintereinander die Sonne scheinen wird.

Also nocheinmal: Let´s get real. Wer als Manager oder Kunde mit der Softwareentwicklung umgeht, sollte nicht an Handwerk denken, sondern an Aktienbörse.

Wer insofern an das Eintreffen einer Aufwandschätzungsvorhersage glaubt und darauf seine Planung ausrichtet, der wettet. Er geht ein Spekulationsgeschäft ein. Er tut genau das, was wir von unseren Banken immer weniger wollen. Und er wähnt sich im selben Glauben, die Sache im Griff zu haben - bis ihm die Sache um die Ohren fliegt. Dann heißt es, den eigenen Arsch retten und den Schaden begrenzen.

Wer das besser machen möchte, der sollte von den Siegern an der Aktienbörse und den Überlebenden der Evolution lernen. Die haben Strategien entwickelt, die uns in der Softwareentwicklung nutzen können.

Strategie 1: Sense & adapt

Vom Baseball-Spieler im Feld können wir lernen, dass Erfolg davon abhängig ist, sich einer Entwicklung anzupassen.

Natürlich rennt der Fänger nicht in einer beliebigen Richtung und auch noch vor Abschlag des Balls los. Er wartet vielmehr, ob der Ball grob in seine Richtung fliegt. Er beobachtet also zunächst. Und dann… dann berechnet er nicht einen Aufschlagort für den Ball und rennt direkt in dessen Richtung. Vielmehr folgt er dem Ball mit einem ständigen Blick darauf. Er läuft keine Gerade, sondern folgt einer Kurve - die ihn umso eher zu einem erfolgreichen Rendevouz mit dem Ball bringt, je besser er beobachtet und seinen Lauf korrigiert. Dazu braucht er Erfahrung und Fähigkeit.

imageErfolg ist im Baseball der Fang des Balls, nicht die Einhaltung eines Zeit- oder Kraftbudgets.

Natürlich hilft es dem Spieler, sich bei jeder Ballverfolgung ökonomisch zu verhalten, um das Spiel durchzuhalten. Deshalb definiert er jedoch keine Aufwände vorab. Das wäre im wahrsten Sinn des Wortes nicht zielführend.

Der gefangene Ball zählt. Übersetzt bedeutet das: Software in ausreichender Funktionalität + Qualität + Wandelbarkeit herzustellen, das zählt. Nicht die Einhaltung eines Budgets.

Das Budget gibt nur vor, wie lange man das tun kann, aber nicht, wie weit man dabei kommt. Genauso gibt das Baseball-Spielfeld vor, wie weit man dem Ball folgen kann - ohne Garantie, dass man ihn innerhalb des Spielfeldes auch fängt.

Das einzig Gewisse ist also der Rahmen, in dem man durch ständiges Beobachten und Anpassen versuchen kann, dem Erfolg so nahe wie möglich zu kommen.

So lautet auch der Standpunkt der Agilität. Eigentlich. Wenn man sie denn mutig genug lebt. Dann verzichtet man nämlich darauf, Story Point Schätzungen in Termine zu übersetzen.

Die Beobachtung-Anpassung-Runden heißen in der Agilität Iterationen. In Scrum sind es die Sprints. Beim Spinning allerdings dauern Sie nur wenige Stunden oder maximal vom Morgen des einen Tages bis zum Abend des nächsten.

Nach jeder Iteration kann der Kurs geändert werden, weil in Inkrementen vorgegangen wird. Jede Iteration produziert etwas mehr Nutzen oder zumindest Gewissheit, was das Verständnis der Anforderungen angeht.

Leider ist diese Strategie noch nicht bei Management und Kunde angekommen. Da mögen die Teams noch so sehr PO-Feedback getrieben dem Ball hinterherlaufen - draußen glaubt man weiterhin daran, dass der Fang berechnet werden könne.

Strategie 2: Limits

imageEin Bieter hat in zwei Fällen Erfolg bei einer Auktion. Wenn er ein Auktionsstück zu einem guten Preis ersteigert - aber auch, wenn er nichts ersteigert, weil er seinen Ausgabewillen begrenzt hat.

Noch mehr gilt das an der Börse. Aufträge sollten dort immer mit Limits versehen werden. Ein Stop Buy Limit verhindert, zu teuer zu kaufen, in dem man zu lange kauft. Ein Stop Loss Limit verhindert, (zu viel) Verlust zu machen, in dem man zu lange auf seinen Aktien sitzt.

Stop Loss kann dabei in zwei Richtungen interpretiert werden. Naheliegend ist, dass es greift, wenn der Kurs unter eine gewisse Marke fällt. Aber man kann es auch so sehen, dass es greift, wenn der Kurs über eine gewisse Marke steigt. Dann wäre es sozusagen ein Start Reaping Limit, bei dem man automatisch verkauft. Ganz unemotional. Denn es gilt ja: Nicht realisierte Gewinne sind keine Gewinne.

Limits sind im Umgang mit der Softwareentwicklung unbekannt, wie es mir scheint. Wie denn auch: Wo nicht beobachtet wird, kann man auch nicht die Überschreitung von Limits beobachten.

Außerdem braucht man für Limits eine Vorstellung von Wert. Da der für Anforderungen unterschiedlicher Größenordnungen notorisch nicht bestimmt wird, kann man weder ein Limit definieren, noch den aktuellen Wert.

Die Gesamtvorstellung einer Software mag man mit einem Wert belegen. Deshalb kann man dann das eine Angebot zu teuer finden und beim anderen den Zuschlag geben.

Anschließend wird vor allem über Aufwand gesprochen. Der muss auf die eine oder andere Weise für Vergleiche, aber noch besser für Voraussagen geschätzt (gemeint ist: berechnet) werden. Ihm wird jedoch nur äußerst selten ein objektivierter Nutzen oder Wert gegenübergestellt.

Deshalb sind Priorisierungen vor allem eine Sache des Gefühls. Denn ohne objektiven, wenn auch geschätzten Aufwänden genauso objektiven Wert gegenüberzustellen, kann sich keine nachvollziehbare Priorität ergeben.

Dieses Gefühl hat ein Product Owner oder es wird lautstark vom Support oder dem Management vermittelt. So rennt denn ein Team solange Gefühlen hinterher, bis sich andere Gefühle einstellen. Systematisch ist das nicht. Budgetschonend auch nicht.

Sobald man jedoch den Wert umzusetzender Anforderungen in einiger Feinheit bestimmen kann, ist es möglich, Limits zu definieren.

Und wenn man Limits hat, dann kann man aufhören, wenn genügend Wert für den Moment angesammelt ist. Man kann dann wieder ausliefern. Nicht nur festgelegt alle Jahre oder Quartale, sondern eben jederzeit, wenn die Wertsteigerung aus Sicht des Kunden, des Vertriebs oder sonst eines Stakeholders attraktiv ist.

Für die Softwareentwicklung gilt: Nicht ausgelieferte Inkremente generieren keinen Umsatz.

Außerdem gilt, dass alles, was umgesetzt und sogar ausgeliefert wurde, aber nicht genutzt wird, nichts nützt und deshalb Verschwendung ist.

Solche Verschwendung lässt sich nicht grundsätzlich vermeiden. So wie sich bei einer Auktion nicht vermeiden lässt, etwas zu teuer zu kaufen oder nur knapp vor dem Zuschlagspreis ausgestiegen zu sein. Ebenso lässt sich an der Börse nicht vermeiden, den optimalen Kurspreis für Kauf oder Verkauf zu verpassen.

Aber je breiter das Risiko gestreut wird, desto geringer der Verlust. Je kleiner die Inkremente, je häufiger das Feedback, desto eher ist es möglich, Verschwendung einzudämmen.

Auch hier hilft wieder der Ansatz des Spinning. Dort werden Anforderungen so dünn geschnitten, dass Feedback innerhalb von 1–2 Tagen Verschwendung minimiert. Keine Anforderungen “in der Urfassung” muss mehr fertiggestellt werden. Vielmehr kann man nach jedem Inkrement wieder evaluieren, ob es lohnt, weiter zu investieren (nachkaufen) - oder doch besser auszusteigen (verkaufen).

Die Evaluation kann z.B. nach dem Verfahren Weighted-Shortest-Job-First (WSJF) erfolgen. Dafür ist es nicht einmal erforderlich, absolute Beträge für Wert und Aufwand zu kennen. Anforderungsgewichte berechnet aus Anforderungsnutzen (Wert) und Realisierungsaufwand dienen nicht der Vorhersage, sondern nur dem Vergleich.

Die sich aus der Gewichtung ergebende Reihenfolge (Priorität) von Anforderungen kann sich ständig ändern. Gearbeitet wird immer nur an dem, was schon/noch genügend Wert pro Aufwand verspricht.

Das bedeutet: “Absolute” Fertigstellung tritt in den Hintergrund. Nicht eine (größere) Anforderung komplett fertigstellen, sondern mehrere parallel vorantreiben. Am Ende reißt nicht ein Feature eine Software heraus, sondern der Mix genügend guter Features.

Strategie 3: Puffer aufbauen

Das Baseballspiel lehrt, “am Ball bleiben” und den Entwicklungskurs ständig korrigieren. Die Börse lehrt, Werte bewusst zuordnen, Grenzen setzen und das Risiko zu streuen.

imageUnd der Umgang mit dem Wetter lehrt: man muss Reserven haben. Wer die Speicher voll mit Gepökeltem, Eingemachtem, Getrocknetem und auch noch Brennholz hat, muss sich um eine schlechte Ernte oder einen langen Winter nicht so viele Sorgen machen.

Die Entsprechung dafür in der Softwareentwicklung ist aber nicht Zeit, wie man meinen könnte. Zeitpuffer sind für mich keine, weil sie schon bei der Planung als ausgeschöpft angesehen werden. Nein, wir brauchen andere Puffer. Puffer, die Softwareherstellung und die Softwarenutzung bzw. den Vertrieb entkoppeln.

Wie bei Getreidespeichern sollte der Puffer dabei aus dem bestehen, was die eine Seite (Natur) produziert und die andere Seite (Mensch) konsumiert.

Zeit ist das nicht. Weder produziert die Softwareentwicklung Zeit, noch konsumieren Vertrieb oder Kunden Zeit. Das Gut, um das es geht, sind vielmehr Softwaremerkmale (Features).

Angesichts des unvorhersagbaren Softwareentwicklungswetters brauchen wir Puffer an umgesetzten Anforderungen. Das halte ich für ein notwendiges Umdenken. Kunden/Management (oder auch der Vertrieb) müssen sich Puffer an schon Realisiertem anlegen.

Statt die Softwareentwicklung zu einer Vorhersage zu nötigen, wann ein bestimmter Wert geschaffen sein wird, sollte geschaffener Wert “eingelagert” werden, statt ihn immer sofort zu konsumieren.

“Live in the now” muss das Motto werden. Es geht um das, was sicher “im Sack” ist. Das kann man bewerben, vorführen, verkaufen. Alles andere sind “Wunschgewinne” - die können eintreten oder nicht. Und wer weiß, wann?

image

(Im Bild hat das Entwicklerteam Releases in den Puffer “eingelagert”. Aus dem entnehmen Interessenten, wenn Sie es brauchen, also entsprechend einem Vorlauf für ihre Maßnahmen. Sie haben keinen Einfluss auf die Einlagerung zu einem absoluten Termin. Sie können nur mit dem arbeiten, was sie vorfinden. Die Entwicklung zieht unterdessen weiter. Allerdings: Prioritäten, also relative Fertigstellungstermine, dürfen der Entwicklung vorgegeben werden.)

Ob das nächste Jahr eine Spitzenernte abwerfen wird? Niemand weiß das. Ob die Aktie bis Monatsende den Wunschkurs hat? Niemand weiß das.

Was man weiß, das ist, was jetzt da ist. Damit lässt sich arbeiten. Ganz verlässlich.

Aus dem Strom der ständig geschaffenen Werte sollte also ein Teil in einen Puffer geleitet werden. Der andere Teil steht zum sofortigen Konsum zur Verfügung.

Geldgewinne spart man oder reinvestiert. Nicht alles, aber einen Teil. Ernteertrage lagert man zum Teil ein und verzehrt den Rest.

Genauso sollte mit dem Strom an Werten in der Softwareentwicklung umgegangen werden.

Konsequenzen für Kunde/Management

Wer im Wahn lebt, also in Verkennung der Realität, kann nicht auf Dauer erfolgreich sein. Oder etwas attraktiver formuliert: Umso näher Weltbild und damit Handeln der Realität sind, desto größer der Erfolg.

Seefahrt, Medizin, Maschinenbau sind erfolgreicher geworden, indem sie sich der Realität angenähert haben. Weniger Wunschvorstellung und Glaubenssatz, dafür mehr Fakten.

Das scheint mir für die Softwareentwicklung auch ein Erfolgsrezept. Die Agilität hat in dieser Hinsicht eine Wende eingeleitet. Angekommen ist die bei Kunde und Management jedoch noch nicht. Es herrschen noch Wunschvorstellungen, Missverständnisse und Ignoranz bzw. Naivität vor.

Um das noch besser zu vermitteln, dürfen wir keine Gelegenheit verpassen, um die Idee eines realitätsnäheren Weltbildes zu verbreiten.

In dem müssen Nachhaltigkeit und Unvorhersagbarkeit verbunden werden.

Dafür scheinen mir gerade der Umgang mit dem Wetter und die Aktienbörse gute Beispiele.

In beiden Sphären sind die Veränderungen nicht vorhersagbar - und dennoch ist nachhaltiges Handeln wichtig. Sonst ist man bald tot oder pleite.

Erste Konsequenz für Kunde/Management: das Weltbild anpassen. Get real! Now!

Zweite Konsequenz: Abschied von der “fire and forget” Mentalität. Anforderungen laden, Ziel anpeilen, abfeuern - und dann auf den Einschlag warten… Das funktioniert nicht. Der PO weiß das schon. Eigentlich. Bis auf manche. Kunde, Management, Vertrieb, Marketing allerdings, die müssen das noch lernen. Vielerorts.

Dritte Konsequenz: Abschied von der “Ich will Alles! Und das sofort!” Mentalität. Denn ob Alles machbar ist innerhalb des Budgets oder ob Alles überhaupt gemacht werden sollte… Wer wollte das mit Sicherheit sagen? Die Verschwendung lauert überall. Also muss eine viel bewusstere Wertvorstellung entwickelt werden. Das bedeutet, mehr Werte bestimmen, doch das bedeutet auch, Werten Grenzen setzen. Denn ohne Grenzen regiert Maßlosigkeit.

Vierte Konsequenz: Abschied von der Zukunftsfixierung. Der Erfolg stellt sich nicht durch Wahrsagerei ein. Die Glaskugel der Softwareentwicklung ist genauso trüb wie die einer Zigeunerin auf dem Jahrmarkt. Wer viel fragt, bekommt viele Antworten, die er hören will - die deshalb aber nicht etwas mit der zukünftigen Realität zu tun haben.

Das Glück liegt in der Gegenwart, in dem, was ist. Der Spatz in der Hand, das ist Erfolg. Die Taube auf dem Dach fliegt weg, bis man dorthin geklettert ist.

Kunde, Management, Vertrieb, Marketing sollten lernen, mit dem zu arbeiten, was real existierend ist. Alles andere sind Wunschvorstellungen einer märchenhaften Zukunft.


  1. Wohlgemerkt geht es mir nicht nur um die sichtbaren Aufwände. Es gibt immer wieder Vorhersagen, die sich äußerlich mit nur wenig Verzug wahr machen lassen. Die dem unbewaffneten Auge sichtbaren Budgets werden kaum überschritten. Ein unbekannt hoher Preis wird dann jedoch woanders bezahlt: bei der Motivation und der inneren Codequalität. Wer Termine durchprügelt mit Überstunden und/oder durch Vernachlässigung von Clean Code Development, der zahlt später. Auf die eine oder andere Weise. Das muss dem Gesamtaufwand zugeschlagen werden. Nur tut das niemand. Es ist so schwer zu fassen. Außerdem ist das dann womöglich das Problem von jemandem anderes. Womit wir wieder bei der Deutschen Bahn wären. So funktioniert nachhaltiges oder wirklich kundenorientiertes Denken nicht. Wer nur an jetzt und sich denkt, arbeitet auf Kosten der Zukunftsfähigkeit von Projekt/Produkt oder gar Unternehmen.

  2. Bitte verstehen Sie mich richtig: Es gibt kaum etwas, was ich mir sehnlicher für die Softwareentwicklung wünsche, als dass sie vorhersagbarer würde. Ehrlich. Der Gewinn an Vertrauen und Effizienz wäre unschätzbar [sic!]. Aber, ach, ich habe es aufgegeben, es zu versuchen und darauf zu warten. Mag es einem zukünftigen goldenen Zeitalter des Software Engineering vorbehalten sein, solche Verlässlichkeit herzustellen.

  3. Bei einem Kanonenschuss will man natürlich das Gegenteil erreichen. Der soll genau in ein anvisiertes Ziel treffen. Letztlich findet man diese Vorhersagbarkeit jedoch limitierend. Immer mehr interessante Ziele bewegen sich. Deshalb ist ein Lenkgeschoss die überlegene Waffe. Und heutige Drohnen gehen noch einen Schritt weiter. Das Militär hat also viel investiert, um stetig besser mit der unvorhersagbaren Realität der Bewegungen seiner Gegner umzugehen.

  4. Wie bei der Softwareentwicklung werden hier Vorhersagen (also Vorgaben) oft zwanghaft erreicht, indem an weniger sichtbarer Stelle Kosten verursacht werden. Mitarbeiterfluktuation, Burn-out, Dienst nach Vorschrift, sinkende Kommunikationsverlässlichkeit, Papierberge uvm. können Symptome dafür sein, dass man mit dem falschen Weltbild, also im Wahn agiert - und sich deshalb an der Wand die Nase blutig stößt.

Samstag, 28. Juni 2014

Regelmäßiges Lernen - Mein Commitment

imageGute Softwareentwicklung gibt es nicht ohne regelmäßiges Lernen. Technologisch bleibt man sonst immer weiter zurück. Aber auch neue Methoden können sonst nicht wirklich eingeführt werden.

TDD, Clean Code, NoSql, Reactive Programming, F# oder was sich sonst noch nützlich auf die Softwareproduktion auswirken könnte, kann man nicht im Kopf anschalten. Dafür braucht es vielmehr Zeit, um zu lesen, zu denken, zu üben, bevor man es in den Alltag der Produktionscodeentwicklung übernehmen kann.

Ich glaube, 20% Lernzeit während (!) der Arbeitszeit wären gut. Mehr als 10% scheinen in den allermeisten Unternehmen jedoch nicht machbar. Dann also 10% - aber nicht weniger!

Diese 10% können aus autodidaktischem Lernen für sich, Lernen in der Gruppe und Teilnahme an Kursen bestehen. Einer meiner Kunden stellt seinen Entwicklern z.B. 150 Stunden pro Jahr für das Lernen zur Verfügung. Das sind ca. 10% der Arbeitszeit, wenn ich mal 200 Arbeitstage à 8 Stunden rechne. Allerdings verplant man diese 150 Stunden in Form von Seminarteilnahmen. Das ist gut gemeint - aber kontraproduktiv. Denn wann soll denn das, was man im Seminar lernt, geübt werden? Seminarteilnehmer können ja nicht nach 2–3 Tagen Seminar, was als Lernstoff vermittelt wurde. Dafür ist unser Metier zu kompliziert. Unser Lernstoff muss geübt werden. Und nochmal geübt werden. Bevor man ihn halbwegs sicher auf Produktionscode anwenden kann.

Kein Musiker probt auf der Bühne. Kein Chirurg lernt neue Techniken am gewöhnlichen Krankenhauspatienten. So sollte es auch bei der Softwareentwicklung sein. Es braucht für Neues geschützte Übungszeit. Regelmäßig.

Das fällt schwer. Das höre ich immer wieder. Es passt einfach nicht zum vorherrschenden Mindset der 110% Auslastung aller Mitarbeiter mit Tagesgeschäft. Doch es hilft nichts. Wer nachhaltig “wirtschaften” will, der muss dafür Zeit zur Verfügung stellen. Und nicht nur fürs Lernen.

Nun mag man sagen, “Ralf, du hast gut reden. Als Berater/Trainer ist dein Leben viel einfacher. Du kannst dir Zeit nehmen, wie du willst.”

Aber das stimmt nicht. Auch ich habe ja mein Tagesgeschäft. Klar, das sieht anders aus als das eines Entwicklungsteams. Von den Prioritäten her fühle ich mich da allerdings genauso eingeengt. Für einen Entwickler mag es aussehen, als würde ich ständig lernen. Ist nicht ein Buch über Softwareentwicklung lesen, einen Artikel schreiben, ein Seminar vorbereiten Lernen?

Das stimmt in Bezug auf die Softwareentwicklung. Es stimmt aber nicht in Bezug auf die Vermittlung von Softwareentwicklung. Was für Entwickler Lernen ist, ist für mich Tagesgeschäft.

Das verwechsle ich allerdings auch oft. Deshalb muss ich einsehen, dass selbst ich, nicht genug lerne. Ich lebe sozusagen selbst noch nicht das, was ich predige. Das ist Mist. So kann ich meine Überzeugung nicht authentisch vermitteln. I need to put my money where my mouth is :-)

Das Lernversprechen

imageDas will ich, nein, das muss ich nun ändern. Da geht kein Weg dran vorbei, wenn ich als One Man Think Tank weiterhin glaubwürdig sein will. Also lege ich hier ein Versprechen ab.

Ich verspreche, dass ich fortan mindestens 10% meiner Arbeitszeit[1] dem Lernen widmen werde.

Dieses Lernen kann im Besuch von Vorträgen oder Seminaren bestehen, das kann aber auch Lesen und Üben daheim sein.

Da mein Job die Vermittlung von Softwareentwicklungsmethodiken ist, können Lerninhalte natürlich nicht Softwareentwicklungsmethodien sein. Mein Lernen muss vielmehr auf der Meta-Ebene bzw. im Allgemeineren stattfinden.

Oder ich könnte auch sagen: Ich muss beim Lernen dasselbe Gefühl haben, wie meine Kunden. Einerseits muss ich es wollen, andererseits muss es mir aber auch wehtun. Auch ich muss beim Lernen spüren, dass ich eigentlich etwas anderes dringender tun müsste.

Aktivitäten auf die das für mich zutrifft, sind z.B. eine Sprache lernen, Meditation, die Beschäftigung mit “Sachthemen”.

Für Sie mögen das Freizeitaktivitäten sein, für mich gehört das jedoch im weiteren Sinn zum Job:

  • Mein Job ist es, mit Sprache umzugehen, sowohl mit natürlicher wie mit formaler. Auf die eine oder andere Weise. Deshalb ist es wichtig, dass ich meinen “Sprachmuskel” fit halte. Jede Sprache, die ich lerne oder deren Kenntnis ich verfeinere, macht es mir leichter, zu kommunizieren, was ich vermitteln will.
  • Mein Job ist es, mich vielen Einflüssen auszusetzen und oft zu reisen. Innere Ruhe und Gelassenheit sind dann wichtig, um in dem Rahmen eine balancierte und authentische Botschaft zu vermitteln. Medidation und die Beschäftigung mit spirituellen Themen hilft, diesen Zustand herzustellen.
  • Die Softwareentwicklung profitiert davon, sich durch andere Disziplinen oder sogar ganz allgemein “durch das Leben” informieren zu lassen. Bauarchitektur, Biologie, Physik, Soziologie usw. halten viel bereit, von dem wir lernen können. Darüber hinaus kann meine didaktische und methodische Praxis als Trainer nur davon profitieren, wenn ich mich in anderen Bereichen umschaue (z.B. systemische Analyse, Lernpsychologie). Ich muss also “Sachthemen” erkunden - und das durchaus, ohne immer genau zu wissen, wann ich welches wie anwenden kann. Sozusagen Grundlagenforschung statt angewandte Forschung.

Natürlich habe ich in der Vergangenheit diese Aktivitäten schon betrieben - nur nicht systematisch. Da war es Freizeit und ich konnte jederzeit damit aufhören. Nun will ich das ändern. Darin besteht mein Commitment.

Ich verspreche, jede Woche mindestens 4 Stunden wie folgt ins Lernen und Üben zu investieren:

  1. Sprachenlernen: Ich widme jeden Arbeitstag 20–30 Minuten dem Lernen einer Sprache. Derzeit ist das Französisch. 5x20=100 Minuten, d.h. 1,66 Stunden.
  2. Meditieren: Ich mediere jeden Tag 10–15 Minuten. 7x10=70 Minuten, d.h. 1,16 Stunden.
  3. Sachthemen: Ich lese jeden Arbeitstag 15–30 Minuten über ein Sachthema. 5x15=75 Minuten, d.h. 1,25 Stunden. Dazu mögen über das Jahr verteilt Konferenzen oder Seminare kommen, wo ich mich en bloc länger mit einem Thema befasse. In diesem Jahr waren das z.B. schon eine Konferenz zum Thema Unternehmertum und ein Seminar über Prozessmanagement.

Das sind Aktivitäten, von denen ich weiß, dass sie für mich wichtig sind. Ich muss hier regelmäßig am Ball bleiben. Dennoch fällt es mir schwer, sie auch ständig während des Tagesgeschäftes auf dem Zettel zu haben.

Jeden (Arbeits)Tag 15–30 Minuten mit so einer Aktivität verbringen, führt das denn zu Fortschritt? Ja, das glaube ich ganz sicher. Nicht kurzfristig, aber mittel- und langfristig. Es gibt ja auch keine Rüstzeiten und spezieller “mental state” muss auch nicht aufrechterhalten werden. Außerdem steht es mir jederzeit frei, mehr Zeit einer dieser Aktivitäten einzuräumen.

Soviel zu meinem Versprechen. Und wie dokumentiere ich, dass ich es einhalte?

Ich benutze die App Lift, um die Durchführung zu protokollieren.

imageimage

imageimage

Nach Abschluss einer Aktivität hake ich sie in der App ab. Das an sich ist schon ein kleiner Erfolg. Noch motivierender ist es jedoch, in der Übersicht zu sehen, wie kontinuierlich ist dabeigeblieben bin.

Wer mag, kann meinen Fortschritt verfolgen. Ich habe die lift-Aktivitäten öffentlich gemacht:

Spätestens in 3 Monaten berichte ich dann hier, wie es mir mit der Erfüllung meines eigenen Anspruchs ergangen ist. (Dass ich unterwegs nicht mogle, müssen Sie mir glauben. Ich mache also nur einen lift-Haken, wenn ich wirklich eine Aktivität durchgeführt habe.)

Und nun: Ich bin genauso gespannt wie Sie :-)

Let the learning begin…


  1. Meine Arbeitszeit ist nicht so klar abgezirkelt wie die eines Angestellten. Als Freiberufler bin ich sehr frei, was Zeit und Datuer meiner Arbeit angeht. Außerdem verschwimmen Arbeit und Freizeit bei mir. Mein Versprechen bezieht sich der Einfachheit halber auf eine 40 Stunden Woche. Ich verspreche also 4 Stunden Lernen pro Woche.