Lösungsansätze für einen erfolgversprechenden Entwicklungsprozess

Scrum und die technische Schuldfrage
Keine Kommentare

In diesem Artikel möchten wir verschiedene Facetten von Scrum und technischer Schuld betrachten, jeweils im Kontext eines Softwareherstellers und einer E-Commerce-Agentur. Dabei wollen wir auch die Frage auflösen, wie mit technischer Schuld umzugehen ist.

Scrum ist ein einfacher und guter Prozess, um Softwareentwicklung zu verwalten. Kurzfristige Ziele werden der langfristigen Planung vorgezogen. Der Hauptvorteil besteht darin, dass agile Teams schneller auf Kundenwünsche reagieren können und gleichzeitig die Sicherheit eines soliden Plans und eines konkreten kurzfristigen Ziels haben. In einem Buch über Scrum beschrieb einer dessen Erfinder, Jeff Sutherland, die vielfältigen Vorteile dieses Prozesses. Er hob dabei hervor, dass man diese Methode nicht nur für Softwareentwicklung einsetzen könne, sondern zum Beispiel auch bei einer Kirchengruppe, beim Hausbau oder für die Selbstverwaltung. Das ist zunächst einmal verwirrend, da es doch bedeutet, dass Scrum nicht nur speziell für die Softwareentwicklung geeignet ist, obwohl es doch eigentlich genau für diesen Zweck eingeführt wurde. Tatsächlich bietet sich jedoch für viele unterschiedliche Branchen ein iterativer Entwicklungsprozess an. Scrum beschreibt im Kern vor allem einen Produktentwicklungs- und Pflegeprozess. Dieser eignet sich für die IT, aber eben auch für andere Gebiete.

Scrum implementiert Qualitätsziele nur über die sogenannten Definition of Done (DoD). Dabei handelt es sich nicht um konkrete Vorgaben, sondern einen Vertrag, der durch die Mitwirkenden für den Entwicklungsprozess definiert wird. Die DoD legt fest, unter welchen Kriterien ein einzelner Vorgang als erledigt gilt. An dieser Stelle entsteht das Hauptproblem mit Scrum in der Softwareentwicklung. Möchte man ein Medikament entwickeln, muss man durch eine Zulassungsstelle, möchte man ein Haus bauen, muss man die Pläne von der Behörde abnehmen lassen, doch möchte man eine Software veröffentlichen, scheint es keine Kontrollstelle zu geben.

Industrieweit vereinbarte und gehaltene Standards existieren in diesem Bereich nicht. In der Praxis gibt es daher Teams, die sich hohe Qualitätsstandards setzen und daran halten und andere Teams, die ihr Hauptaugenmerk auf andere Punkte legen. Es ist bestimmt für jeden leicht vorstellbar, dass ein Team eine teilweise sehr strenge DoD für die UX-Elemente hat, aber dafür jede festgelegte technische Konvention schnell über Bord wirft. Einfach nur, weil es dadurch auf kurze Sicht schnell vorankommt. Die DoD als Gefäß für unumstößliche Qualitätsstandards muss eben auch von Entwicklern gefüllt werden.

Technische Schuld

Auf Ward Cunningham geht der Begriff der „technischen Schulden“ (Technical Debt) zurück:

„Although immature code may work fine and be completely acceptable to the customer, excess quantities will make a program unmasterable, leading to extreme specialization of programmers and finally an inflexible product. Shipping first time code is like going into debt. A little debt speeds development so long as it is paid back promptly with a rewrite. Objects make the cost of this transaction tolerable. The danger occurs when the debt is not repaid. Every minute spent on not-quite-right code counts as interest on that debt. Entire engineering organizations can be brought to a stand-still under the debt load of an unconsolidated implementation, object-oriented or otherwise.“

Cunningham vergleicht schlechten Quellcode mit einer Art von Hypothek, für die natürlich auch Zinsen fällig werden. Es kann durchaus sinnvoll oder gar notwendig sein, eine Hypothek aufzunehmen, wenn dadurch das Produkt schneller vermarktungsfähig ist. Findet aber keine Tilgung der Hypothek statt, z. B. durch die Refaktorierung der Codebasis, dann entstehen langfristig erhebliche Kosten für die anfallenden Zinszahlungen. Es gibt darüber hinaus verschiedene Ausprägungen von technischer Schuld. Sehen wir uns im Folgenden zwei der extremeren Ausprägungen an.

Technische Schulden als Abkürzung

Man mag diese Art, Schulden zu produzieren, sogar mit Innovation verwechseln. Ein wie auch immer geartetes Softwaresystem setzt sich aus Konventionen zusammen. Mal gibt es Controller-Klassen, die einzelne Aktionen des Benutzers abarbeiten und kapseln. Mal gibt es Repositories für den Datenbankzugriff. Für gewöhnlich vereinbaren Teams, gleichartige Probleme auch auf gleichartige Weise zu lösen. Technische Schuld ist nun gegeben, wenn Elemente des Systems teilweise dieser Vereinbarung widersprechen. Wenn man zu lange alles erlaubt, was auch nur irgendwie funktioniert, entsteht dabei ein Flickenteppich von Insellösungen. Man kann im Extremfall jede Zeile Code blind einem speziellen Entwickler und sogar einem bestimmten Jahr zuweisen. Jeder Entwickler zwingt jedoch auch der Codebasis den jeweiligen aktuellen Trend auf. Symptome dieser Art zeigen sich auch schon im Kleinen: Das plötzliche Auftauchen von Lambdakonstrukten oder die Existenz eines seltsam zentralen Traits oder auch das unkontrollierte Wachstum einiger weniger zentraler Methoden sind sichere Anzeichen für Abkürzungen.

Systeme dieser Art neigen dazu, inkonsistent und fragil zu werden. Es wird immer schwerer vorauszusehen, welchen Umfang an Entwicklung eine neue Funktion benötigt, besonders wenn kein gedanklicher Leitfaden existiert, an dem man sich für Schätzungen orientieren könnte.

Technische Schulden als Entscheidung

Im Gegensatz zu Abkürzungen, die bestehende Konventionen bewusst brechen, steht die Entscheidung, also die Erweiterung der Konventionen. Dies geschieht, weil sich existierende Paradigmen als nicht ausreichend oder schlicht als falsch herausgestellt haben. Eine solche Entscheidung erfüllt einige Charakteristika. So ist sie z. B. im System weitläufig implementiert. Wenn sie eine alte Konvention ablöst, existiert ein Plan, wie und bis wann die alte Konvention im System entfernt wird. Es existiert zudem eine Exit-Strategie für den Fall, dass die getroffene Entscheidung falsch war. Unter diese Kategorie fällt z. B. die Nutzung eines ORM. Um kurzfristig schneller liefern zu können, nimmt man Einbußen in der Performance gerne in Kauf. Statt z. B. ein neues JavaScript-Framework zu lernen und einzubauen, nutzt man iframes. Oder man nutzt Symfony, statt selbst ein Framework zu entwickeln.

Diese Art, Schulden anzuhäufen, ist gerade in iterativen Prozessen unumkehrbar und nötig. Wir Entwickler müssen uns hier davon verabschieden, dass es nur gute und schlechte Lösungen gibt. Im Alltag machen der Kunde, der Manager und auch der Firmenvorstand Kompromisse, wir also auch. Zur besseren Verständlichkeit schlagen wir vor, den Begriff der technischen Schuld mit dem des Kompromisses gleichzusetzen. Es sollte jedem einfach verständlich sein, was ein guter und was ein fauler Kompromiss ist.

API Conference 2018

API Management – was braucht man um erfolgreich zu sein?

mit Andre Karalus und Carsten Sensler (ArtOfArc)

Web APIs mit Node.js entwickeln

mit Sebastian Springer (MaibornWolff GmbH)

Wenn Schulden in die Kategorie „Chaos“ fallen, wird der Entwickler bald mit weitaus größeren Problemen konfrontiert werden. Wenn z. B. ein Team nicht mehr in der Lage ist, neue Funktionen in der gleichen Zeit wie am Anfang umzusetzen. Auch wenn die Fehlerrate nicht zwingend signifikant ansteigt, wird das Team in der Regel mehr Zeit für neue Features benötigen. Bei der Entwicklung sollte immer daran gedacht werden, dass Scrum bei technischer Schuld nicht unterstützt. Im schlimmsten Fall kann es sogar die Probleme vergrößern. Denn man hat nicht alle zwei Monate ein Release der Software, sondern in der Regel alle zwei Wochen. Dadurch verleitet Scrum die Entwickler noch mehr dazu, Abkürzungen zu nehmen und somit technische Schuld anzuhäufen.

Broken Windows Theory

Was aber, wenn das Kind schon in den sprichwörtlichen Brunnen gefallen ist? Die sogenannte „Broken Windows Theory“ aus der Sozialforschung illustriert das anschaulich. Auf Software angewandt, lässt sich diese Theorie am einfachsten an einem Beispiel erklären: Ein Entwickler stößt auf eine Methode mit 500 Zeilen Quellcode und muss diese Methode um ein winziges Feature erweitern. Maximal fünf Zeilen hinzufügen, was würde er in diesem Fall tun? Hier schlägt jetzt der typische Entwicklerinstinkt zu. Der Entwickler schaut auf die Uhr – natürlich muss dieses Feature heute noch fertig werden. Er frickelt ein bisschen herum, versucht zu verstehen, was diese Methode verflucht nochmal macht und zum Schluss erweitert er sie, so dass diese nun 505 Zeilen lang ist. Doch Stop: Die If-Bedingung oben bedeutet, dass er die Erweiterung dort auch nochmal einbauen muss. 510 Zeilen ist sie nun lang, womit soweit alles in Ordnung wäre. Vorher war die Methode ja auch nicht viel besser, oder? Das bedeutet: Release.

Nachdem die ersten Fehlermeldungen eintrudeln, stellt er fest, dass er noch an einer weiteren Stelle die fünf Zeilen Quellcode hinzufügen muss und die Methode nun 515 Zeilen lang ist. Frustriert schreit er seinen Monitor an und informiert seinen Projektleiter darüber, dass eine Refaktorierung der Methode eingeplant werden muss. Was ist genau passiert? In einem Satz zusammengefasst: Er hat ein Haus mit vielen kaputten Fensterscheiben gesehen und hat ein weiteres eingeworfen. Was ist schon seine Schuld dabei? Wenn der Fensterbauer zur Reparatur kommt, wird es ihn nicht stören, ein weiteres Fenster zu reparieren, oder?

Refaktorierung vs Reengineering

Viele Entwickler setzen das Wort Refaktorierung ziemlich lose ein. Wer in das Buch über Refactoring von Martin Fowler hineinsieht, wird feststellen, dass Methoden der Refaktorierung in Wirklichkeit ziemlich klein und einfach sind. Es geht um das Umbenennen von Klassen und Variablen oder darum, Methoden und Interfaces zu extrahieren. Evolutionäre Änderungen sind nichts Revolutionäres. Features sollen die Revolution in Programmen sein. Diese benötigen riesige Teile an neuem Quellcode. Refaktorierung nimmt nur, was da ist und macht es besser.

Es sind die kleinen Verbesserungen. Um das Beispiel von oben wieder aufzugreifen, bei einer Refaktorierung würde die 500-Zeilen-Methode nicht um fünfzehn Zeilen wachsen, sondern um fünfzehn Zeilen schrumpfen. Nach und nach wird diese große Methode immer kleiner, immer lesbarer. Dies ist der agile Weg, um die Softwarequalität im Laufe der Zeit ständig zu verbessern. Bei Reengineering wird dagegen ein Codeabschnitt (in unserem Beispiel die 500-Zeilen-Methode) vollständig entfernt und durch etwas Neues ersetzt. Das Neue wird hoffentlich qualitativ hochwertiger sein, aber niemand weiß, ob die neue Implementierung stabil und fehlerfrei ist. Denn die 500 Zeilen Quellcode haben ihren Zweck erfüllt, zumindest irgendwie. Reengineering ist eine Notbremse, ein Anzeichen des Versagens, weil das Entwicklungsteam zu lange schlechte Änderungen toleriert hat. Demgegenüber ist Refactoring ein Prozess, der zur iterativen Natur von Scrum passt und seinen Charme in der Berechenbarkeit der benötigten Veränderungen hat.

Umgang mit technischer Schuld

Umgang mit technischer SchuldDurch unseren großen Erfahrungsschatz als Entwickler für einen Softwarehersteller und für eine E-Commerce-Agentur betrachten wir nun die verschiedenen Formen, wie jeweils mit technischer Schuld umgegangen werden kann. Als Beispiel nehmen wir ein Bonuspunktesystem für einen Onlineshop.

E-Commerce-Agentur

Zuerst schauen wir uns die Herangehensweise einer Agentur an. Die Agentur hat im Vorfeld verschiedene Meetings, um das gewünschte Softwareinkrement zu besprechen. Der Kunde liefert in der Regel eine Liste von Anforderungen, die er an das Bonussystem hat. Die Agentur bewertet sie und prüft sie auf ihre Machbarkeit. In den anfänglichen Besprechungen wird die Problemdomäne, in der sich die Entwickler später bewegen, gut umrissen. Durch das schnelle Ausliefern von einzelnen Inkrementen nach jedem Sprint kann der Kunde noch nachbessern lassen, wenn das Ergebnis von seinen Zielvorstellungen abweicht. Normalerweise werden in den ersten Sprints vom Entwicklerteam Prototypen, z. B. Klickprototypen, erstellt, damit der Kunde einen schnellen Eindruck von Aussehen und Bedienbarkeit seiner Software bekommt.

Bei den Prototypen wird meist nicht auf die Qualität der Software geachtet, sondern der Fokus liegt klar darauf, dem Kunden schnell etwas präsentieren zu können. Nimmt der Kunde die Software soweit ab und stimmt den Ergebnissen zu, geht es in deren detailliertere Ausarbeitung. Werden hierbei Teile der Prototypen übernommen, hat man schon unbewusst die erste technische Schuld auf sich genommen. Wie hilft uns in diesem Fall der Scrum-Prozess weiter? Erst einmal gar nicht. Es gibt keinen festen Termin, in dem die Qualität der Software von dem Entwicklerteam geprüft werden muss, geschweige denn dem Product Owner die Qualitätskriterien zur Verfügung gestellt werden müssen. Hier kommt es ganz auf das Team an. Wenn es feststellt, dass Komponenten technische Schulden aufweisen, muss das Team proaktiv auf seinen Product Owner zugehen und einfordern, dass dafür in den nächsten Sprints Zeit eingeräumt wird. Es mag bei der anfänglichen Umsetzung vorerst keine große Rolle spielen, diese Schuld weiter mit sich herumzuschleppen. Doch falls das Team zu spät reagiert, kann dies Folgen für seine Reputation haben, denn in der Zwischenzeit können sich schon viele Fehlermeldungen angehäuft haben. In unserem Beispiel gibt es nun mehrere Möglichkeiten, wie das Team mit dem Product Owner entscheiden kann:

  • Lösung 1: Das Team und der Product Owner besprechen die Situation und wägen Pros und Kontras ab. Hierbei kommt der Programmierer zu dem Schluss, dass sich das Feature Bonuspunktesystem erst einmal in der Praxis bewähren soll, bzw. ob es überhaupt von den Kunden angenommen wird. Ist das der Fall, wird dem Team in zukünftigen Sprints Zeit eingeräumt, die Erweiterung zu refaktorieren und somit Schritt für Schritt von technischer Schuld zu befreien.
  • Lösung 2: Es wird beschlossen, den Quellcode so weit zu refaktorieren, dass man die Basis auch für weitere Tippspiele wiederverwenden kann.
    Wie man an diesem schönen Beispiel sehen kann, hat eine Agentur mehrere Möglichkeiten, mit technischer Schuld proaktiv umzugehen. Einerseits kann sie diese wissentlich in Kauf nehmen, um für erste Erfahrungswerte keine unnötige Zeit in die Erweiterung zu stecken. Das anschließende Tilgen der Schuld sollte natürlich obligatorisch sein. Andererseits besteht aber auch die Möglichkeit, proaktiv mit der Schuld umzugehen und sie direkt wieder abzubauen.

Wie man an diesem schönen Beispiel sehen kann, hat eine Agentur mehrere Möglichkeiten, mit technischer Schuld proaktiv umzugehen. Einerseits kann sie diese wissentlich in Kauf nehmen, um für erste Erfahrungswerte keine unnötige Zeit in die Erweiterung zu stecken. Das anschließende Tilgen der Schuld sollte natürlich obligatorisch sein. Andererseits besteht aber auch die Möglichkeit, proaktiv mit der Schuld umzugehen und sie direkt wieder abzubauen.

Softwarehersteller

Für einen Softwarehersteller sieht das Ganze schon wieder anders aus. In der Regel wird die Software für ein breite Masse entwickelt, um möglichst viele potenzielle Kunden zu erreichen. Auch hier werden im Vorfeld Konzeptionsmeetings mit den verschiedensten Fachabteilungen durchgeführt. Als Ergebnis steht ein Konzept, das die Anforderungen vom Markt für ein Bonussystem abdeckt. Für größere Projekte, z. B. die Entwicklung eines B2B-Frameworks für ein eigenes Shopsystem, werden sogenannte Think Tanks ins Leben gerufen. Zu diesen Think Tanks werden Partner, Kunden und Technologiehersteller eingeladen, um die Anforderungen des Markts noch genauer zu ermitteln.

Ist das Konzept soweit finalisiert, fängt das Team mit der Umsetzung an. Hierbei werden auch Prototypen entwickelt und intern vorgestellt. Im Anschluss geht es an die detaillierte Ausarbeitung der Software mit Fokus auf eine wartungsfreie und auch durch Dritte erweiterbare Architektur. Hierbei steht bei uns im Vordergrund, die einzelnen Minor- und Patchversionen abwärtskompatibel zu gestalten, um den Aktualisierungsprozess für die Kunden so einfach wie möglich zu halten.

So eine Fokussierung auf die Möglichkeiten, mit technischer Schuld umzugehen, hat immense Auswirkungen auf den Entwicklungs- und Releaseprozess der Software. Ist eine Erweiterung funktional abgeschlossen und veröffentlicht, können für eine Refaktorisiererung ggf. notwendige Breaking Changes erst in einer nächsten Major-Version umgesetzt werden. Solange muss sich der Hersteller mit dem Status Quo beschäftigen, ihn pflegen und auch weiterentwickeln. Eine abschließende Tilgung der technischen Schuld ist somit frühestens in der nächsten Major-Version möglich. Oder mit einem Zitat von Michael Sinz ausgedrückt: „Programming is like sex – one mistake and you have to support it for the rest of your life.“

Grundsätze für einen besseren Umgang mit technischer Schuld

Grundsätze für einen besseren Umgang mit technischer SchuldWenn wir die Möglichkeiten eines Softwareherstellers mit denen aus der Agenturwelt vergleichen, bemerken wir gleich, dass die vorhandenen Optionen, mit technischer Schuld umzugehen, für einen Softwarehersteller eigentlich nicht existent sind. Es gibt keine Möglichkeit, technische Schuld bewusst aufzunehmen und zu einem späteren Zeitpunkt zu tilgen. Erstellte Prototypen oder Betaversionen werden von den potenziellen Kunden nur selten auf Herz und Nieren geprüft oder direkt eingesetzt, um durch eventuelle Fehler in der Software keine Umsatzverluste zu erfahren. In der Regel muss man diese Schulden dann lange mit sich tragen, sodass die zu zahlenden Zinsen in keinem vertretbaren Verhältnis mehr stehen. Somit kommt es besonders auf das Team an, proaktiv auf seinen Product Owner zuzugehen und offen und ehrlich mit technischer Schuld umzugehen.

Ob man nun Softwarehersteller oder Agentur ist, Scrum unterstützt niemanden aktiv dabei, mit technischer Schuld umzugehen. Hier ist es wichtig, dass sich das Team selbst dafür sensibilisiert, offen mit der aufgenommenen technischen Schuld umzugehen. Wird dieses Thema totgeschwiegen, hat das unter Umständen weitreichende Konsequenzen für das Team. Daher empfehlen wir folgende Grundsätze für einen besseren Umgang mit technischer Schuld:

  • Du siehst etwas, was nicht richtig benannt ist? Benenne es um!
  • Du siehst eine Methode, die zu lang ist? Teile sie in kleinere Fragmente auf!
  • Du siehst eine aufgeblähte Bedingung? Teile sie auf!
  • Du siehst eine Methode an einer falschen Stelle? Verschieb Sie!

Ein Team eines Softwareherstellers kann diese Grundsätze in der Regel jedoch nur bei noch nicht veröffentlichtem/releastem Quellcode anwenden, anders als eine Agentur, bei der sie immer Anwendung finden können.

Fazit

Wenn ein Feature zwar funktioniert, aber die Architektur der Software zerstört oder es kein anderer Entwickler verstehen kann, ist dieses Feature nicht fertig und musst angepasst werden. Erschaffen Sie daher eine Kultur, in der die Software sich ständig verbessern kann.

Sollten Sie in einer großen Legacy-Applikation entwickeln müssen: Sehen Sie etwas, das auf den ersten Blick nicht anzupassen ist, verlassen Sie es in einem besseren Zustand als zuvor. Zumindest ein kleines bisschen. Programmierer sollten nicht weitere Fenster zerstören, sondern sie Stück für Stück reparieren.

PHP Magazin

Entwickler MagazinDieser Artikel ist im PHP Magazin erschienen. Das PHP Magazin deckt ein breites Spektrum an Themen ab, die für die erfolgreiche Webentwicklung unerlässlich sind.

Natürlich können Sie das PHP Magazin über den entwickler.kiosk auch digital im Browser oder auf Ihren Android- und iOS-Devices lesen. In unserem Shop ist das Entwickler Magazin ferner im Abonnement oder als Einzelheft erhältlich.

Unsere Redaktion empfiehlt:

Relevante Beiträge

Hinterlasse einen Kommentar

Hinterlasse den ersten Kommentar!

avatar
400
  Subscribe  
Benachrichtige mich zu:
X
- Gib Deinen Standort ein -
- or -