Liegt die Zukunft der Softwarearchitektur in Emergent Architecture und Growing Software? Diese Frage wurde in zwei Open Space Gruppen auf der SoCraTes Konferenz 2011 behandelt. Das hat mir gefallen, da ich ja mit meinen Softwarezellen auch schon einmal eine naturnahe Metapher gewählt hatte.
In den Diskussionen wurde ich das Gefühl jedoch nicht los, dass wir bei allem Appeal der Metaphern noch zu wenig darüber nachgedacht hatten, was es denn wirklich heißt, naturnah Software entstehen zu lassen. Wie entwickeln sich natürliche Systeme? Was lässt sich davon auf Softwareentwicklung übertragen? Welche Voraussetzungen sind nötig?
Struktur entspricht gegenwärtiger Umwelt
Ganz zentral für naturnahe Softwareentwicklung ist, dass wir die Rolle der Umwelt richtig verstehen. In der Natur ist alles so wie es ist, weil es so am besten zur Umwelt passt. Das ist der Kerngedanke der Evolutionstheorie, würde ich sagen. Alles an allen Organismen hat einen Zweck, den es erfüllt, so wie es ist. Da ist nichts zuviel, nichts zuwenig.
Vor allem ist nicht so entwickelt wie es ist auf Vorrat. Alles ist nur einer gegenwärtigen Umwelt mit ihren über Generationen erfahrenen Schwankungen angepasst. Kein Lebewesen besitzt eine Eigenschaft nach dem Motto “Aber was wäre, wenn Umweltparameter X in der Zukunft ganz anders aussehen würde?”
Leben ist insofern “lean”, d.h. frei von “Fett”. Es gibt keine “Eigenschaftenpolster”. Selbst die Anpassungsfähigkeit ist begrenzt, obwohl sie die wichtigste Metaeigenschaft ist.
Wenn wir wirklich naturnah Software entwickeln wollen, dann müssen wir konsequent auf den Blick in die Glaskugel verzichten. Erfahrung, die uns verleitet zu sagen, “Aber ich weiß doch, dass Kunden in den meisten Fällen noch Y wollen…”, darf nicht zu Anreicherungen in der Software führen. Das höchste der Gefühle ist, dem Kunden einen solchen Gedanken vorzulegen, um durch seine Antwort die gegenwärtige Umwelt besser zu verstehen. Das oberste Prinzip naturnaher Entwicklung ist mithin YAGNI.
Jede Entscheidung darf sich nur vom gegenwärtigen Kenntnisstand leiten lassen. Dann ist die Entscheidung erstens schnell getroffen und zweitens das Ergebnis so schlank wie möglich.
Evolution ist ohne Ziel
Wenn Evolution sich nur an der gegenwärtigen Umwelt orientiert, dann bedeutet das in verschärfter Formulierung, dass Evolution kein Ziel hat. Und das bedeutet, Evolution kann nicht vorplanen. Es gibt kein Vordenken, sondern nur Reaktion, Anpassung. [1]
Das bedeutet für die Softwareentwicklung ein viel größere als bisher übliche Konzentration auf das Hier und Jetzt. Geradezu buddhistisch muss für naturnahe Entwicklung gelten “live in the now”.
Weder Strukturen noch Schritte sollten über das unmittelbar Sichtbare und Notwendige hinaus ausgelegt sein. Zu YAGNI tritt KISS als Leitprinzip.
Evolvierbarkeit ist ein Ergebnis von Evolution
Als Ergebnis der Evolution sehen wir vor allem die umweltangepassten Eigenschaften von Lebewesen. Wir haben verstanden, dass diese Eigenschaften sich durch Feedback ausprägen. “Survival of the fittest” nennen wir das. Eigenschaften entstehen und müssen sich gegenüber der Umwelt behaupten. Passen sie nicht, sinkt die Wahrscheinlichkeit zur Weitergabe der Eigenschaften an die nächste Generation; unpassende Eigenschaften sterben aus. Das Feedback der Umwelt ist gnadenlos.
Auf die Software haben wir das inzwischen in Form iterativen Vorgehens übertragen. Wir stellen Software mit bestimmten Eigenschaften her, von denen wir meinen, dass sie zur Umwelt (den Anwendern) passen – und suchen dann das Feedback der Umwelt. So nähern nähern wir die Eigenschaften in kleinen Schritten der Umwelt an bzw. co-evolvieren Software mit der Umwelt.
Hinter den sichtbaren Eigenschaften evolvierender Systeme gibt es allerdings noch eine unsichtbare Eigenschaft: die Evolierbarkeit. Wie jede Eigenschaft unterliegt auch sie einem Zwang zur Passgenauigkeit.
Meinem Empfinden nach haben wir diese Eigenschaft als ebenfalls zu entwickeln nicht auf dem Zettel. Wir unterwerfen sie in unseren Projekten keinem Feedback. Wir unterwerfen sie nicht einmal branchenweit einem Entwicklungsdruck (oder allenfalls einem nur vergleichsweise schwachen).
Wenn wir über naturnahe Softwareentwicklung sprechen, ist das eine große Nachlässigkeit, da im Kern der gesuchten Naturnähe ja gerade die Evolvierbarkeit steht.
Wie müsste also das Feedback aussehen, um Evolvierbarkeit zu entwickeln?
Ob unsere Software schon performant, skalierbar, sicher genug ist, stellen wir fest, indem wir sie immer wieder auf die Probe stellen. “Los, zeig uns, wie schnell du bist!”, “Ha! Kommst du auch mit dieser größeren Nutzerlast zurecht?”, “Nimm diese Sql Injection Attacke, du Software, du!”
Aber wie ist es mit der Evolvierbarkeit? Was ist eine Herausforderung für sie?
Ich denke, das sollte auf der Hand liegen: Evolvierbarkeit wird durch unerwartete Anforderungen auf den Grill gelegt. “Pass dich dieser überraschenden Anforderung an, Code!”
Das erste, was Evolution lerne musste war die Unvorhersehbarkeit der nächsten Umweltveränderung. Von der hat sie ihre grundlegenden Bausteine, die Moleküle (DNA, RNA), Organellen und Zellen formen lassen. So existiert Leben am tiefsten Meeresgrund genauso wie im Darm und auf dem Mount Everest.
Für die Softwareentwicklung ist das noch eine Aufgabe, denke ich. Unsere grundlegenden Bausteine sind noch nicht wirklich evolutionsunterstützend. Allemal können wir noch viel zu leicht anti-evolutionäre Strukturen damit herstellen, wie die Massen an Brownfield-Code zeigen.
Das bedeutet, wir müssen mehr Druck auf die Evolvierbarkeit ausüben. Sonst hinkt ihre Entwicklung der anderer Eigenschaften hinterher – und behindert deren Evolution. Wir müssen also geradezu auf die Evolvierbarkeit zuallererst Evolutionsdruck ausüben, weil sie für alles andere fundamental ist. Wie soll das aber geschehen?
Nach meinem Gefühl ist das gar nicht schwer. Wir müssen erstens die Frequenz der Änderungsanforderungen drastisch erhöhen. Und zweitens müssen wir die Vorausschau drastisch begrenzen.
Ganz konkret bedeutet das für mich: Software ist jeden Tag mit überraschenden Änderungswünsche zu konfrontieren. Und jeden Tag ist Software auszuliefern. Nur so entsteht auf ihre Anpassungsfähigkeit soviel Druck, dass die wirklich geschmeidig wird. Das gilt für die allgemeine Form von “Softwarebauteilen” wie für die konkrete Struktur einer Lösung. Ohne diesen Druck werden wir nicht dahin kommen, die Prinzipien und Praktiken für dauerhafte Evolvierbarkeit zu erkennen und zu leben.
Evolution geht aufs Ganze
Wer hätte je einen Magen oder ein Gehirn oder eine Hand getrennt von einem Lebewesen sich entwickeln sehen?
Evolution findet immer am ganzen Organismus statt. Ein Lebewesen ist entweder als Ganzes an seinem Umwelt angepasst oder gar nicht. Das beste Herz nützt nichts, wenn das Nervensystem unangepasst ist.
Auf die Softwareentwicklung übertragen bedeutet das, es gibt keine Infrastrukturentwicklung. Jedes Mal, wenn sich Software der Umwelt aussetzt – also am Ende einer Iteration –, setzt sie sich als Ganzes aus. Sonst ist sie nicht “anschlussfähig” gegenüber ihrer Umwelt. Das muss sie aber sein, sonst bekommt sie kein Feedback. Und Mangel an Feedback bedeutet Stillstand und dann Tod.
Alle Arbeit an Software muss deshalb sagen können, inwiefern sie an die Umwelt anschließt, welches konkrete Bedürfnis der Umwelt sie erfüllt. Ein Team als Ganzes muss zu jeder Zeit auf die Software als Ganzes konzentriert sein. (Ein einzelner Entwickler kann sich im Rahmen dessen natürlich auf ein Detail fokussieren. Er dient damit ja einem Ganzen.)
Naturnahe Entwicklung bedeutet also Entwicklung in Durchstichen. In jeder Iteration ist eine ganze, besser angepasste Software abzuliefern. [2]
Evolution ist Verfeinerung
Schließlich scheint mir ein wesentliches Merkmal von natürlicher Entwicklung die Bewegung vom Groben zum Feinen. Evolution ist Differenzierung, ist Verfeinerung.
Die Entscheidung zwischen bottom-up und top-down Entwicklung können wir zur Ruhe betten. Diese beiden Pole sind unwichtig. Wir können die Herangehensweise wählen, wie wir mögen, wie es uns in Bezug auf eine Problemstellung passt.
Worüber wir aber nicht nachdenken sollten, das ist coarse-to-fine oder simple-to-complex Entwicklung. Software sollte schrittweise “schärfer” oder detaillierter werden.
Auch breadth-first vs. depth-first ist hier zweitrangig. Die Verfeinerung kann in der Breite in geringem Maß stattfinden oder in der Tiefe in hohem Maß. Wie es der Kunde mag. Er bestimmt die Prioritäten.
Nach jeder Iteration kann er sich wünschen, ob Feature A verfeinert werden soll oder lieber Feature X grob angegangen werden soll. Vor dem Hintergrund des täglichen Drucks auf die Evolvierbarkeit bedeutet das, der Kurs der Entwicklung kann sich prinzipiell jeden Tag ändern. Und warum auch nicht? Der Kunde, die Anwender: das ist die Umwelt. Der gilt es sich anzupassen.
Naturnahe Entwicklung findet deshalb in kleinsten Schritten statt. User Story, Use Case, ja selbst Feature sind dafür zu groß. Würden sie pro Iteration komplett umgesetzt, würde zu schnell zu viel Detail entstehen. Das wäre keine Evolution mehr, sondern Setzung.
Wenn es jedoch jeden Tag an quasi beliebiger Stelle in der Software ein Nutzenstückchen weiter geht, dann entsteht kontinuierliche Anpassungsfähigkeit. Dann kann auch nie mehr als die Arbeit eines Tages umsonst gewesen sein. Tägliches Feedback korrigiert ja den Evolutionsweg unmittelbar.
Fazit
Agile Softwareentwicklung ist schon ein Schritt in Richtung naturnahe Softwareentwicklung. Erreicht ist das Ziel mit ihr jedoch noch nicht. Wenn wir naturnahe Softwareentwicklung als Tugend ansehen, dann müssen wir ein paar Schrauben noch mehr anziehen. Evolution ist rigoroser als Agilität.
Fußnoten
[1] Ziellosigkeit mag merkwürdig klingen, da doch anscheinend mindestens der Kunde ein Ziel hat. Er möchte schließlich eine Software für einen bestimmten Zweck. Wie oft ist es aber der Fall, dass am Ende der Entwicklung genau das herauskommt, was am Anfang in den Anforderungen drin gestanden hat? Wie oft sind Anforderungen vollständig? Ich halte es deshalb für besser, die Idee von der Zielhaftigkeit im Sinne einer sichtbaren Zielmarke aufzugeben. Softwareentwicklung ist vielmehr ziellos – hat jedoch ein Ende. Beendet ist sie, wenn der Kunde sagt “Genug!”
[2] Mit “ganze Software” meine ich natürlich nicht, dass vom ersten Tag an eine komplette Buchhaltung oder eine ganze Textverarbeitung ausgeliefert werden soll. Wie sollte das auch gehen? Nein, “ganze Software” bedeutet, dass die Software für den Anwender als etwas sinnhaftes wahrnehmbar ist, zu dem er Feedback geben kann. Für eine Buchhaltungssoftware bedeutet das nicht mal, dass es ein GUI geben muss, sondern am ersten Tag vielleicht nur einen Prüfstand, mit dem der Anwender Feedback zum Datenimport geben kann.
Spendieren Sie mir doch einen Kaffee, wenn Ihnen dieser Artikel gefallen hat...