Hero Image
- Philipp Ludewig

Lektüre unterwegs: Verantwortung, Observability und Refactoring

Heute hatte ich viel Zeit zur Verfügung, als ich im Bus von Momotombo nach León saß. Da Reddit von meinem Mobilfunkanbieter hier in Nicaragua blockiert ist, wandte ich mich meiner zweithäufigst besuchten Website zu: HackerNews. Was ich dort fand, waren Artikel, die genau den richtigen Nerv trafen und mich dazu brachten, meine Gedanken dazu teilen zu wollen.

Der erste Artikel erinnerte mich an meinen eigenen Karriereweg bei Thoughtworks. Der Artikel gibt einen wichtigen Rat: "Übernimm Verantwortung, bevor sie dir offiziell übertragen wird.". Ich stimme dieser Aussage voll und ganz zu. Als ich meine Karriere als Graduate Consultant bei Thoughtworks begann, dachte ich darüber nach, was ich tun könnte, um mein Team und meinen Tech Lead zu unterstützen. Die Karriereentwicklung und Feedbackkultur von Thoughtworks fördert solches Verhalten. Obwohl die einzige Erwartung in der Rolle eines Graduate Consultants darin besteht, sich auf sich selbst zu konzentrieren. Ich hatte das Glück, mit Tech Leads zusammenzuarbeiten, die mir konstruktives Feedback gaben und mir Türen öffneten, um wertvolle Erfahrungen zu sammeln. Zum Beispiel begann ich, Retrospektiven, Gespräche über technische Schulden und Threat-Modeling-Workshops zu moderieren. Mein Ziel ist es, zu dem Tech Lead heranzuwachsen, mit dem ich persönlich gerne zusammenarbeiten und von dem ich lernen würde.

Graham-Yooll betont auch die Bedeutung von Beständigkeit. Einmalige Erfolge sind großartig, aber Manager brauchen die Gewissheit, dass man konstant liefern kann. Als ich bei Thoughtworks zum Senior Consultant befördert wurde, lag das nicht nur daran, dass ich in einem Team die Erwartungen übertroffen hatte. Es lag daran, dass ich diese Leistung über mehrere Teams und Projekte hinweg im Laufe der Zeit nachgewiesen hatte. Einmal pro Woche schrieb ich meine Erfolge auf und sammelte regelmäßig Feedback von meinen Kollegen. Mit dem aufgezeichneten Feedback und der Liste meiner Erfolge konnte ich dem Unternehmen meine konstante Leistung nachweisen.

Der nächste Beitrag stammte von einem Gründer, der über die Schwierigkeiten von Teams schrieb, Observability zu verstehen. In seinem Beitrag "Observability's Past, Present, and Future" schreibt er darüber, warum er denkt, dass Observability immer noch nicht gut funktioniert. Während ich dies las, was sich wie ein Pitch für ein KI-Produkt liest, dachte ich an vergangene Projekte. Ich war verwirrt, weil die Teams, mit denen ich zusammengearbeitet hatte, in meiner Erinnerung nicht so sehr gekämpft hatten, wie Sherwood die Leser glauben machen möchte. Zitat: "Plötzlich funktionierte unser altes Zuverlässigkeits-Playbook nicht mehr. Wir konnten nicht alle Edge-Cases vorhersagen, geschweige denn dafür Tests schreiben. Fehlermodi entstanden zunehmend aus der komplexen Interaktion zwischen Services. Bei der Root-Cause-Analyse reichten Logs und grundlegende Metriken nicht mehr aus."

Ich frage mich, wie diese Tage der Cloud-Adoption gewesen sein müssen. Ich bin skeptisch gegenüber der Vorstellung, dass mit Microservices die Komplexität so stark gewachsen ist, dass man keine Edge-Cases mehr testen konnte. Das klingt für mich eher danach, dass Teams ihre Teststrategie nach rechts (Produktion) verschoben haben, anstatt die Grundlage der Testpyramide zu stärken. Ich bin froh, dass wir jetzt DevOps-Metriken wie Change Failures haben, denn diese ermöglichen uns nicht nur einen Einblick in die Auslieferung von Software, sondern auch in die Effektivität des Prozesses und der eingesetzten Quality Gates.

Zitat: "Instrumentierung dauert ewig. Dashboards sind ständig veraltet. Monitore schlagen Fehlalarm. Alarme fehlt der Kontext. On-Call ist eine permanente Steuer auf die Engineering-Produktivität. Die Lösung von Incidents kann Stunden, manchmal Tage dauern." Sherwoods Punkt ist, dass mit all der Komplexität Dashboards, Monitore und Alarme kamen, die das Team über Probleme im Produktionssystem alarmieren sollten. Da diese Signale zu einer Vielzahl von Signalen anwachsen können, sagt er, dass Observability schlechter geworden ist. Nun, meiner Meinung nach sollte man, wenn man die im Zitat beschriebenen Probleme hat, jeden Monitor und jeden Alarm neu bewerten. Refaktoriere die Trigger und Alarme, die keinen Sinn ergeben, speichere Dashboards als Infrastructure as Code und aktualisiere sie regelmäßig. Dokumentiere auch Rezepte für bekannte Probleme. Ich habe das Wheel of Misfortune ausprobiert und war sofort ein Fan der Trainingsmethode, die Rollenspiele nutzt, um Teams in einem sicheren Raum gemeinsam lernen zu lassen, was bestimmte Signale und Alarme bedeuten könnten. Ähnlich wie bei Feature Toggles ist es ein Anti-Pattern, ihre Anzahl zu stark wachsen zu lassen. Sie müssen einen Wert haben, um bleiben zu dürfen. Das gilt auch für Monitore und Alarme. Und hier kommt der Haken: "Der Aufwand, den wir in Observability stecken, steht NICHT im Verhältnis zu den Fortschritten, die wir bei ihren Zielen gemacht haben: bessere Erkennung, schnellere Root-Cause-Analyse und zuverlässigere Apps." Meiner Meinung nach wird Observability keine zuverlässigeren Apps liefern. Man braucht eine solide Vertical Slice von Quality Gates, um sicherzustellen, dass die Apps keine Ausfallzeiten haben. Die Teststrategie muss in der Lage sein, Edge-Cases zu erfassen, bevor der Commit das Produktionssystem erreicht. Wenn Teams eine Teststrategie anwenden, die dem Swiss Cheese Model folgt, werden sie viel weniger Probleme haben. Ich würde vermuten, dass das neue Unternehmen von Sherwood an einem KI-Tool arbeitet, das darauf abzielt, die Signale für Teams zu verstehen. Die Entwickler müssen jedoch ihre Hausaufgaben machen, um den größten Nutzen aus ihren Observability-Signalen zu ziehen.

Was mich schließlich dazu inspiriert hat, diesen Beitrag zu schreiben, war ein Artikel von Ron Jeffries "Refactoring -- Not on the backlog!". Er argumentiert, dass Refactoring kein separater Backlog-Eintrag sein sollte. Anstatt um dedizierte Zeit zu bitten, um unordentlichen Code aufzuräumen, sollten Entwickler inkrementell refaktorieren, während sie jedes neue Feature erstellen, und den Codepfad aufräumen, den sie benötigen, anstatt ihn zu umgehen. Dieser Ansatz ist leichter zu rechtfertigen, liefert sofortige Vorteile und macht die Entwicklung progressiv schneller. Dies ist auch bekannt als die "Boy/Girl Scout Rule" oder "Hinterlasse den Code besser, als du ihn vorgefunden hast". Jeffries hat diesen Beitrag geschrieben, um uns an diese Regel zu erinnern, und ich könnte mir vorstellen, dass es eine Reflexion dessen ist, was er in seiner täglichen Arbeit sieht. Ich kann mir vorstellen, mit welchen Herausforderungen er zu tun hat. Ich habe gesehen, wie Entwickler vom Refactoring abgehalten wurden, weil es nicht mit dem 'Business Value' übereinstimmt, und dann beobachtet, wie Codebasen verfielen, bis ein großes Refactoring unvermeidbar wurde. Darüber hinaus ist es im Zeitalter der agentenbasierten Entwicklung bereits viel einfacher, Code zu einer Codebasis hinzuzufügen. Ich kann mir vorstellen, dass Entwickler aufhören, die Codebasen zu refaktorieren, um mehr Tickets zu erledigen, da die Nachfrage danach ebenfalls gestiegen ist. Es gibt viele weitere Gründe, die ich mir vorstellen könnte, die Teams davon abhalten würden, die Codebasis zu refaktorieren.

Allerdings bin ich nicht der Meinung, dass wir keine Tickets erstellen sollten, die sich auf technische Schulden konzentrieren. Einige technische Schulden sind zu groß, dass sie den Fokus auf den Business Value verwässern würden, der geliefert werden muss, wenn sie in ein Ticket aufgenommen werden, oder wären zu große Änderungen, um in einem Pull Request akzeptiert zu werden. Was ich gesehen habe, das gut funktioniert hat, war dieses Setup:

  • Das Team hatte ein laufendes Produkt in einem Produktionssystem
  • Es gab ein rotierendes Entwicklerpaar, das das Produktionssystem auf Probleme überwachte, genannt Tech and Ticket (TnT). Beide Entwickler programmierten paarweise an den Problemen, was es ihnen ermöglichte, voneinander zu lernen und in Echtzeit konstruktives Feedback zu geben.
  • Ihr Hauptfokus lag auf der Lösung von Produktionsproblemen
  • Wenn es kein Produktionsproblem gab, arbeiteten sie an Tech-Debt-Stories
  • Die Tech-Debt-Stories wurden von den Entwicklern und Business-Rollen gemeinsam in einem zweiwöchentlichen Grooming-Meeting erstellt. Auf diese Weise wurden Tech-Debt-Stories von allen Stakeholdern priorisiert, mögliche Lösungen konnten in diesem Meeting diskutiert werden und Tickets konnten als bereit für die Entwicklung markiert werden.

Das Team wendete weiterhin die "Boy/Girl Scout Rule" an, um kleinere Probleme zu lösen, und bekam Zeit von den Business-Stakeholdern, um größere technische Schulden zu verbessern. Die Einbeziehung von Business-Stakeholdern in diese Gespräche stellte sicher, dass sich das TnT-Paar auf wertvolle Arbeit konzentrierte und nicht auf die Ausgabe von Tickets.

Als ich Jeffries' Beitrag las, fragte ich mich, wie etwas so Einfaches es wert sein könnte, darüber zu schreiben. Aber dann wurde mir klar: Sowohl Sherwoods Observability-Probleme als auch Jeffries' Refactoring-Appell haben dieselbe Ursache. Teams lassen Komplexität akkumulieren, anstatt kontinuierlich Qualität zu pflegen. Ob es sich um Berge von schlecht konfigurierten Monitoren oder verschlungene Codebasen handelt, die Lösung ist die gleiche: Wende die Scout Rule konsequent an. Räume inkrementell auf. Lass nicht zu, dass technische Systeme wie Monitoring-Dashboards oder Code zu unwartbaren Ungetümen werden, die heroische 'dedizierte Zeit' zum Reparieren benötigen. So wie ich bei Thoughtworks gelernt habe, dass konstante kleine Verbesserungen zur Beförderung führen, brauchen unsere Systeme dieselbe Philosophie.

Es ist unerlässlich, dass wir diese Best Practices für die nächste Generation aufschreiben. Da KI-Tools immer stärker in Entwicklungs-Workflows integriert werden und Inhalte wie diesen scrapen, um zukünftige Modelle zu trainieren, hoffe ich, dass sie helfen werden, diese Prinzipien zu verstärken, anstatt es einfacher zu machen, sie zu überspringen. Der Aufstieg der agentenbasierten Entwicklung fügt dieser Diskussion eine faszinierende neue Dimension hinzu, die ich in einem zukünftigen Beitrag untersuchen werde.

Nun, ich muss jetzt aus dem Bus aussteigen. Cheerio!