Posts mit dem Label Debt & Legacy werden angezeigt. Alle Posts anzeigen
Posts mit dem Label Debt & Legacy werden angezeigt. Alle Posts anzeigen

Montag, 6. Oktober 2025

Tech Debts VS More Features

Nachdem ich dieses Video in den letzten Monaten immer wieder zugeschickt bekommen habe, ist es höchste Zeit, es auch hier einzubinden. Keine Ahnung ob KI-generiert oder nicht, den Urhebern ist damit ein kleines Kunstwerk gelungen.



Und falls der Inhalt irgendjemandem zu weit hergeholt vorkommen sollte - es lohnt sich, das Video jemandem zu zeigen, der in einer grossen IT-Organisation arbeitet. Mit grosser Wahrscheinlichkeit wird er sagen, dass ihm das Ganze sehr bekannt vorkommt.

Dienstag, 25. Juni 2024

Runaway Effect

Bild: Pixabay / Peter Kaul - Lizenz

Es ist ein Phänomen, das man immer wieder beobachten kann: in irgendeiner Softwareentwicklungs-Organisation tritt eine Verschlechterung der Arbeits-Effektivität und -Effizienz auf, erst nur ein bisschen, dann ein bisschen mehr, dann deutlich mehr, dann viel mehr. Verbesserungsmassnahmen werden ergriffen, aber im besten Fall verlangsamen sie die Entwicklung nur, im schlimmsten Fall bleiben sie wirkungslos. Es wird immer schlimmer. Für dieses Phänomen gibt es einen Namen: den Runaway-Effekt.


Die Gründe für diese Benennung sind offensichtlich. Zum Einen erinnert die zunehmende Beschleunigung der Verschlechterung an einen Läufer oder Motor, der nach dem Start immer mehr Geschwindigkeit aufnimmt, zum Anderen an den Versuch, eine schnellere Person einzufangen. Aufgrund ihrer höheren Geschwindigkeit wird sie immer in der Lage sein, sich durch Weglaufen dem Zugriff zu entziehen. Übertragen: wenn das Problem an einer Stelle gelöst ist, ist es längst woanders aufgetaucht.


Der Grund für diese Entwicklung ist fast immer der gleiche: irgendwann wurde bewusst oder unbewusst entschieden, technische Schulden aufzunehmen, also nichtfunktionale (und für den Nicht-Techniker unsichtbare) Qualitätsaspekte wie Testabdeckung, Clean Code und stringente Architektur wegzulassen, um dadurch mehr Zeit für die Featureentwicklung zu haben. Das Tückische daran - in der unmittelbar anschliessenden Zeit halten sich die Folgen scheinbar in Grenzen.


Im Einzelnen sehen diese Folgen so aus, dass an einigen Stellen etwas mehr manueller Aufwand entsteht (z.B. beim Testen), und dass Code und/oder Architektur nicht sofort verständlich sind, so dass man sich bei einer Weiterentwicklung zuerst "Hineindenken" muss. Im Hintergrund geht der Runaway-Effekt aber bereits los: bei den manuellen Tätigkeiten kommt es zu Flüchtigkeitsfehlern und neuer Code "erbt" seine Architektur und (Un)Verständlichkeit von dem bereits vorhandenen.


Das addiert sich über die Zeit auf, die manuellen Aufwände (und Fehler) werden immer mehr und die Nachvollziehbarkeit von Code und Architektur wird immer geringer. Beides sorgt ausserdem dafür, dass immer mehr Fehlfunktionen versehentlich ins System gelangen, wo sie mit mühsamer Detektivarbeit gesucht werden müssen, wenn ihre Auswirkungen irgendwann auffallen. In Kombination sind das die Gründe für die ständig grösser werdenden Effektivitäts- und Effizienzverluste.


Schlimmstenfalls kommt es sogar dazu, dass IT-Systeme selbst dann ständig zunehmende Probleme generieren wenn gar nicht an ihnen gearbeitet wird. Unter Lastspitzen zusammenbrechende Systeme können ein Grund dafür sein, aber auch vollaufender Speicherplatz, in den unmöglichsten Situationen auftretende Race Conditions oder Fehler, die nur zu bestimmten Zeitpunkten auftreten können, etwa beim Jahreswechsel oder bei der Sommer- und Winterzeitumstellung.


Ein häufiger Versuch, den Runaway-Effekt in Griff zu bekommen sind so genannte Code- oder Feature-Freezes. Beim ersten wird die Anwendung gar nicht mehr weiterentwickelt (z.B. weil stattdessen ein komplett neues System entwickelt wird), beim zweiten darf nicht mehr an funktionalen Erweiterungen gearbeitet werden, damit alle Arbeitskraft in den Abbau der technischen Schulden gehen kann, die für die Entstehung des Effekts gesorgt haben. Oft anzutreffen ist eine Kombination: Feature Freeze für wichtige oder häufig zu ändernde Teile, vorläufiger Code Freeze für den Rest.


Eine entscheidende Frage bei solchen Reparatur- oder Ablöse-Phasen ist, mit welchem Ziel sie durchgeführt werden. Wenn in ihnen das Ausmass der technischen Schulden unter eine Schwelle gedrückt werden  soll, ab der der Runaway-Effekt auftritt, ist das zumindest etwas, besser wäre ihr weitestmöglicher Abbau. Zum anderen ist entscheidend, ob danach ein erneutes Anstauen technischer Schulden zugelassen wird. Wenn ja, ist es nur eine Frage der Zeit, bis alles von vorne losgeht.

Freitag, 11. August 2023

Technische Schulden dem Management erklären

Wer dieses Video anklickt und sieht, dass es ganze zwei Stunden lang ist, braucht nicht zu sehr erschrecken. Der eigentliche Vortrag von Carola Lilienthal ist nach ca. einer Stunde vorbei, was danach kommt sind Fragen und Diskussion. Selbst die kann man sich aber gut anhören, wenn man sich dafür interessiert, wie sich die Idee (und die Konsequenzen) der technischen Schulden dem Management erklären lassen.



Was ich gut finde ist, dass gegen Ende explizit darauf eingegangen wird, dass die Erklärung für Manager nicht nur verständlich sondern auch relevant sein soll, was u.a. auch bedeutet, dass man versuchen muss, technische Schulden finanziell quantifizierbar zu machen. Das ist natürlich nicht einfach, im Sinn der Zielgruppenorientierung aber unverzichtbar. Und es gibt auch Ratschläge wie das gemacht werden kann.

Donnerstag, 23. Juni 2022

Keynesianismus und Austerität in der Softwareentwicklung

Bild: Wikimedia Commons / TM - CC BY-SA 2.0

Dass technische Schulden eine Analogie aus dem Finanzwesen sind, mit deren Hilfe man die Folgen unterlassener Software-Modernisierung und -Instandhaltung beschreiben kann, dürfte zwar weitgehend bekannt sein, welche Ideen genau hinter dem Begriff stehen ist aber nur noch wenig bekannt. Eine nähere Beschäftigung damit wäre dabei durchaus lohnend, denn die Analogie geht weiter als man denken könnte - auch ein weiterer Ansatz der Haushaltsführung kann darin enthalten sein, der Keynesianismus.


Zur Auffrischung: von der Aufnahme technischer Schulden spricht man, wenn in der Software-Entwicklung schnelle Lösungen gesucht werden, die dann dadurch erreicht werden, dass eigentlich wichtige Dinge wie klare Architektur, das Einspielen von Updates oder Test-Absicherung auf später verschoben werden. Dadurch wird man kurzfristig schneller, dafür werden alle Weiterentwicklungen schwieriger. Diese Mehraufwände sind die "Zinsen", die zusätzlich zu den Schulden abzubezahlen sind.


Der in diesem Zusammenhang ebenfalls analogiefähige Haushaltsführungs-Ansatz des nach John Maynard Keynes benannten Keynesianismus (bzw. dessen Konjunkturtheorie) geht davon aus, dass es grundsätzlich sinnvoll sein kann Schulden aufzunehmen wenn Zeit- oder Ressourcenknappheit gegeben sind. Wenn diese Notlage mit dem durch Verschuldung gewonnenen Kapital bewältigt wurde kann die Rückzahlung stattfinden, so dass bis zur nächsten Notlage wieder die Schuldenfreiheit gegeben ist.


Auch auf die Softwareentwicklung kann der Keynesianismus angewendet werden. Um in Druckphasen (z.B. vor dem Weihnachtsgeschäft) schneller zu werden können eigentlich wichtige Aufgaben verschoben werden, sobald der Druck nachlässt finden Refactorings, Updates und nachträgliche Herbeiführung von Testabdeckung statt um die technischen Schulden zurückzuzahlen. Kurzfristige Handlungsfähigkeit wird so im wahrsten Sinn des Wortes erkauft.


Das Problem dabei: in der Realität funktioniert die keynesianistische Konjunkturtheorie nur extrem selten, sowohl in der Wirtschaft als auch in der Softwareentwicklung. Das Aufnehmen von (technischen) Schulden findet zwar statt, deren Rückzahlung in Entspannungsphasen aber nur eingeschränkt. Beim Eintreffen der nächsten Notlage besteht der Schuldenberg daher noch und wird jetzt weiter erhöht, mit dem Risiko eines (technischen) Bankrotts (Software die nicht mehr wartbar und weiterentwickelbar ist).


Die Alternative dazu besteht in einem anderen Haushaltsführungs-Ansatz: der Austerität. In ihm wird auf die Aufnahme von Schulden kategorisch verzichtet, selbst wenn das schrumpfende Haushalte zur Folge hat. Übertragen auf die Softwareentwicklung würde das bedeuten, dass auf die Aufnahme technischer Schulden auch dann verzichtet wird wenn dadurch gewünschte Funktionen erst verspätet oder deutlich verkleinert geliefert werden können.


Welcher der beiden Ansätze (Keynesianismus oder Austerität) von einer Softwareentwicklungs-Einheit gewählt werden sollte ist nicht klar zu sagen, je nach Kontext kann es sogar sinnvoll sein zwischen den beiden zu wechseln. Bei Teams die immer wieder falsch verstandenen Keynesianismus anwenden (Schulden aufnehmen aber nicht zurückzahlen) besteht aber irgendwann nur noch die Auswahl zwischen technischem Bankrott und Austerität.


Um es nicht dazu kommen zu lassen sollten keynesianische Teams sich regelmässig fragen was John Maynard Keynes sagen würde wenn er ihnen zusehen würde. Gegebenenfalls eine schöne Übung für die nächste Retrospektive.

Freitag, 13. Mai 2022

Technische Schulden (II)

Bild: Pixabay / Raten-Kauf - Lizenz

Wir müssen noch einmal über das Thema der technischen Schulden sprechen, genauer gesagt über eines der grössten damit verbundenen Probleme: die Unklarheit darüber was mit diesem Begriff eigentlich gemeint ist. Wie bereits gesagt ist nicht jeder Fehler oder jeder Qualitätsmangel im Code automatisch eine technische Schuld, das ist nur dann der Fall wenn diese Missstände bewust in Kauf genommen wurden um ein anderes Ziel zu erreichen. Aber auch das ist noch nicht alles.


Tatsächlich kann es auch technische Schulden geben die nicht bewusst "aufgenommen" wurden sondern mehr oder weniger versehentlich entstanden sind oder von jemand anderem (einem anderen Team, einem Zulieferer, einem aufgekauften Wettbewerber, etc) übernommen wurden. Das Entscheidende ist in diesen Fällen nicht mehr der Entstehungskontext sondern etwas Anderes - der Beschluss die Behebung in die Zukunft zu verschieben.


Um das besser zu verstehen ein kurzer Einschub: eigenlich ist es Best Practice Good Practice Fehler in der Software sofort zu beheben sobald sie entdeckt werden (🡪 Zero Bug Policy). Unterbleibt das besteht ein erhebliches Risiko, dass es zu einem "Jenga-Effekt" kommt: weitere, neue Funktionen bauen (bewusst oder unbewusst) auf den bestehenden, fehlerhaften auf, und wenn diese repariert und dadurch verändert werden stürzt das ganze Konstrukt in sich zusammen.


Es kann  aber Gründe dafür geben diese Reparaturen nicht sofort vorzunehmen, vor allem dann wenn ein wichtiger Liefertermin anliegt und für die entdeckten Fehler ein kurzfristiger Workaround möglich, eine sofortige Behebung dagegen relativ aufwändig wäre. Um den Termin einhalten zu können kann es in solchen Situationen Sinn machen die mit einer späteren Reparatur verbundenen Mehraufwände zu akzeptieren - und genau das ist nichts anderes als das Aufnehmen technischer Schulden.


Ist das ein realistisches Szenario? Es kommt darauf an, wie so oft. Bei stabilen Teams die langfristig an einem Produkt arbeiten ist diese Art der technischen Schuld eher ein Ausnahmefall, in Organisationen in denen Software in einer Abfolge von Projekten mit wechselnder Personalbesetzung entwickelt wird ist es eher die Regel, genauso in Systemlandschaften mit vielen Legacy-Anwendungen. Und seien wir ehrlich, die beiden letzten Typen sind in Konzernen der Normalfall.


Das Ergebnis dieser "Normalität" ist eine Art von Generationenvertrag - die aktuelle Entwicklergeneration hält ihre Systeme durch die Aufnahme technischer Schulden irgendwie am Laufen und kann sie so (mehr oder weniger) funktionierend an ihre Nachfolger übergeben, die dann vor der Wahl stehen sie in Form von Reparatur- und Aufräumarbeiten abzubezahlen oder noch mehr aufzunehmen und das Problem an die übernächste Generation weiterzugeben.


Und nochmal, auch dieses Weitergeben von immer schlimmer werdenden technischen Schulden über mehrere Generationen hinweg ist leider nicht unrealistisch, verbunden mit Wassermelonen-Projekten und Arschkarten-Lücken tritt es immer wieder auf. Um aber auch die andere Option zu nennen: ich habe es auch erleben dürfen, dass "geerbte" technische Schulden nach und nach abgebaut wurden. Das war anstrengend und fühlte sich ungerecht an, dafür wurde ab diesem Zeitpunkt alles wieder leichter.

Donnerstag, 14. April 2022

Technische Schulden

Bild: Wikimedia Commons / r2hox - CC BY-SA 2.0

Schon seit einigen Jahren steht es auf meiner To Do-Liste, etwas über technische Schulden zu schreiben. Dieses Phänomen ist in praktisch jedem Softwareentwicklungs-Vorhaben vorhanden und es kann zu spürbaren Verzögerungen führen, bis hin zum totalen Stillstand, dadurch ist es auch eine der Hauptquellen für Frustration und Demotivation der Entwickler. Gleichzeitig ist es einem grossen Teil der oberen Management-Ebenen bis heute unbekannt, was viele Fehlplanungen in IT-Projekten erklärt.


Entwickelt wurde der Begriff als bewusste Analogie zu den finanziellen Schulden. In beiden Fällen werden Verbindlichkeiten aufgenommen um kurzfristig handlungsfähiger zu werden, in beiden Fällen weiss man von Anfang an, dass man sie irgendwann zurückzahlen muss und in beiden Fällen ist es auch klar, dass die Rückzahlung um so teurer wird je später sie stattfindet, da für die gesamte Dauer der Verschuldung Zinsen fällig werden, die zusätzlich abzuzahlen sind.


Der Hintergrund dieser Analogie ist, dass ihr Erfinder, Ward Cunningham, sie sich auf einem Projekt einfallen liess auf dem Buchhaltungs-Software entwickelt wurde. Um für die Fachabteilungen die Probleme der IT nachvollziehbar zu machen wählte er für seine Erklärungen Begriffe die dort bekannt waren, darunter eben den der technischen Schulden. Durch einen Konferenz-Vortrag wurde der Begriff dann bekannt und fand auch branchenübergreifend Verwendung.


Zu Stande kommen technische Schulden dadurch, dass irgendwann in der Software-Entwicklung "schnelle Lösungen" gesucht werden, die dann dadurch erreicht werden, dass eigentlich wichtige Dinge weggelassen werden. Das kann eine verständliche Strukturierung und Formatierung des Code sein, eine Absicherung durch automatisierte Tests, das Integrieren neuer Software-Versionen, etc. Ohne sie wird zwar das kurzfristige Ziel erreichbar, dafür werden ab jetzt alle Weiterentwicklungen schwieriger.


Diese Schwierigkeiten können z.B. daraus bestehen, dass es ab jetzt unverhältnismässig viel Zeit erfordert den schlecht geschriebenen Bestands-Code überhaupt zu verstehen, dass Fehler aufgrund der fehlenden Tests zu spät gefunden werden (und schlimmstenfalls bereits neue Funktionen auf ihnen aufbauen, die dann auch überarbeitet werden müssen) oder daraus, dass veraltete Software-Versionen ständige Probleme mit Stabilität, Kompatibilität oder Regel-Konformität haben.


Wichtig ist dabei eine Abgrenzung: es handelt sich nicht bei nicht jeder qualitativ schlechten Software um technische Schulden, der Begriff ist nur dann angemessen wenn sie bewusst "aufgenommen" wurden. Und genau wie bei finanziellen Schulden kann es auch bei technischen Schulden sinnvoll sein sie aufzunehmen, etwa um vor der Konkurrenz am Markt zu sein. Problematisch werden sie vor allem dann wenn die Rückzahlung immer wieder verzögert wird.


Nicht abgebaute technische Schulden türmen sich mit der Zeit auf, sorgen dafür, dass selbst kleine Veränderungen einem immensen Umsetzungsaufwand mit sich bringen und erzeugen dadurch den Wunsch nach noch mehr "schnellen Lösungen", die dann zu noch mehr technischen Schulden führen. Dreht dieser Kreislauf sich zu lange kann es zu "technischem Bankrott" kommen, einer Situation in der Weiterentwicklung und schlimmstenfalls sogar Betrieb der Systeme nicht mehr möglich sind.


Um es dazu nicht kommen zu lassen empfiehlt sich ein konsequenter Abbau der technischen Schulden, und auch der lässt sich mit Finanz-Analogien erklären. Beide Schuldenberge verschwinden nicht über Nacht sondern nur nach und nach, bei beiden sollte man für den Abbau einen spürbaren Teil der verfügbaren Mittel einplanen und bei beiden sollte man die Schulden mit den besonders hohen Zinsen zuerst angehen, die weniger kostenintensiven dagegen erst später abbauen.


Gegebenenfalls kann sogar eine "Umschuldung" sinnvoll sein, z.B. indem für einige Zeit auf ein Versions-Upgrade verzichtet wird um dafür die alte Version stabilisieren und durch Tests absichern zu können. Überlegungen wie diese zeigen auf, dass technische Schulden nicht per se schlecht sind. Es kann gute Gründe dafür geben sie aufzunehmen - man sollte sich nur der Konsequenzen bewusst sein.