Umgang mit technischen Schulden
Wie sollte man mit technischen Schulden umgehen? Gehören „Refactoring“ Stories ins Product Backlog oder nicht? Das sind wichtige Themen für fast alle unserer Kunden ob sie Scrum anwenden oder nicht.
Es braucht viele Jahre Erfahrung, um darüber sprechen zu können. Viele Entwickler arbeiten an einer Code-Base nicht lange genug, um die Auswirkungen der eigenen Entscheidungen noch Jahre später selbst mitzuerleben oder sie kommen und erleben die Konsequenzen der Entscheidungen von anderer Entwickler und übernehmen für deren Handlungen nicht die Verantwortung.
Umso wichtiger ist es von Menschen mit viel Erfahrung darüber zu lesen. Im Folgenden ist die Übersetzung des Blog-Artikels von Ron Jeffries, einem der erfahrensten Software-Entwickler, Mitbegründer von Extreme Programming (XP) und einem der Erstunterzeichner des Manifests für Agile Software Entwicklung. Er hat uns die Übersetzung und die Verwendung seiner Bilder erlaubt.
Refactoring – Nicht im Product Backlog!
Es gab in letzter Zeit viel Kommentare in Foren und Fragen auf Konferenzen, die sich alle um Refactoring-“Stories” Im Produkt-Backlog drehten. Selbst wenn sich viele “technische Schulden“ angesammelt haben, ist es keine gute Idee das zu machen. Hier ist Warum:
Wenn unser Projekt beginnt, ist der Code sauber. Das Feld ist gut gemäht, das Leben ist leicht, die Welt liegt uns zu Füßen. Alles wird gut.
Wir können Features reibungslos und einfach erstellen, obwohl wir manchmal ein paar kleine Wendungen nehmen müssen. Die Dinge sehen ziemlich sauber aus, und außerdem haben wir es eilig. Wir merken nicht, das irgendetwas schief läuft, und wir machen schnell weiter.
Allerdings entstehen mit der Zeit einige kleine Büsche in unserem ansonsten nahezu perfektem Garten. Manchmal nennen Leute das „technische Schulden“. Das ist es nicht wirklich: es ist nur nicht sehr guter Code. Aber insgesamt sieht es nicht schlecht aus – noch nicht.
Doch wenn wir neue Dinge bauen, müssen wir das Dickicht schon mal umfahren oder durch da hindurchgehen. Meistens machen wir einen Umweg.
Das verlangsamt uns zwangsläufig ein wenig. Um schnell gehen zu können, sind wir noch weniger vorsichtig als zuvor, und bald sind noch mehr überwucherte Dickichte gewachsen.
Diese neuen Dickichte, zusätzlich zu den alten, verlangsamen uns noch mehr. Uns ist klar, dass es ein Problem gibt, aber wir haben es sehr eilig, etwas dagegen zu unternehmen. Wir drücken härter, um unsere frühe Entwicklungsgeschwindigkeit beizubehalten.
Bald scheint es so, als ob der halbe Code, mit dem wir arbeiten müssen, mit Unkraut, Buschwerk, kleinen Bäumen und Hindernissen jeglicher Art bewachsen ist. Vielleicht liegen sogar irgendwo alte Dosen und schmutzige Klamotten herum. Vielleicht sogar ein paar Gruben.
Jede Reise durch dieses durcheinander geratene Feld des Codes wird zu einem langen Weg aus Ausweichen von Büschen und Springen über die Gruben, die zurückgelassen wurden. Zwangsläufig fallen wir in einige davon und müssen uns wieder nach draußen graben. Wir sind langsamer als je zuvor. Etwas muss sich ändern!
Die Dichte der Probleme ist für uns jetzt sehr sichtbar und wir sehen, dass wir nicht einfach ein schnelles Mähen des Feldes alles wieder gut machen können. Wir müssen eine Menge Refactoring machen, um zu einem sauberen Feld zurückzukehren. Wir sind versucht, unseren Product Owner um Zeit zu bitten. Oft wird diese Zeit nicht gewährt: Wir bitten um Zeit, um zu beheben, was wir in der Vergangenheit vermasselt haben. Es ist unwahrscheinlich, dass irgendjemand für uns auf wichtige Dinge verzichten wird.
Und wenn wir die Zeit doch bekommen, erreichen wir kein gutes Ergebnis. Wir werden alles aufzuräumen, was wir sehen, und zwar so sauber wie wir es in der uns zur Verfügung stehenden Zeit können. Aber es wird niemals gut genug sein. Wir werden viele Wochen gehabt haben, um den Code so schlecht zu machen, wir werden sicherlich jetzt nicht genau so viel Zeit bekommen, um ihn zu reparieren.
Das ist nicht der richtige Weg. Eine große Refactoring-Sitzung ist schwer zu verkaufen, und wenn sie verkauft wird, kommt nach einer langen Verzögerung weniger zurück, als wir erhofft hatten. Keine gute Idee. Was sollen wir also machen?
Ganz einfach! Wir nehmen das nächste Feature, das wir bauen sollen, und anstatt alle Unkräuter und Büsche zu umfahren, nehmen wir uns die Zeit, um einen Weg durch einige von ihnen frei zu machen. Vielleicht gehen wir um andere herum. Wir verbessern den Code, an dem wir arbeiten, und ignorieren den Code, an dem wir nicht arbeiten müssen. Wir machen einen schönen, sauberen Weg für einige unserer Arbeiten. Und es ist wahrscheinlich, dass wir diesen Ort wieder besuchen werden: So funktioniert die Softwareentwicklung.
Vielleicht dauert dieses Feature etwas länger. Oft nicht, denn die Bereinigung hilft uns sogar beim aller ersten Feature, das auf diesem Weg implementiert wird. Und natürlich wird es auch bei anderen Features helfen.
Saubermachen, wiederholen. Mit jeder neuen Funktion bereinigen wir den von dieser Funktion benötigten Code. Wir investieren ein wenig mehr Zeit als wir es tun würden, wenn wir weiterhin das Feld zerstören würden, aber nicht viel mehr – und oft weniger. Gerade im Laufe des Prozesses bekommen wir mehr und mehr Vorteile durch unsere Aufräumarbeiten, und die Entwicklung wird immer schneller.
Bald, oft innerhalb desselben Sprints, in dem wir anfangen aufzuräumen, stellen wir fest, dass ein zukünftiges Features tatsächlich den gleichen Code-Bereich verwendet, den wir gerade vorher gesäubert haben. Wir profitieren sofort vom inkrementellen Refactoring. Hätten wir darauf gewartet, es in einem großen Los zu machen, hätten wir uns mehr Mühe gegeben, die Vorteile noch bis später aufgeschoben und wahrscheinlich auch an Orten Zeit verschwendet, die noch keinen Nutzen bringen.
Die Arbeit läuft besser, der Code wird sauberer und wir liefern mehr Funktionen als bisher. Jeder gewinnt.
So macht man es.
Dieser Wissensbeitrag wurde von Anton Skornyakov geschrieben und zuletzt am 23.12.2020 aktualisiert.