- Bei Software ist vieles unsicher.
- Warum ist das so unsicher?
- Der größte Grund ist die vorhandene Komplexität des Business.
- Durch diese Komplexität verändert sich die Situation fortlaufend, wodurch die Vorhersagen von Entwicklerinnen und Entwicklern mit hoher Wahrscheinlichkeit falsch liegen.
- Sorgfältig aufgebaute Türme stürzen ein und werden direkt zu technischer Schuld.
- Ein weiterer Grund ist der Mangel an Wissen und Erfahrung.
- Fehlen Wissen und Erfahrung, können Entwicklerinnen und Entwickler selbst erzeugte technische Schuld anhäufen.
- Die Komplexität des Business ist ein externer Faktor, den Entwickler nicht kontrollieren können, während Wissen und Erfahrung interne Faktoren sind, die sie kontrollieren können.
- Für Entwicklerinnen und Entwickler gibt es drei Wege.
- Den pessimistischen Weg, zu glauben, Widerstand gegen Komplexität sei sinnlos.
- Dann sagt man Dinge wie: „Es wird ohnehin geändert, also machen wir es einfach“ oder „Technik ist bedeutungslos“.
- Weil es der bequeme und komfortable Weg ist, kann man sich unbemerkt dafür entscheiden.
- Den Weg, Komplexität auszublenden und nur an ideale Wunschvorstellungen zu glauben.
- Man glaubt, mit einer einzigen Technologie, die man selbst für ideal hält, alles lösen zu können.
- Das führt zu starrem und uniformem Denken.
- Entwickler geraten leicht auf diesen Weg, aber es ist schwer, wieder herauszukommen.
- Den Weg, Komplexität anzunehmen und sich ihr zu stellen.
- Auch wenn man akzeptiert, dass Perfektion unmöglich ist, sucht man weiter nach einem besseren Weg.
- Es ist ein schwieriger Weg, den man aushalten muss.
- Softwareentwicklung hat immer wieder gegen Komplexität gekämpft.
- Architektur, Methodologien, Agile usw.
- Was wird als Nächstes auftauchen?
- Zerstörungsorientierte Entwicklung
- Betrachtet man die Realität, verfällt man leicht in den pessimistischen Gedanken, dass am Ende sowieso alles gelöscht wird.
- Denn es ist sehr schmerzhaft, den von uns mühsam geschriebenen Code selbst zu löschen, weil er sich wie ein Fehlschlag anfühlt.
- Warum nicht umgekehrt denken und ihn so bauen, dass er sich gut löschen lässt?
- Ist Zerstörung etwas Gutes?
- Ohne Zerstörung kann nichts Neues entstehen.
- Es gibt in der Software grob zwei Arten von Zerstörung: Pivot und Refactoring.
- Ein Pivot ermöglicht es Organisation und Produkt, einen besseren Weg zu wählen.
- Refactoring ist unverzichtbar, um die Lebensdauer von Software weiter zu verlängern.
- Was ist also zerstörungsorientierte Entwicklung?
- Eine Methodik, die akzeptiert, dass Code irgendwann zerstört wird, und die Entwicklung genau daran ausrichtet.
- Sie orientiert sich an drei Grundprinzipien.
- Wenn es Unsicherheit gibt, reduziert man sie so weit wie möglich.
- Wenn mehrere Wege zur Auswahl stehen, entscheidet man sich für den, der leichter zu zerstören ist.
- Man behält nur das Notwendige bei. Alles Unnötige wird daher entfernt.
- Analyse -> Abgrenzung von Grenzen -> Code-Implementierung -> Entfernen von Komplexität
- Der Kern besteht darin, Unsicherheit durch interne Faktoren zu verringern und auf Zerstörung vorbereitet zu sein, die durch unvermeidbare externe Faktoren verursacht wird.
- Trennung von Grenzen
- Unsicherheit ist die Änderungsrate, und auf dieser Grundlage ist eine Trennung möglich.
- Entwickler müssen sich auf externe Faktoren vorbereiten und zugleich die Änderungsrate durch interne Faktoren so weit wie möglich senken.
- Da sich die Änderungsraten der einzelnen Faktoren je nach Organisation unterscheiden können, lassen sie sich nicht in festen Zahlen ausdrücken -> sie werden heuristisch gemessen.
- z. B. Story-Point-Schätzung
- Man muss entscheiden, auf welcher Abstraktionsebene die Trennung erfolgen soll.
- Zerstörbarkeit
- Bei der Implementierung wählt man gemäß den Grundprinzipien die leichter zerstörbare Variante.
- Die Zerstörbarkeit lässt sich anhand von Unabhängigkeit, Verständlichkeit und Kontrollierbarkeit beurteilen.
- Unabhängigkeit wird nach dem Grad von Kopplung und Kohäsion sowie danach beurteilt, wie gut das Single-Responsibility-Prinzip eingehalten wurde.
- Verständlichkeit beschreibt, in welchem Maß Entwickler den Code ansehen und verstehen können.
- Kontrollierbarkeit beurteilt, ob es sich um einen Bereich handelt, den Entwickler kontrollieren können.
- Entfernen von Komplexität
- Man muss prüfen, ob es Unnötiges gibt, und es entfernen. Letztlich sollte in der Codebasis nur das Notwendige verbleiben.
- Wenn die Arbeit wegen Problemen wie Deadlines schwer umzusetzen ist, reicht es auch aus, sie nur zu dokumentieren und später daran zu arbeiten.
- Denn interne Faktoren sind kontrollierbar.
- Entscheidend ist, im Hinblick auf mögliche Zerstörung so viel Einfachheit wie möglich zu bewahren.
- Die Kunst der Code-Zerstörung
- Es gibt verschiedene Prinzipien und Methoden, um Code gut zu löschen.
- Schritte aufteilen (Refactoring-Muster)
- Referenzielle Transparenz wahren
- Das Single-Responsibility-Prinzip einhalten
- Das Interface-Segregation-Prinzip einhalten
- Strangler-Fig-Pattern
- Methodenspezialisierung
- Doppelten Code schreiben
- Änderungsrate dokumentieren
6 Kommentare
Ich kann der Aussage nicht wirklich zustimmen, dass technische Schulden durch mangelndes Wissen und fehlende Erfahrung entstehen.
-> Es kann auch sein, dass für die Umsetzung der Anforderungen nicht genug Zeit zur Verfügung steht, oder dass man in der Zusammenarbeit mit anderen im Interesse der Abstimmung gewisse technische Schulden bewusst in Kauf nimmt — die Situationen sind vielfältig.
Ich finde es auch fraglich, Wissen und Erfahrung als interne Faktoren zu betrachten, die Entwickler kontrollieren können.
-> Das Business ist komplex, und man kann nicht vorhersagen, welche Situationen eintreten werden; es ist unmöglich, jedes mögliche Szenario laufend im Voraus zu lernen. Und selbst wenn man sich erst in der konkreten Situation einarbeitet, kann beim nächsten Mal ein völlig neues Problem auftreten, sodass dieses Wissen dann wieder nutzlos wird.
Hallo. Vielen Dank für Ihre Rückmeldung.
Ich denke, dass man das Wesentliche erst dann erkennen kann, wenn man Extreme betrachtet. Aus dieser Perspektive dachte ich, dass man, wenn man über „Wissen und Erfahrung“ vollständig verfügt hätte, innerhalb der gegebenen Zeit Code statt technischer Schulden hätte erstellen können.
Zeitmangel lässt sich in zwei Fälle unterteilen. Der erste ist der Fall, dass schlicht die für die Implementierung nötige Zeit fehlt. In diesem Fall fehlt unabhängig von Wissen und Erfahrung die physische Zeit, um Code zu schreiben. Damit sind die Voraussetzungen von vornherein so, dass das Ziel nicht erreichbar ist. Der zweite ist der Fall, dass die Zeit fehlt, um herauszufinden, was gut ist. In solchen Fällen beendet man die Arbeit, indem man Code nur auf Basis des Wissens schreibt, das man im Moment hat, weil die Zeit fehlt, sich über Implementierungsmethoden zu informieren oder etwas Besseres zu finden. Wenn man die Arbeit so abschließt, weiß man zwar, dass „irgendetwas nicht stimmt“, aber nicht genau, wie man es korrigieren soll. Wenn man exaktes Wissen gehabt und durch entsprechende Erfahrung Selbstvertrauen gewonnen hätte, wäre dieses Problem vermutlich nicht entstanden.
Ich denke, dass der oben beschriebene Zeitmangel meine Ansicht stützt. Natürlich ist das in der Realität ein sehr schwieriges Problem. Ich habe lediglich eine idealisierte Sicht formuliert. Ein Zustand vollständigen Wissens und vollständiger Erfahrung ist selten, und wie Sie gesagt haben, gibt es sicher auch Fälle, in denen man etwas bewusst zum Wohl der Organisation in Kauf nimmt. Das kann frustrierend sein, aber ich habe dieses Problem, „wenn man es extrem betrachtet“, als ein Problem angesehen, das aus mangelndem Wissen und mangelnder Erfahrung entstanden ist.
Der zweite von Ihnen angesprochene interne Faktor ist einfach. „Das Geschäft ist komplex, sodass man nicht vorhersagen kann, welche Situationen eintreten werden …“ — dieser Teil entspricht in meinem Text der „Komplexität des Geschäfts“. Mit anderen Worten: ein Problem, das durch externe Faktoren verursacht wird. Weil es ein externer Faktor ist, kann der Entwickler ihn nicht kontrollieren und empfindet Furcht. Auch hier gilt: Wenn man es extrem betrachtet und annimmt, dass es keine geschäftliche Komplexität gäbe, bliebe nur noch der vom Entwickler geschriebene Code übrig. Dann bliebe intern nur noch das Problem von „Wissen und Erfahrung“, das kontrollierbar ist.
Natürlich ist auch der von mir geschriebene Text nur meine Meinung. Es kann durchaus Gegenbeispiele geben. Ich denke, dass der Austausch von Meinungen eine Gelegenheit ist, einen besseren Weg zu finden. Ich freue mich auch künftig über viele Rückmeldungen. Vielen Dank.
Vielen Dank für Ihre freundliche Antwort.
Ich habe den Artikel mit großem Interesse gelesen. Je nach Phase einer Organisation scheint sich auch zu unterscheiden, was als verfrühte Optimierung und was als Overengineering gilt. Der schwierige Punkt ist, dass es sich um Code handelt, den man ohnehin irgendwann neu schreiben müsste, zugleich aber unklar ist, ob dieser Moment überhaupt jemals kommt. Ich entscheide das manchmal auch anhand der Frage: Wenn der xxx-Dienst oder die Funktion wegfällt, wo sollten sich dann der yyy-Code und die Daten sinnvollerweise befinden? Mich würde auch interessieren, wie andere dabei vorgehen.
Ich denke nicht nur darüber nach, ob Code verschwinden oder geändert werden kann, sondern auch Daten oder Schemata.
Ich wollte auch etwas zum Thema Daten ergänzen, aber es fiel mir schwer, dazu gute Gedanken zu fassen. Da es sich um einen kritischen Bereich handelt, lässt er sich nicht leicht anfassen, und man kann schnell in der Migrationshölle landen, daher war ich vorsichtig.
Wie Sie gesagt haben, scheint die Entwurfsphase am Anfang sehr wichtig zu sein. Der Schlüssel dürfte darin liegen, RAW so gut wie möglich aufzubauen. Oder aber eine Event-Sourcing-Architektur könnte im Hinblick auf Löschung von Vorteil sein. Natürlich habe ich diese Architektur selbst noch nie wirklich eingesetzt, daher weiß ich nicht, ob das tatsächlich sinnvoll ist.