Trends in der modernen Software-Entwicklung

Wie Software-Entwicklung mit Hilfe moderner Methoden schneller, effizienter und zielgerichteter organisiert werden kann.

Von Neno Loje, freiberuflich tätiger Berater und MVP für Visual Studio ALM und Thomas Schissler, Coach und Consultant artiso AG, MVP für Visual Studio ALM

Build-Measure-Learn

Software-Entwicklung ist seit jeher ein Gebiet mit rasanten Veränderungen und Entwicklungen. Doch während sich in der Vergangenheit diese Entwicklungen zumeist auf einer technologischen Ebene abgespielt haben, erleben wir momentan die größten Veränderungen im Bereich der Prozesse und der Organisation der Softwareentwicklung. Vor allem finden agile Methoden immer stärker Einzug in Projekte aller Art, auch wenn die Interpretation von Agilität noch sehr unterschiedlich ist.

Dabei spielt ein Konzept eine besonders wichtige Rolle, welches als Build-Measure-Learn bezeichnet wird. Ziel ist dabei, durch kurze Zyklen nach Bewertung eines Zwischenergebnisses Entscheidungen für die nächsten Entwicklungsschritte zu treffen und so den Nutzen der Entwicklung zu optimieren. So einleuchtend sich dieses Konzept anhört, so herausfordernd ist jedoch die richtige Umsetzung. Viele Bereiche der Software-Entwicklung sind direkt oder indirekt betroffen und um dieses Konzept tatsächlich erfolgreich anwenden zu können, sind etliche tiefgreifende Veränderungen notwendig.

Wir wollen uns zunächst das Build-Measure-Learn-Konzept etwas näher anschauen und betrachten dann in den weiteren Kapiteln dieses Artikels die wichtigsten Veränderungen, die zur Umsetzung notwendig sind.

Während in der Vergangenheit versucht wurde, ein Software-Projekt möglichst gut zu planen und diesen Plan dann möglichst gut umzusetzen, geht Build-Meaure-Learn davon aus, dass wir erst im Laufe der Zeit bestimmte Fragen richtig beantworten können. Statt also einen Plan zu erstellen und diesem zu folgen, wird entschieden, was aus der aktuellen Situation heraus der nächste geeignete Schritt ist, der den größten Nutzen generiert. Dabei spielt der Kunde eine wesentlich größere Rolle, da er durch sein Feedback direkten Einfluss auf diese Entscheidungen hat.

Build-Measure-Learn Ansatz
Der Build-Measure-Learn Ansatz beschreibt, wie in kurzen Zyklen Ideen realisiert werden, um aus den Erfahrungen heraus die weitere Produkt​entwicklung zu planen.

Das Konzept von Build-Measure-Learn sieht dabei vor, dass eine Idee zunächst als Funktionalität in der Anwendung umgesetzt wird (Build). Diese Funktionalität wird den Anwendern oder einer kleinen Test-Gruppe zur Verfügung gestellt und wir ermitteln über den Schritt Measure Daten bezüglich des Nutzens dieser Funktion. Anschließend erfolgt der Schritt Learn, bei dem wir aus diesen Ergebnissen lernen, wie wir unsere Software-Anwendung verbessern können. Diese Verbesserungs-Ideen werden wieder umgesetzt, gemessen, daraus eine Lehre gezogen und so weiter.

Als Beispiel könnte der Betreiber eines Internet-Portals für Flugbuchungen eine Funktion einbauen, die es bestimmten Benutzern erlaubt, direkt nach der Buchung des Fluges ein Hotel am Zielflughafen zu reservieren. Anschließend würde gemessen werden, ob Anwender dieser Funktion eine Hotelreservierung häufiger vornehmen, als Anwender die diese Funktion separat aufrufen müssen. Ausgehend von diesen Erkenntnissen kann die Funktion weiter ausgebaut oder auch wieder eingestellt werden.

Damit wird auch akzeptiert, dass nicht alle Annahmen in der Software-Entwicklung korrekt sind und dass wir auch Fehler machen. Build-Measure-Learn ist dann effizient, wenn man es in kurzen Zyklen anwendet. Ein Beispiel dafür findet man z.B. bei Microsoft, wo die aktuelle Version des TF Service alle 3 Wochen aktualisiert wird und das Kundenfeedback direkten Einfluss auf die Weiterentwicklung einzelner Funktionen hat.

Damit bietet das Learn die Möglichkeit, die Funktionalität unserer Anwendung auf das zu fokussieren, was den Anwendern tatsächlichen bzw. den meisten Nutzen bringt und ggf. eine Funktionalität, die nicht genutzt wird, wieder zu entfernen. Um das Measure auszuführen, stehen verschiedene Methoden zur Verfügung. So kann z.B. das Anwenderfeedback direkt ausgewertet werden, wie es Microsoft mit dem UserVoice-Portal für Visual Studio vormacht. Oder durch Applikationsmetriken kann direkt gemessen werden, wie häufig eine bestimmte Funktion genutzt wird. Mit diesen Informationen erhält man eine gute Basis, Entscheidungen im Sinne des maximalen Kundennutzens zu treffen. Diese Aspekte stellen natürlich besondere Anforderungen an die Build-Phase, um in diesen kurzen Zyklen qualitativ hochwertigen und wartbaren Code zu liefern.

Fazit

Der Anspruch, die perfekte Software zu planen und anschließend umzusetzen, muss heute als unrealistisch angesehen werden, egal wie viel Planungsaufwand investiert wird. Als viel erfolgreicher hat sich herausgestellt, durch kleine Experimente Funktionalität in sehr kurzen Zyklen hinzuzufügen und dann herauszufinden, wie die Software weiter optimiert werden kann. Also weg vom Planen, hin zum Ausprobieren und sich eingestehen, dass die eine oder andere Idee vielleicht doch nicht so gut war.

Siehe auch Moderne Softwareentwicklung 1 - Trends in der modernen Softwareentwicklung

Modernes Anforderungs​management und Planung

Bevor das Entwicklungs-Team mit der Arbeit beginnen kann, werden die Wünsche und Ideen der einzelnen Stakeholder (Anspruchsgruppen wie Auftraggeber, Anwender, usw.) gesammelt und in eine Form gebracht, die die spätere Umsetzung begünstigt und das Ergebnis möglichst klar beschreibt.

Product Ownership

Die Koordination der Ideensammlung und die Formulierung einer Vision und der gewünschten Ergebnisse werden durch einen zentralen Produktverantwortlichen, den so genannten Product Owner (PO) unterstützt. Dieser arbeitet auf der einen Seite mit den Stakeholdern, um die Ideen zu erfassen, und zum anderen dient er dem Entwicklungs-Team als zentraler Ansprechpartner bei fachlichen Fragen. Ebenso kommuniziert der PO die Vision, also für wen die Software entwickelt wird (Zielgruppe) und welcher Nutzen mit ihr realisiert werden soll (Business Value).

Dabei geht es nicht um viele Worte, sondern im Gegenteil eher um nur so viel Text, wie nötig mit dem "richtigen" Detailgrad, um das gewünschte Resultat klar zu kommunizieren. Eine beliebte Form, die sich in den letzten Jahren etabliert hat, ist Formulierung von Anforderungen in Form einer "User Story".

User Story-Syntax
Abbildung: Die User Story-Syntax beschreibt in einer kompakten Weise das erwartete Ergebnis aus Sicht des Benutzers sowie welcher Nutzen für den Benutzer realisiert werden soll.

Product Backlog

Alle gesammelten Ideen kommen - häufig noch ungefiltert - auf eine große Liste, das so genannte Product Backlog. Da es bei den meisten Projekten mehr Wünsche gibt, als das Team in der Lage wäre direkt umzusetzen, wird die Liste zu einer Art Warteschlange. Die Anforderungen in der Warteschlange in der Reihenfolge, wie sie eingetragen wurden, einfach abzuarbeiten ist dabei allerdings häufig nicht die effizienteste Wahl. Aus diesem Grunde bewertet der Produktverantwortliche in Zusammenarbeit mit den Stakeholdern und dem Entwicklungs-Team das Product Backlog und sortiert es neu, sodass immer zuerst das "Wichtigste" abgearbeitet wird.

Dazu braucht es vor allem zwei Informationen zu jedem Element: die Größe und den Nutzen für den Benutzer bzw. das Unternehmen. Die Größe wird vom Entwicklungs-Team in Form einer relativen Schätzung beigesteuert, d.h. es werden Elemente auf dem Product Backlog verglichen, ohne konkret über die Umsetzung nachzudenken (Beispiel: "Ich weiß zwar nicht, wie viel ein Apfel wiegt, aber wenn ich ihn mit einer Erdbeere vergleiche, dann ist es mindestens Faktor 5."). Für den Mehrwert/Nutzen fragt man möglichst die Personen, die es am besten wissen sollten: die Stakeholder. Auch hier kann man die Elemente relativ gegeneinander abwägen (Feature A ist aus Kundensicht drei Mal so viel wert wie Feature B). Weitere Kriterien könnten noch das Risiko (besonders riskante Anforderungen möchte man vielleicht möglichst frühzeitig abarbeiten) bzw. Abhängigkeiten zwischen den Elementen sein.

Entwicklungs-Team

Die Umsetzung der Elemente vom Product Backlog (Product Backlog Items) erfolgt durch das Entwicklungs-Team. Dieses ist idealerweise nicht zu groß, sodass man sich gut untereinander abstimmen kann, am gleichen Ort angesiedelt und verfüget über alle Fähigkeiten, die benötigt werden um die Software fertigzustellen, inklusive aller Qualitätsaspekte und Testing. Die Anzahl der Product Backlog Items, die das Team innerhalb einer Zeiteinheit von z.B. einer Woche fertigstellt, ist dann die Geschwindigkeit des Teams (Velocity). Mit dieser Zahl lassen sich Prognosen anstellen, die auf der bisher gemessenen Geschwindigkeit basieren. So kann der Product Owner bereits frühzeitig kommunizieren, welche Features man bis wann erwarten kann und die Erwartungen richtig setzen.

Einige Teams setzen sich ein "Work in Progress"-Limit und definieren somit, dass z.B. nur fünf Elemente gleichzeitig vom Team bearbeitet werden dürfen. Die Anzahl wird häufig so gewählt, dass es ausreicht das Team kontinuierlich zu beschäftigen, aber eben auch nicht zu viel, sodass das Team einen klaren Fokus behalten kann.

Dabei ist das Team dafür verantwortlich, den Code nachhaltig zu schreiben und sich keine "technische Schuld" aufzuladen. Ziel sollte sein, dass man auch sechs Monate später noch gerne in dem Code arbeitet. Leidet die Codequalität bzw. wurde nicht darauf geachtet erweiterbaren und testbaren Code zu schreiben, wird es immer aufwendiger Änderungen durchzuführen. Die Umsetzung neuer Funktionen dauert dann zunehmend länger und bremst mittelfristig die Geschwindigkeit des Team aus (bis hin zu praktisch Null).

Fazit

Ein für alle sichtbares Product Backlog dient als Spiegel dessen, was das Team vor hat bzw. woran gearbeitet wird. Voraussetzung ist, dass auch wirklich alle Punkte auf dem Product Backlog notiert werden. Es bietet die ideale Grundlage für Diskussionen, da die Reihenfolge für alle Beteiligten transparent erkennbar ist. Es sind aber vor allem auch die Diskussionen, die stattfinden, während Elemente für das Product Backlog geschrieben oder verfeinert werden, die letztlich zu einem Erkenntnisgewinn der Beteiligten führen.

Jede Rolle hat einen klaren Fokus:

Backlog
Durch das Backlog gewinnt das Team an Transparenz (jeder sieht, was gerade getan wird). Durch die klaren Zuständigkeiten kann sich jede beteiligte Person voll und ganz auf ihre Aufgabe konzentrieren.

Siehe auch Moderne Softwareentwicklung 2 - Modernes Anforderungsmanagement und Planung

Stakeholder effizient einbinden

Ein sehr wichtiger Aspekt moderner Software-Entwicklung ist die Einbeziehung von Kundenfeedback in den Entwicklungsprozess. Wobei der Begriff "Kunde" dabei etwas weiter zu fassen ist. Im Englischen wird dafür der Begriff "Stakeholder" benutzt, womit alle Personen bezeichnet werden, die an einem Projekt ein Interesse haben, also neben den klassischen Anwendern eben auch Management, Marketing, Vertrieb etc.

Stakeholder Feedback nutzen

Die Stakeholder kommunizieren ihre Wünsche an den Product Owner (PO), der diese in einem Backlog sammelt, verwaltet und auf Basis des Inputs seiner Stakeholder entscheidet, welche Funktionen als nächstes implementiert werden sollen. Diese Funktionen werden im Entwicklungs-Team umgesetzt und am Ende einer kurzen Iteration als nutzbares Software-Inkrement bereitgestellt. In der Praxis fehlt häufig der nun folgende - entscheidende - Schritt, nämlich dass sich die Stakeholder und der PO mit dem Ergebnis befassen und aufgrund der daraus gewonnenen Erkenntnisse ihre Anforderungen anpassen. Die Stakeholder sollen also nicht - wie in einer Einbahnstraße - ihre Anforderungen nur in diesen Prozess einbringen, sondern sich auch mit dem Ergebnis beschäftigen um zu sehen, wie die Software aktuell aussieht und daraus neue Erkenntnisse zu ziehen.

Aber den Stakeholdern wird es oftmals nicht ganz einfach gemacht, diese Feedback-Schleife zu schließen. Es ist meist nicht ihre primäre Aufgabe, sich um ein Software-Projekt zu kümmern. Sie sind keine Software-Experten und die Entwicklungsteams sehen ihre Aufgabe oft als erledigt an, wenn sie sagen können: "Wir haben die aktuellste Version auf einem Netzlaufwerk abgelegt, man kann sich diese von dort herunterladen und installieren." Mit den Problemen, die dabei entstehen können, wollen Stakeholder sich nicht herumschlagen.

Wichtig ist hierbei, dass Entwicklungsteams die Verantwortung anerkennen, dass sie ihre Stakeholder beim Liefern von Feedback bestmöglich unterstützen müssen. Entwickler haben die Kompetenz und die Werkzeuge, die dabei helfen können und - noch viel wichtiger - die Entwickler sind auf dieses Feedback angewiesen. Stakeholder sollten also nicht als "Störfaktor" gelten, die eh nicht genau wissen, was sie wollen, sondern sie sind ja die Daseinsberechtigung für Software-Entwickler. Denn nur wenn die Stakeholder einen Nutzen durch die Software haben, wird auch Geld für die Entwicklung bereitgestellt. Es liegt also in der Verantwortung der Software-Entwickler, die Kommunikation mit den Stakeholdern zu optimieren und so für optimale Ergebnisse zu sorgen. Durch geeignete Werkzeuge können wir diesen Prozess noch weiter unterstützen.

So bietet z.B. der Team Foundation Server zusammen mit dem Microsoft Feedback Client die Möglichkeit, dass Stakeholder dieses Feedback direkt über eine kleine Anwendung geben können, entweder über Texte mit Screenshots oder eine Video-Aufzeichnung mit Audio. Dieses Feedback kann vom Entwicklungs-Team am Ende einer Iteration eingefordert und verwaltet werden. Es ist beispielsweise jederzeit nachvollziehbar, wie ein entsprechendes Feedback sich in Änderungen der Anforderungen ausgewirkt hat oder welcher Stakeholder noch gar kein Feedback gegeben hat.

Storyboards

Ein weiterer Aspekt für die Kommunikation zwischen dem Entwicklungs-Team und den Stakeholdern ist die Frage, wie Anforderungen und Wünsche von Anwendern effizient formuliert werden können. Neben einer schlanken textlichen Beschreibung z.B. in Form von User Stories inkl. Akzeptanz¬Kriterien nutzen immer mehr Teams auch Storyboards. Diese stellen in vereinfachter und bildhafter Form dar, wie ein Anwender mit der zu implementierenden Funktionalität arbeiten wird, ähnlich zu einem Storyboard zu einem Film. Das Ziel ist dabei, mit einigen einfachen Bildern ein einfaches Verständnis für den Ablauf zu geben.

Storyboard

Diese Form der Dokumentation können Stakeholder und POs nutzen, um ihre Anforderungen klarer zu beschreiben und damit die Chance zu erhöhen, gleich bei der ersten Implementierung ihre Vorstellungen zu treffen. Oder Teams nutzen diese Methode um ihre Realisierungsvision zu dokumentieren und vor der Implementierung mit den Stakeholdern zu verifizieren. Dabei bilden die Storyboards eine wesentlich bessere Diskussionsgrundlage als verbaler oder textueller Informationsaustausch. Und neben der Vermeidung von Missverständnissen bieten Storyboards den Vorteil, dass Diskussionen effizienter, präziser und schneller stattfinden können.

Fazit

Die Kommunikation mit den Stakeholdern ist für Entwicklungs-Teams ein elementarer Schritt zum erfolgreichen Software-Projekt. Dabei müssen Software-Entwickler sich dieser Aufgabe stellen und mit geeigneten Prozessen und Hilfsmitteln diesen Austausch nach Kräften fördern, statt sich "im stillen Kämmerlein zu vergraben".

Beide Methoden zur Optimierung der Kommunikation mit Stakeholder sollen allerdings nicht die direkte Kommunikation ersetzen, sondern diese ergänzen. Jedoch ist gerade bei größeren Projekten mit einer großen Anzahl Stakeholder eine direkte Kommunikation zwischen allen Beteiligten nicht immer in der erforderlichen Intensität möglich. Hier können solche Tools eine sinnvolle Unterstützung bieten.

Siehe auch Moderne Softwareentwicklung 3 - Stakeholder effizient einbinden

Continuous Delivery als zentraler Motor für erfolgreiche Projekte

Auch aus technischer Sicht bringen kürzere Zyklen "frischen Wind" in die Software-Entwicklung, in dem die Zeit zwischen der Programmierung eines Features und der Bereitstellung für Tester und Kunden verkürzt wird. Der Fokus des ganzen Teams liegt also darin, ein Feature fix-und-fertig an den Kunden auszuliefern, anstatt viele verschiedene Dinge gleichzeitig zu starten.

Anstelle erst Tage oder gar Wochen später eine Rückmeldung zu erhalten, dass ein Feature den Test aus irgendwelchen Gründen nicht bestanden hat, erhält man ein zeitnahes Feedback, während die Erinnerung noch frisch ist.

Diese Erkenntnis ist nicht neu: Je später man ein unerwünschtes Verhalten findet, desto aufwändiger wird die Korrektur. Am schönsten wäre es natürlich, schon während des Tippens in Visual Studio darauf hingewiesen zu werden, dass die Zeile Code, die man gerade geschrieben hat, aufgrund von Abhängigkeiten etwas anderes kaputt macht.

Schnelles Feedback bekommt man (in zeitlicher Abfolge) von:

  1. IntellISense
    Schon beim Tippen "ahnt" Visual Studio, dass die Zeile wohl nicht kompilieren wird und hilft beim der richtigen Schreibweise - und wartet nicht bis zur Kompilierung.
  2. Compile & Link
    Der Compiler prüft, dass alle nötigen Abhängigkeiten vorhanden sind und der Code kompiliert. Auch wenn ein Stück Code kompiliert, heißt das noch lange nicht, dass es das tut, was es tun sollte (bzw. was der Entwickler beabsichtigt hatte), deshalb...
  3. Entwickler-Test
    ...schreibt der Entwickler mit Komponententests (Unit Tests) Code um zu prüfen, ob sich der Produktivcode wie gewünscht verhält. Die Unit Tests dienen auch anderen Teammitgliedern als Sicherheitsnetz bei Änderungen am Code und als technische Dokumentation, wie sich der Code verhalten soll.
  4. Check-In
    Durch das Einchecken werden die Änderungen des einzelnen Entwicklers mit den Änderungen des gesamten Teams zusammengeführt. Das birgt immer Potential für Konflikte, sodass man mit diesem Schritt möglichst nicht lange warten sollte.
  5. Continuous Integration (CI)
    Nach dem Einchecken wird der Code vom Builderserver, der dem Team zentral zur Verfügung steht, nochmals in einer sauberen Umgebung gegengeprüft. Dabei wird der Code mindestens kompiliert, häufig laufen danach noch Tests oder weitere Qualitätsanalysewerkzeuge. Man glaubt gar nicht, wie häufig der Fall auftritt, dass es auf einem Entwicklerrechner scheinbar funktioniert, der Buildserver jedoch ein Kompilierfehler meldet - zum Beispiel wegen fehlender Dateien oder Abhängigkeiten.
  6. Integration-Test (Test Lab)
    Um herauszufinden, ob die Software überhaupt startet, kommen Integrations-Tests oder auch UI-Tests zum Einsatz. Diese erfordern eine funktionierende Testumgebung ("Test Lab"), die meistens erst recht aufwendig bereitgestellt und eingerichtet werden muss. Gerade hier lohnt sich die Automatisierung, damit die Ergebnisse zeitnah (z.B. über Nacht) ausgeführt werden und morgens eine E-Mail mit den Testergebnissen vorliegt.
  7. Testen von System-/​Performance-/​Technischen Anforderungen
    Im nächsten Schritt ließen sich auf der Testumgebung auch technische Tests ausführen, die jeweils das Gesamtsystem bzw. bestimmte nicht-funktionale Aspekte wie Sicherheit, Performance, Verhalten unter Last oder besondere Situationen testen.
  8. User Acceptance Testing
    Sind alle automatischen Tests durchlaufen, folgt das manuelle Testen. Neben dem Prüfen von Teilen, die sich nur schwer automatisieren lassen (oder noch nicht automatisiert wurden) liegt der Schwerpunkt hier auf der Erfüllung der Anforderungen. Die Leitfrage lautet, ob die Anforderung aus Sicht des Kunden erfüllt und umgesetzt wurde.
  9. Operational Acceptance Testing (Production)
    Egal, wie viel man testet und wie ähnlich die eigenen Testumgebungen an der Produktionsumgebung angelehnt sind, es wird wohl immer Probleme geben, die erst auf der Zielumgebung auffallen. Dazu gehören auch Kennzahlen, die man verwenden kann, um das System zu überwachen und zu bemerken, wenn es sich nach einem Update anders verhält (also z.B. dass man seit dem letzten Update nur halb so viele Artikel pro Stunde verkauft). Gerade, wenn man sehr kurze Zyklen verwendet, wie es einige Webseiten tun, sollte man hier einen "Plan B" haben, wie man im Fehlerfall vorgeht.Und natürlich sollte man daraus lernen und ggf. die Tests erweitern, um ähnliche Fehler früher zu bemerken.

Wann ist ein Feature eigentlich fertig?

Kunden finden kürzere Zyklen naturgemäß eher gut, geht das doch häufig mit einer kürzeren Wartezeit bis zum neuen Feature einher. Letztlich ist ein Feature erst dann fertig, wenn es fertig entwickelt, getestet und ausgeliefert wurde und es der Kunde sinnvoll bei sich nutzen kann.

Wenn man die Zeit stoppt zwischen dem Eingang einer Idee bis hin zu dem Moment, an dem das Feature vom Kunden angenommen ist, so erhält man die Durchlaufzeit (Cycle Time). Bei Fehlerberichten wird dies als mittlere Zeit bis zur Wiederherstellung (Mean Time to Repair; MTTR) bezeichnet. Je mehr von der oben stehenden Liste automatisiert wurde, desto kürzer werden hier die Zeiten ausfallen.

Aus Entwicklersicht sollte man im Team das Wort "fertig" erst einmal definieren. Was bedeutet "fertig" für uns? Ist das inklusive Tests (auf jeden Fall!)? Mit Dokumentation? Sind Compilerwarnungen erlaubt oder ist man dann nicht "fertig"? Nur, wenn man eine explizite Definition von "fertig" bzw. "done" vorliegt, ist jedem klar, was alles zu tun ist (und was nicht). Die "Definition of Done" enthält die Mindestanforderungen, die ein Feature erfüllen muss, um als "fertig" bezeichnet zu werden - und sichert das Team auch dagegen ab, dass Dinge nach hinten geschoben oder gar übersprungen werden (denn dann wäre es nicht "fertig").

Also am besten gleich nach dem Urlaub mit dem Team zusammensetzen und eine "Definition of Done" erstellen und schriftlich festhalten.

Feature
Abbildung: Viele Schritte liegen zwischen dem Einchecken des Entwicklers und bis zum Eintreffen des neuen Features beim Kunden. Diese Zeitspanne zu verkürzen ist ein zentrales Anliegen.

Fazit

Kurze Zyklen sind möglich, erfordern aber ein hohes Maß an Automatisierung, eine funktionierende kontinuierliche Integration und Bereitstellung und eine klare Definition im Team, was eigentlich "fertig" bedeutet.

Siehe auch Moderne Softwareentwicklung 4 - Continuous Delivery als zentraler Motor für erfolgreiche Projekte

Optimierte Qualitätssicherung für moderne Prozesse

Modernes Testen

Software-Entwicklungsteams stehen heute vor der Herausforderung, dass in immer kürzeren Zyklen Software geliefert werden soll. Gleichzeitig werden die Systeme immer komplexer und der Qualitätsanspruch der Anwender steigt. Diese Situation macht Veränderungen in Bezug auf die Qualitätssicherung erforderlich, die sich in 3 Bereiche unterteilen lassen:

  1. Das Mindset, also die Einstellung von Software-Entwicklern zu Qualität.
  2. Die Team-Organisation verbunden mit der Frage: "Wer testet wann?".
  3. Und die Testpraktiken, also "Wie können wir das Testen effizient gestalten?".

Team-Organisation

Aktuell haben viele Unternehmen eine klare Trennung zwischen Entwicklungs- und Qualitätssicherungsteams bzw. -Abteilungen. Entwickler erstellen Code, übergeben diesen an die Tester und beheben anschließend Fehler, die der Tester findet. Jedoch bietet dieses Vorgehen eine Reihe von Nachteilen wie beispielsweise hohe Transaktionskosten (Kosten für die Kommunikation zwischen Tester und Entwickler) oder das Risiko, dass bestimmte Probleme unentdeckt bleiben, weil der Tester nicht das erforderliche Wissen über die Anwendung hat.

Mindset

Idealerweise berücksichtigen Entwickler die Qualitätsansprüche bereits beim Implementieren des Codes. Und am effizientesten erreicht man dieses Ziel dadurch, dass es keine Tester mehr gibt. Ja, so radikal und unglaublich sich das anhört, das Entfernen von Testern aus Software-Projekten erhöht die Qualität - sofern diese Maßnahme durch eine Qualifizierung der Entwickler in Bezug auf modernes Testen begleitet wird.

Dem entgegen steht die Theorie, dass ein Entwickler nie seinen eigenen Code testen soll. Während diese Aussage sicherlich in einigen Aspekten zutrifft (z.B, Vorteile des 4-Augen-Prinzips), so dient sie Entwicklern oft als Rechtfertigung oder Ausrede, Tests nichts selbst ausführen zu müssen. Grund ist, dass Entwickler nicht gerne testen und somit auch keine hohe Motivation haben, ihre Fertigkeiten in diesem Bereich zu verbessern.

Test-Praktiken

Jedoch haben Entwickler oftmals viel bessere Möglichkeiten, Tests effizient zu gestalten, gerade in Bezug auf Test-Automatisierung. Und letztendlich werden Entwickler auch anderen, besseren Code schreiben, wenn sie wissen, dass sie selbst die Tests dafür ausführen müssen. Einige Konzepte wie z.B. Unit-Tests oder TDD (Test Driven Development) lassen sich nicht sinnvoll umsetzen, wenn die Implementierungs- und Testaufgaben auf 2 Personen aufgeteilt sind, die unabhängig voneinander, möglicherweise in getrennten Teams arbeiten. Und auch wenn in einigen Teams Software-Entwicklung ohne dedizierte Tester nicht realisierbar erscheint, sollte dennoch versucht werden, diesem Ideal möglichst nahe zu kommen und möglichst viel der Verantwortung für die Qualität der Anwendung bereits beim Schreiben des Codes durch die Entwickler übernehmen zu lassen. Die Qualität wird also quasi in das Produkt eingebaut. Die nachgelagerten Tester sind nur noch ein Sicherheitsnetz. Sie sollten aber eigentlich keine Fehler mehr finden. Und um Transaktionskosten in diesem Szenario zu minimieren, sollten Tester auf jeden Fall Teil des Entwicklungs-Teams sein, idealerweise mit den Entwicklern in einem Raum sitzen und nicht organisatorisch getrennt sein.

Als nächsten Schritt, vor allem in Bezug auf kürzere Iterations-Zyklen, spielt die Testautomatisierung eine wichtige Rolle. Nur damit werden Teams es schaffen, in Zyklen von wenigen Tagen oder Wochen jeweils am Ende einer Iteration qualitativ hochwertige Software bereitstellen zu können. Die Testautomatisierung beginnt mit dem Schreiben von Unit-Tests. Unit-Tests gehören heute zum absoluten Muss, was Software-Entwicklung anbelangt. Und wenn es richtig gemacht wird, müssen Entwicklungsteams für das Schreiben der Unit-Tests keine zusätzliche Zeit aufwenden, da viele andere Dinge dadurch effizienter gestaltet werden können. Die effiziente Erstellung von Unit-Tests setzt allerding eine geeignete Architektur voraus - eine Voraussetzung, an der Teams mit einer großen Basis an Legacy-Code häufig scheitern.

Über Unit-Tests hinaus bieten moderne Test-Tools auch die Möglichkeit, über Integrations-Tests das Gesamtsystem effizient zu testen. So können über Virtualisierung Testumgebungen bereitgestellt werden, in denen automatische UI-Tests in möglichst realistischen Szenarien die Anwendung prüfen und so das Risiko der Übernahme von Fehlern nach dem Deployment in die Produktivumgebung reduziert. Last- und Performance-Tests helfen, böse Überraschungen bezüglich des Laufzeitverhaltens im Produktivbetrieb zu verhindern, indem diese Probleme bereits früh im Entwicklungsprozess erkannt und beseitigt werden.

Während automatisierte Tests die Möglichkeit bieten, sehr häufig ausgeführt zu werden um Abweichungen früh zu erkennen, haben manuelle Tests nach wie vor eine wichtige Funktion. So bieten "explorative" Tests den Vorteil, dass nicht nur vordefinierte Szenarien geprüft werden, sondern die Anwendung allgemein auf unerwartetes Verhalten geprüft wird.

Fazit

Bei der Entwicklung von Software in immer kürzeren Zyklen brauchen wir neue Methoden zur Qualitätssicherung. Dabei müssen Entwickler bereits bei der initialen Implementierung mehr Verantwortung übernehmen und die dazu erforderlichen Praktiken erlernen und anwenden. Der Lohn dafür ist eine neue Sicherheit und ein Ende des "Gezerres" zwischen Entwicklung und Qualitätssicherung vor allem am Ende eines Releases.

Siehe auch Moderne Softwareentwicklung 5 - Optimierte Qualitätssicherung für moderne Prozesse

Erweiterbare und wartbare Architekturen entwickeln

Klassische Architektur liefert meistens spezialisierte Lösungen für konkrete Probleme oder Anforderungen. Deshalb ist der klassische Wasserfall-Prozess auch so aufgebaut, dass zunächst alle Anforderungen bekannt sein müssen, um dann die ideale Architektur zu entwerfen. Das bedeutet aber auch, wenn sich die Anforderungen ändern, kann es vorkommen, dass das Architekturkonzept nicht mehr passt.

Im Gegensatz dazu funktioniert moderne Architektur mehr mit allgemeinen Patterns, die sich auf verschiedene Projekte und Situationen anwenden lassen. Diese Patterns muss jeder Entwickler beherrschen, da er sie in seiner täglichen Entwicklungsarbeit anwenden muss; d.h. Architektur manifestiert sich in diesem Zusammenhang sehr stark direkt in der Code-Ebene. Zusätzliche Aspekte von Architektur betreffen Technologien und Modelle.

Code, Technologien, Modelle

Die Code-Ebene bezieht sich auf Strukturen im Code und bietet Lösungspatterns für Fragen wie z.B.

Bei der Technologie-Ebene gibt es in Bezug auf die Architektur zwei Aspekte. So ermöglichen Technologien auf der einen Seite gewisse Architektur-Patterns erst. Beispiele dafür sind WPF, wodurch das MVVM-Pattern erst richtig elegant umsetzbar wurde, oder WCF und Webservices, die serviceorientierte Architekturen zum Durchbruch verholfen haben. Auf der anderen Seite muss Architektur es auch ermöglichen, Technologien auf enge Bereiche des Codes zu beschränken, sodass beim Wechseln einer Technologie die notwenigen Anpassungen auf diesen Bereich begrenzt werden können.

Modelle stellen die Visualisierung von Architektur dar. Dies ist wohl die heute gängigste Assoziation mit dem Begriff Architektur. Beim klassischen Ansatz werden Modelle genutzt, damit ein Spezialist (der Software-Architekt) seine Konzepte und Ideen an die Entwickler kommunizieren kann, die diese in Code umsetzen sollen. Moderne Teams kommen jedoch ohne klassischen Architekten aus, da das Team gemeinsam Verantwortung für die Architektur übernimmt und jeder im Team aktiv an deren Gestaltung mitwirkt. Gerade hier erfüllen Modelle einen wichtigen Aspekt, nämlich die Visualisierung von Strukturen und die Reduktion von Code auf verschiedene Abstraktionsebenen. Dies erlaubt eine wesentlich effizientere Kommunikation im Team über Architektur.

Der klassische Architekt wird durch diese Veränderung jedoch nicht arbeitslos, sondern er übernimmt eine neue wichtige Aufgabe. Er übernimmt die Aufgabe eines Coaches für die Entwickler und sorgt dafür, dass die Entwickler die notwendigen Patterns kennen und korrekt anwenden können. Und er entdeckt und entwickelt neue Patterns, da es hier ja auch kontinuierliche Verbesserungen und Weiterentwicklungen gibt und transferiert dieses neue Wissen nach einer Evaluierung an das Team weiter.

Moderne Architektur muss drei wichtige Aspekte erfüllen:

Wartbar, Testbar, Erweiterbar

Die Testbarkeit ermöglicht es uns, dass wir effizient Unit-Tests mit klaren und atomaren Testzielen erstellen können. Dazu hilft z.B. auch Entkopplung, die es uns u.a. ermöglicht, bestimmte Teile unserer Anwendung durch sog. Mockups zu ersetzen, welche diesen Teil simulieren (z.B. den Zugriff auf eine Datenbank), ohne für die Testausführung eine Datenbank mit entsprechenden Test-Daten bereitstellen zu müssen.

Wartbarkeit beschreibt das Ziel, Veränderungen an der Anwendung schnell und vor allem ohne das Risiko, andere Bereiche zu beeinträchtigen, durchführen zu können. Die Wartbarkeit erlaubt es z.B. auch, dass Fehler durch alle Entwickler im Team behoben werden können, unabhängig davon, wer den Code ursprünglich geschrieben hat. Wartbarkeit beschleunigt auch die Fehlersuche und ermöglicht es, die notwendigen Änderungen möglichst lokal zu begrenzen.

Durch Erweiterbarkeit bekommen wir die Möglichkeit, neue Funktionen schnell und effizient zu unserer Anwendung hinzuzufügen. In jeder Anwendung steigt der Aufwand, neue Funktionalität einzubauen mit der Gesamtmenge an Code an. Diesen Anstieg möglichst gering zu halten ist das primäre Ziel von Erweiterbarkeit.

Alle diese Aspekte stellen eine Voraussetzung für ein effizientes Build-Mesure-Learn dar. Testbarkeit ermöglicht das Liefern qualitativ hochwertigen Codes in kurzen Zyklen, Wartbarkeit ermöglicht schnelle Anpassung bestehender Funktionalität und Erweiterbarkeit erlaubt es, Anwenderwünsche, die aus unserem Learn-Schritt entstehen, schnell und effizient umzusetzen.

Fazit

Während der Erfolg der Bemühungen in Bezug auf Wartbarkeit und Erweiterbarkeit sich nur mittel- bis langfristig messen lässt, bietet die Testbarkeit den Vorteil, dass sie sofort überprüfbar ist - schon in dem Moment, in dem ich Tests dafür schreibe. Schön ist an dieser Stelle nun, dass dieselben Patterns, die die Testbarkeit verbessern auch zu einer Verbesserung der Erweiterbarkeit und Wartbarkeit führen. Wir haben hier also nicht nur kein Problem mit konkurrierenden Patterns, sondern können über die Testbarkeit die Einhaltung dieser Patterns auch sehr kurzfristig überprüfen.

Siehe auch Moderne Softwareentwicklung 6 - Erweiterbare und wartbare Architekturen im Team entwickeln

Weiterführende Literatur:

Weiterführende Trainings:

  1. Professional Scrum Developer (eine Initiative von Microsoft und scrum.org)
Thomas Schissler

Mehr zum Thema