Die Realität, in der man nicht lernt, wie hochwertige Software entwickelt wird
(florianbellmann.com)- Viele Projekte schieben QA-Maßnahmen nach hinten und verlassen sich kurz vor dem Release auf einen großen QA-Sprint, nur um im nächsten Zyklus dasselbe Chaos zu wiederholen
- Informatikausbildungen investieren Zeit in Algorithmen und Sprachen sowie in Projektmanagement, behandeln Software-Qualitätssicherung jedoch oft nicht auf praxisnahem Niveau
- In Unternehmen wird bei fehlendem Budget, Verzögerungen in der Entwicklung oder wachsendem Scope zuerst an QA gekürzt, und es wird anfällige Software ausgeliefert, die nur minimale unstrukturierte Tests durchlaufen hat
- Um für QA zu argumentieren, sollte man statt abstrakter Aussagen wie „stabiler“ lieber die Kosten des Unterlassens benennen, etwa höhere Entwicklungskosten oder längere Release-Stabilisierungsphasen
- Statt alle Qualitätssysteme auf einmal aufzubauen, ist es realistischer, zuerst Kernfunktionen zu schützen, die direkt mit dem Kundennutzen verbunden sind, und Tests für neue Funktionen gleich bei der Implementierung mitzuschreiben
QA wird bis kurz vor dem Release verschoben
- In vielen Projekten wird entwickelt, obwohl wichtige Qualitätssicherungsmaßnahmen fehlen
- Auch wenn die Notwendigkeit bekannt ist, wird die tatsächliche Umsetzung oft auf einen großen QA-Sprint direkt vor dem Release verschoben
- Dieser Ansatz erhöht den Stress und führt nur dazu, dass die Software gerade eben lauffähig gemacht wird
- Im nächsten Release-Zyklus wiederholt sich dasselbe Chaos, und strukturelle Verbesserungen lassen sich nur schwer etablieren
Die Qualitätslücke zwischen Ausbildung und Praxis
- Informatikstudiengänge konzentrieren sich vor allem auf Algorithmen, die Funktionsweise von Computern sowie die Geschichte und Konzepte von Programmiersprachen
- Es kann zwar Semester geben, in denen Projektmanagement oder Scrum behandelt werden, QA fällt jedoch mitunter komplett weg
- Da mehr als 90 % der Absolventen im Unternehmenskontext arbeiten, brauchen sie die Fähigkeit, innerhalb vorgegebener Zeit fehlerfreie Software zu liefern
- QA in der Ausbildung zu vernachlässigen, passt nicht zu den tatsächlichen Anforderungen im Berufsalltag
Warum in Unternehmen zuerst bei QA gekürzt wird
- Wenn es in Projekten Budgetprobleme gibt, werden QA-Standards und -Maßnahmen oft als Erstes gestrichen
- QA wird häufig ans Ende des Projekts geschoben; wenn sich die Entwicklung verzögert oder der Scope wächst, fehlt dann die Zeit zur Qualitätssicherung
- Das Ergebnis ist, dass nach minimalen unstrukturierten Tests Software mit fragiler Struktur ausgeliefert wird
- Einige Teams haben zwar QA-Standards, doch meist werden sie von Senior-Teammitgliedern gegenüber dem Rest des Teams durchgesetzt
- Selbst wenn Standards existieren, führt das kaum zu ausreichender Qualitätssicherung, wenn das Team Tests nur schreibt, um Projektmanagement-Kennzahlen zu erfüllen
Der erste Schritt, um wiederkehrende Qualitätsprobleme zu durchbrechen
- Darauf hinzuweisen, dass QA-Maßnahmen fehlen, erfordert Erfahrung und Selbstvertrauen
- Crunch kurz vor dem Release, ausfallende Produktionssysteme und fehlendes Monitoring belasten am Ende das gesamte Team
- Verbesserungen, die für Manager nicht direkt sichtbar sind, lassen sich ähnlich wie Refactoring nur schwer vermitteln, und QA kann noch ungreifbarer wirken, wenn man sie nie richtig erlebt hat
- Erst wenn Probleme immer wieder angesprochen und Diskussionen erneut angestoßen werden, entsteht ein erster Schritt zur Veränderung
QA in der Sprache des Geldes erklären
- Aussagen wie „Die Software wird stabiler“ oder „Sie wird leichter wartbar“ sind für Menschen außerhalb der Codebasis oft schwer greifbar
- Entwickler sollten über die Kosten sprechen, die entstehen, wenn man QA nicht macht
- Beispiele für solche Formulierungen sind:
- Wenn wir das jetzt nicht tun, steigen Entwicklungsaufwand und Kosten in vier Monaten um 15 %
- Wenn wir nicht für alle Funktionen Unit-Tests schreiben, dauert die Release-Stabilisierungsphase jedes Mal länger
- Je mehr neue Funktionen hinzukommen, desto mehr Nebenwirkungen müssen bei jedem Release manuell getestet werden, wodurch der Fortschritt pro Release sinkt
- So eine Argumentation ist eine Sprache, die Business und Management leichter verstehen
- QA-Maßnahmen können letztlich das Leben von Entwicklern und Managern gleichermaßen verbessern
Mit der minimal wirksamen Dosis beginnen
- Wer QA als große Vorabinvestition überplant, blockiert den Projektfortschritt und bekommt schwer die Zustimmung der Stakeholder
- Ein realistischer Startpunkt ist, die wichtigsten Teile der Anwendung zu identifizieren
- Meist gibt es bestimmte Use Cases, Funktionen oder Kernverhalten, von denen die gesamte Anwendung abhängt
- Zuerst sollten die Kernfunktionen getestet werden, die für den Kundennutzen zwingend korrekt funktionieren müssen
- Die minimal wirksame Dosis (MED) bezeichnet die kleinste Menge, die das gewünschte Ergebnis erzeugt
- Bei QA kann MED eines der folgenden Dinge sein:
- ein manueller Testplan
- automatisierte Tests in der Pipeline
- andere Maßnahmen, die das Kernverhalten absichern
- Sobald die Kernfunktionen abgesichert sind, kann die Stabilität schrittweise ausgeweitet werden
- Für jede neue Funktion sollten Unit-Tests ergänzt werden, und auch Informationen, die man nicht kontrollieren kann, wie externe APIs oder Nutzereingaben, müssen validiert werden
- Auch QA sollte iterativ und schrittweise verbessert werden
QA-Fragen, die man bei neuen Projekten prüfen sollte
- Wenn man ein neues Projekt startet oder dazukommt, sollte man prüfen, ob es zumindest in kleiner Form ein QA-Konzept gibt
- Das Team sollte über folgende Fragen nachdenken:
- Was liefern wir aus?
- Was muss unbedingt funktionieren?
- Wie stellen wir das sicher?
- Welche Maßnahmen setzen wir bewusst nicht um, und warum?
- Wenn diese Punkte dokumentiert und um einen Testplan ergänzt werden, entsteht eine gute Grundlage, auf der sich die Software weiterentwickeln kann
- Der gewählte Ansatz sollte regelmäßig überprüft werden, zum Beispiel quartalsweise
Tests gemeinsam mit der Implementierung schreiben
- Auch ohne TDD wird empfohlen, Tests parallel zum Schreiben der Software zu verfassen
- Der Zeitpunkt der Implementierung ist ein guter Zeitpunkt, um Tests zu schreiben
- Werden Tests gleichzeitig mit der Implementierung geschrieben, erzwingt das eine Struktur, in der der Code tatsächlich testbar ist
- Wenn Tests erst später an bestehende Software angehängt werden, zeigt sich oft, dass der Code zu stark gekoppelt ist oder gegen das Single-Responsibility-Prinzip verstößt
- Tests sind eine Beschreibung dafür, dass das gewünschte Verhalten verstanden wurde und wie erwartet funktioniert, und sie dienen zugleich als eine Form von Code-Dokumentation
Auswirkungen auf Projekt und Einzelne
- Wer Qualitätsdiskussionen anstößt und mögliche Lösungen vorschlägt, zeigt dem Umfeld, dass ihm das Projekt wichtig ist
- Diskussionen über Qualität können den eigenen Einflussbereich als Entwickler erweitern
- Auch die Lebensqualität von Entwicklern und Managern kann dadurch steigen
- Projekte können mit QA-Maßnahmen in gesundem Tempo wachsen
- Niemand muss ein QA-Botschafter sein, aber man kann mit einer kleinen MED beginnen und im Team bessere Vorgehensweisen vorleben
1 Kommentare
Meinungen auf Hacker News
Solche Inhalte werden durchaus gelehrt. Sie stehen nur nicht in den zentralen Informatik-Fächern, sondern eher in Wahlfächern wie Software Engineering.
An der CMU gibt es auch Master- und Promotionsprogramme in Software Engineering, die das behandeln, was der Blogbeitrag anspricht, und noch mehr. Zwischen CS und SE gibt es zwar eine große Kluft, aber so weit zu sagen, „niemand lehrt, wie man hochwertige Software baut“, stimmt nicht.
Ironischerweise mochte ich als Student die Software-Engineering-Fächer am wenigsten. Ein Design-Patterns-Kurs mit strikter UML-Treue wirkte veraltet, und ein QA-Kurs über TDD und Tools im Java-Ökosystem war ebenfalls langweilig. Als ich ein paar Jahre später in ein Team kam, das Test-Workflows und Tools für Software mit hohen Sicherheitsanforderungen aufbaute, waren meine Kollegen überrascht, dass ich schon wusste, was zu tun war.
Selbst wenn es gelehrt wird, ist es meist veraltet oder sehr wörtlich auf Dinge wie das Schreiben von Webanwendungen verengt. Wenn es einen Kurs gegeben hätte, der sich auf Implementierung, Teamarbeit und den Aufbau komplexer Systeme konzentriert, hätte ich ihn wirklich gern belegt.
Solche Inhalte sollten nicht als Wahlfach oder Masterprogramm behandelt werden; es braucht grundständige Software-Engineering-Programme, und 90 % der CS-Studierenden sollten dorthin wechseln.
Die Codebase war ein einfacher Dienst für Viren-/Malware-Scans und so konzipiert, dass durch Scanner und Signaturen immer weitere Arbeit anfiel. Die Idee ist über 15 Jahre alt, hätte aber ein hervorragender fortlaufender Kurs werden können; schade, dass er den Fachbereich nicht überzeugen konnte.
Er hat meine Studienzeit zwar nicht ganz definiert, kam dem aber ziemlich nahe, und die Tatsache, dass die meisten Menschen, die Systeme entwerfen, diese Inhalte nicht kennen, löst zugleich Wut und existenzielles Grauen aus.
Der Grund, warum es leichter ist, mit Menschen mit CS-Abschluss zu arbeiten, ist, dass man ihnen seltener erklären muss, warum gute Algorithmen nötig sind oder warum man Parser und Kryptografie nicht selbst implementieren sollte.
Im Software Engineering gibt es dagegen keinen vergleichbaren Nachweis dafür, dass Naivität in Bezug auf Qualität, Teamarbeit und Zusammenarbeit mit anderen Teams ähnlich geglättet wurde. Es entstehen Menschen, die darin geübt sind, schnell furchtbaren, ungeprüften Code zu schreiben und zu verschwinden, bevor die Probleme hochgehen; das Management mag solche Leute und schaut auf diejenigen herab, die anschließend die Trümmer beseitigen.
Stringbasierte Protokolle mit klaren Trennzeichen lassen sich in der Regel sehr leicht parsen, und je nach Use Case reicht es, nur einen Teil abzudecken. Natürlich muss man Tests und funktionale Anforderungen berücksichtigen. Wenn man eine Sprache baut, kann der Rat anders ausfallen.
Anfänger bauen sie selbst, fortgeschrittene Entwickler und mittelgroße Projekte nutzen Parser-Generatoren, und auch die Leute, die die ausgefeiltesten Parser pflegen, bevorzugen wieder handgeschriebene Varianten. GCC verwendete früher einen bison-Parser, wechselte aber für bessere Fehlermeldungen zu einem handgeschriebenen rekursiven Abstiegparser, und Clang nutzt ebenfalls rekursiven Abstieg.
Die einzige Ausnahme, die ich persönlich kenne, ist jq, und deshalb ist es in der jq-Implementierung schwer, hilfreiche Syntaxfehlermeldungen zu erzeugen.
Einen Parser zu schreiben kann simpel genug sein, um in eine einzelne Übungsaufgabe zu passen, und handgeschriebener Parser-Code ähnelt am Ende einer LL-Grammatik. Parsing ist der einfachste Teil beim Schreiben von Compilern oder Sprachwerkzeugen; wenn ein handgeschriebener Parser für ein Team eine zu hohe Hürde ist, kann das ganze Projekt fragwürdig sein. Ich sage nicht, dass man niemals Parser-Generatoren verwenden sollte, aber ich würde lieber in einem Projekt mit gut getestetem handgeschriebenem Parser arbeiten als in einem, das den Build mit zusätzlichen Tools verkompliziert oder alte Werkzeuge wie Bison oder ANTLR verwendet.
Insgesamt scheinen die Standards aber höher zu sein als vor 20 Jahren. Source Control, Unit-Tests und CI/CD sind zum Beispiel nicht mehr umstritten.
Die Prämisse „Wir müssen fehlerfreie Software pünktlich liefern“ ist ein ziemlich schlechter Ausgangspunkt für einen Text über Qualitätssoftware.
Wenn man glaubt, bugfreien Code ausliefern zu können, ist es Zeit, den Beruf zu wechseln.
Selbst wenn man Unit-Tests, Integrationstests und User-Acceptance-Tests macht, bedeutet jede Codeänderung die Möglichkeit eines neuen Bugs. Wenn ein Entwickler sagt: „Ich liefere niemals fehlerhaften Code aus“, fragt man besser genauer nach, was damit gemeint ist.
Wenn man über „Ich habe die Funktion geschrieben“, „Ich habe die Funktion getestet“ und „Ich habe sogar die Funktion getestet, die über das Netzwerk aufgerufen wird“ hinauskommt, merkt man: Egal wie gut man Randfälle erfasst und wie gründlich QA ist, bei einer bestimmten Konfiguration, bestimmter Hardware oder einem bestimmten Kernel bleibt immer 0-day-undefiniertes Verhalten übrig. Man kann nur sagen, dass Tests, menschliche Augen und Reviews durchlaufen wurden und man deshalb fast garantiert keine Bugs hat — am Ende bleibt einem nur, die Daumen zu drücken.
Wenn die Behebung eine Woche dauert, der Bug aber nur wenige Nutzer in sehr seltenen Situationen betrifft, muss man ihn möglicherweise nicht beheben.
Es gibt Informatikprogramme, und es gibt Universitäten, die Praktika und Praxis betonen. Aber an vielen Hochschulen stammen CS-Fachbereiche aus der Mathematik und sind theorieorientiert.
Ich halte das für in Ordnung, so wie Chemie nicht Chemieingenieurwesen ist. Universitäten sind keine bloßen Berufsschulen; der Sinn fast jedes Abschlusses besteht darin, Denkfähigkeit zu trainieren und zu zeigen, dass man komplexe Inhalte erfassen kann.
Eine rein universitäre Ausbildung, die nicht berücksichtigt, ob etwas in der Praxis nützlich ist, schadet der Bildung; aber eine rein berufliche Ausbildung, die nur Methoden ohne Verständnis lehrt, ist ebenfalls nicht nützlich. Allerdings sind echte Berufsschulen auch nicht ganz so: Selbst wenn sie schwierige Teile überspringen, vermitteln sie bei wichtigen Dingen meist ein tiefes Verständnis.
Trotzdem ist es gut, um einen Einblick in die professionelle Softwarewelt zu bekommen.
So etwas lernt man in guten Entwicklungsorganisationen. Vor 10 bis 15 Jahren waren das grob die FAANG-Unternehmen, heute sind Orte wie TailScale ein Beispiel.
Man kann durchaus vermeiden, lauter nutzlose Microservices und Schichten aus Docker, JSON-Serialisierung/Deserialisierung und Unit-Tests nur für Coverage zu haben, während QuickCheck, Hypothesis und Fuzzing ignoriert werden. All das ist möglich: gestapelte Änderungspakete, On-Call-Rotation des Teams, das den Code schreibt, Minimierung von Fehlern durch dynamisches Linken und nicht erzwungene Abhängigkeiten, Design passend zu Runtimes verwalteter Sprachen und sogar die Forderung, die gut lesbare verbale Syntax einer Sprache als „Lesbarkeit“ zu behandeln. Es wird immer wieder abgetan, aber wie man Qualitätssoftware ausliefert, ist öffentliches Wissen.
Vielleicht steckt darin ein Gedanke zu Qualitätssoftware, aber dieser Kommentar ist schwer zu verstehen.
Ich würde gern wissen, worauf man achten sollte und ob es empfehlenswerte Bücher oder Kurse gibt.
Es ist schwer, zu Messwerten zu kommen, die valide genug sind, um Aussagen wie „Wenn wir das jetzt nicht tun, steigen Entwicklungsaufwand und Kosten in vier Monaten um 15 %“ zu stützen.
In einem Startup sagten mir einmal zwei Gründer: „Schreib keine Unit-Tests.“ Ich habe nicht diskutiert und verstanden, dass die eigentliche Bedeutung dieser Aussage war: Wir waren zu langsam, also sollten wir so schnell wie möglich ausliefern. Wir lieferten schnell aus, hielten die Qualität aufrecht und schrieben auch Unit-Tests. Sie mussten das nicht wissen; sie brauchten nur Ergebnisse. Der versteckte Kern solcher Diskussionen ist, dass die meisten Softwareorganisationen nicht wissen, wie man schnell und zugleich mit Qualität ausliefert. Es gibt keine magische Formel, es braucht individuelle Handwerkskunst und ist zugleich ein Teamsport. Die Situation ist überall anders; leichtgewichtige Prozesse können teilweise helfen, aber ihre Wirkung ist begrenzt. Am Ende braucht man ein gutes Team mit Erfahrung, den richtigen Wertvorstellungen und der Weisheit, sich auf die Wertlieferung zu konzentrieren.
Die Annahme, dass Universitäten lehren, wie man in der Industrie Software baut, ist eine ziemlich gewagte Behauptung.
Außerdem wirkt dieser Text wie aus den 90ern, als Software noch per CD oder Diskette verteilt wurde. Heute verschwimmt der Begriff „Release“ durch Continuous-Deployment-Pipelines oft, und das gilt als gute Praxis. In so einer Situation wirkt die Vorstellung, dass eine QA-Abteilung manuell garantiert, ein Release enthalte keine Bugs, ziemlich veraltet.
Es gibt auch Menschen, die Code schreiben, der auf Geräten ausgeliefert wird, bei denen Upgrades nicht einfach sind.
Wenn man die Zustimmung von jemandem braucht, muss man dieser Person erklären, warum es eine gute Idee ist.
Aussagen wie „es ist stabiler“ oder „es wird leichter wartbar“ kommen bei Menschen, die nicht direkt an der Codebase arbeiten, nicht an. Entwickler müssen über die Kosten sprechen, die entstehen, wenn QA nicht gemacht wird — also in der Sprache des Geldes. Auch wenn sich „Aber das ist doch der richtige Weg!“ wie ein unwiderlegbares Argument anfühlt, interessiert sich die Person, die zustimmen muss, möglicherweise nicht für diese Korrektheit. Dieses Prinzip gilt nicht nur dafür, Software richtig zu reparieren, sondern für fast alles am Arbeitsplatz.
Wenn man erklären muss, warum Qualität wichtig ist, sind sie mindestens genauso unwissend wie man selbst, vielleicht sogar noch mehr. Solche Organisationen müssen ihr Schicksal akzeptieren. In reifen Unternehmen wird man dagegen schneller und besser entlohnt und entwickelt auch schneller ein Gefühl dafür, wie ein Business funktionieren sollte. Natürlich muss man selbst beweisen, dass die investierte Zeit tatsächlich zu Verbesserungen führt; es darf kein donquichottischer Impuls eines Amateurs sein.
Von Qualität, kurzer Zeit, geringer Kommunikationskomplexität und wenig Geld kann man ungefähr drei haben; dabei ist Zeit eher eine abhängige Variable
Menschen versuchen, auf Software, die zugleich Teamsport und Ingenieursdisziplin ist, fabrikartige Prozesse und Strukturen anzuwenden. So wie man ein Basketballteam nicht in Angriffsphasen, Verfahren und Checklisten zerlegt und daraus aufbaut oder trainiert, muss man Kommunikation minimieren und das Team wie eine Einheit handeln lassen. Das ist nicht der Aufbau von Prozessen, sondern der Aufbau von Teams und Individuen. Man plant zwar, aber wie Moltke sagte, hält kein Operationsplan den ersten Kontakt mit dem Feind zuverlässig aus. Die geschäftliche Denkweise glaubt jedoch, dass man mehr Prozesse hinzufügen müsse, weil der Plan nicht wie erwartet funktioniert hat, und sorgt dafür, dass Manager beim nächsten Scheitern Einzelpersonen die Schuld geben können. Prozesse haben ihren Platz, um sicherzustellen, dass Dinge innerhalb rechtlicher und moralischer Rahmenbedingungen geschehen, und um schlechte Randbedingungen zu reduzieren, etwa dass beim Testen versehentlich sämtliche Mittel eines Hedgefonds gesetzt werden. In den meisten Startups und Unternehmen werden sie jedoch auf eine Weise eingesetzt, die nicht das Team in den Mittelpunkt stellt
Einen klassischen Architekten schreit man auch nicht an, wann er fertig sei. Meist ist es vorbei, wenn der Kunde zufrieden ist oder eine Entscheidung trifft. Viel Entwicklung ähnelt dem
Ich frage mich, ob es überhaupt eine menschliche Tätigkeit gibt, in der die Eigenschaft Qualität erfolgreich gelehrt wird
Aus Erfahrung entsteht die Fähigkeit, etwas Hochwertiges zu schaffen, nur durch Übung, Übung, Übung
Umgekehrt bedeutet der Titel lediglich, dass Programmieren keine industrielle Praxis ist. Für diejenigen, die genau hingesehen haben, sollte das offensichtlich sein, aber manche weigern sich bis zum Schluss, es zu sehen
Schon beim Schreiben lernen viele Menschen, wie sie Qualität verbessern können. Man gibt Hinweise, was sie ausprobieren sollen, und, noch wichtiger, wie sie die Qualität des gerade Geschriebenen reflektieren und verbessern können
Übung hilft immer, aber auch Qualität wird von vielen Menschen gelernt und eingeübt
Beim Fliegenlernen lernt man Standards, aber mit der Zeit lernt man, die Toleranzen enger zu ziehen. Wenn bei einer Steilkurve zum Beispiel die Höhentoleranz ±100 Fuß beträgt, ist das das Minimum; man zielt auf 50 Fuß, 20 Fuß und schließlich darauf, dass sich die Nadel kaum bewegt. Das Ziel ist: „besser, immer besser, was kann man noch besser machen?“ Und beim Fliegen besteht man nicht nach einem Gesamtdurchschnitt, sondern nur, wenn alle Punkte erfüllt sind. Kulturell ist „zufriedenstellend“ nicht das Ende, sondern der Ausgangspunkt
Ich habe den Eindruck, dass diese Haltung ein deutlich kooperativeres Modell schafft. In der Luftfahrt wollen alle aufrichtig, dass alle erfolgreich sind, und wenn jemand scheitert, trägt man selbst einen Teil der Verantwortung. Es gab eine Kultur, in der man nach einem Fehler Wege finden musste, die Wahrscheinlichkeit künftiger Fehler zu senken; bei Fluggesellschaften spielt auch Flight Operations Quality Assurance (FOQA) eine große Rolle. In kleinen abgelegenen Flugbetrieben war das informeller, aber meist näher an einer „No-Blame“-Kultur; der Kern war: „Wie machen wir es besser?“
Qualität, Entscheidungsfindung und „das Richtige tun“ waren Kernbestandteile der Luftfahrtkultur. Bei einem seriösen Betreiber führt die Einschätzung, dass das Wetter zu schlecht ist, um sicher zu fliegen, unmittelbar zur Einstellung des Flugbetriebs; man startet nicht auf Biegen und Brechen, nur um die Aufgabe zu erledigen. Die Tech-Branche, in die ich neu gekommen bin, fühlt sich wie das Gegenteil an. Schon das Konzept des Minimum Viable Product zeigt das Problem. Es sollte nicht „Minimum Viable“ heißen, sondern „Produkt von minimal akzeptabler Qualität als Ausgangspunkt“. Das Minimum darf nicht das Ziel sein; es ist nur der Startpunkt
Wenn man nur übt, Müll zu produzieren, wird man lediglich gut darin, Müll zu produzieren. Es gibt tatsächlich Menschen, denen Qualität egal ist; in diesem Fall bricht die gesamte Prämisse zusammen