Follow my new blog

Donnerstag, 31. März 2011

Gläserne Decke für die Agilität – Abhängigkeiten

Agile Softwareentwicklung weist den richtigen Weg zu besserer Software. Die Softwareentwicklung muss alles tun, um so dicht wie möglich an den diffusen und wechselnden Bedürfnissen der Kunden zu sein. Also mehr Dialog als fixierte Kontrakte. Mehr den Menschen im Blick als starre Tools. Mehr Offenheit für Veränderungen als Plantreue.

Dazu muss natürlich das Vorgehen einer Entwicklergruppe passen. Scrum oder XP machen angesehene Vorschläge dazu.

Trotzdem kommt es mir so vor, dass die versprochenen Vorteile sich nicht so schnell manifestieren, wie erhofft. Liegt das immer wieder daran, dass Scrum oder XP nicht gut genug implementiert werden? Ja, sicher kommt das immer wieder vor. Das scheint mir jedoch keine vollständige Erklärung. Ich glaue, selbst wenn ein Team Scrum perfekt einführte, würde es deshalb allein noch nicht wirklich agil werden.

Der Weg zu besserer Software scheint klar. Man muss nur die Vorgehensmodellleiter hochsteigen. Doch dann stößt man – ob man es merkt oder nicht – an gläserne Decken. Die Verbesserungen geraten vorzeitig ins Stocken – der Grund ist allerdings nicht recht auszumachen. Alle Vorgehensmodell-Rituale werden doch eingehalten… Was läuft denn noch falsch?

Ich glaube, eine solche gläserne Decke besteht in einem fundamentalen Widerspruch zwischen zwei Gedankenmodellen von Software.

Das heutige technische Gedankenmodell

Die Softwareentwicklung hat in weiten Teilen ein technisches Gedankenmodell. Im Kern dieses Modells stehen abhängige Funktionseinheiten. Verständlich ist das durchaus, wenn man die Softwareentwicklung als Enkel des Maschinenbaus und Kind der Elektrotechnik sieht. Denn Maschinen und Geräte jeder Art funktionieren nur, wenn ihre Teile komplett sind. Das heißt, die müssen in geeigneter Weise bottom-up hergestellt und integriert werden.

Ein Computer ist ohne Netzteil, Bildschirm, Hauptplatine, Prozessor, Speicher, Tastatur nichts. Man kann keinen aus einem halben Netzteil, einem Viertel Prozessor, einem Drittel Speicher usw. zusammensetzen. Alles steht in einer Abhängigkeitsbeziehung, die zumindest eine Integrationsreihenfolge diktiert. Und alles, was da integriert wird, das muss vollständig sein.

image

Ohne Display kein vollständiges Gehäuse, ohne Prozessor keine vollständie Hauptplatine usw. Was weiter oben steht, also höher integriert ist, das ist abhängig von dem, was weiter unten steht.

Hört sich das plausibel an? Dann finde ich plausibel, dass das reflexartig genannte Pattern für die Struktur von Software genauso aussieht:

image

Wenn man Entwickler nach der einer Soll-Architektur fragt, dann kommt in 9 von 10 Fällen “Schichtenarchitektur” als Antwort. Wenn man in Projekten nach der Architektur fragt, dann kommt auch in 9 von 10 Fällen der Begriff “Schichtenarchitektur” – wenn auch meist mit Einschränkungen wie “Wir haben es nicht geschafft, eine saubere Schichtenarchitektur hinzukriegen. Aber das war unser Ziel.” Gefolgt von einem Augenaufschlag, der eigentlich nur eine Reaktion verträgt: Kopfstreicheln. Denn ist eine Strukturierung nach Schichtenmodell - das gern differenzierter als obigens aussehen darf - nicht das Ziel schlechthin, für eine Softwarearchitektur?

Nein, das sehe ich nicht so. Das pauschale Schichtenmodell hat eher mehr kaputt gemacht als Gutes bewirkt. Sein größter Schaden mag dabei gar nicht mal technischer Natur sein, sondern mentaler. Das Schichtenmodell hat offenes, flexibles Denken in Richtung besserer Architekturen gelähmt. Bei vielen Entwicklern.

Aber das ist hier gar nicht mein Punkt. Heute geht es mir um das fundamentale Denken in Abhängigkeiten und deshalb in Schichten. Die “Abhängigkeitsdenke” ist überall. Hier die Diagrammtypen, die der Beitrag zur UML bei Wikipedia zuerst nennt:

image

Insgesamt werden 12 Diagrammtypen beschrieben, wovon mindestens 7 (58%) Abhängigkeitsdiagramme sind. (Und eigentlich würde ich sogar noch das Sequenzdiagramm mit in diese Gruppe rechnen. Dann wären es 66%.) [1]

Solch technische Sicht ist für sich genommen natürlich kein Problem. Maschinenbau und Elektrotechnik leben damit ja wunderbar – und können eigentlich auch nicht anders. Auch Softwareentwicklung kann man natürlich ausgerichtet an diesem Gedankenmodell betreiben. Das tun ja auch Millionen von Entwicklern täglich.

So weit, so gut also erstmal.

Das agile Gedankenmodell

Agilität interessiert sich erstmal nicht für Technik. Technik ist nur ein Mittel, um für den Kunden eine Lösung herzustellen. Aus Sich der Agilität zählt also nicht, wie Software intern strukturiert ist. Sie hat deshalb ein ganz anderes Gedankenmodell von ihr.

Für die Agilisten besteht Software nicht aus Schichten von abhängigen Funktionseinheiten. Stattdessen denken sie in Scheiben, in Durchstichen, in Längsschnitten durch Software.

image

Agile Softwareentwicklung orientiert sich konsequent am Nutzen für den Anwender. Der mag klein sein, eine dünne Scheibe vom großen Ganzen, aber nur er zählt.

Solche Nutzenscheiben (Features) können zwar auch abhängig von einander sein insofern, dass z.B. Monatsberichte bei einer Faktura-Anwendung keinen rechten Sinn machen, wenn nicht zumindest Rechnungen vorhanden sind. Doch das ist keine technische Abhängigkeit, sondern nur eine inhaltliche. Das Monatsberichte-Feature könnte mithin technisch hergestellt werden und sogar zum Einsatz kommen, selbst wenn es noch keine Rechnungserfassung gibt, sondern die Rechnungsdaten aus einem Altsystem importiert werden. Abhängigkeiten zwischen Features sind vergleichsweise lose.

Widerstreit

Das scheint mir nun ein fundamentales, wenn auch subtiles Problem: der Widerstreit der Gedankenmodelle, von denen eines die Software in Schichten gegliedert sieht und das andere sie in Scheiben gegliedert denkt.

image

Diese um 90° gegeneinander gedrehten Vorstellungen von Software müssen von der Programmierung immer wieder überein gebracht werden. Das Vorgehensmodell “denkt” in Scheiben, die Programmierung “denkt” in Schichten.

Klar, irgendwie geht diese Transformation. Jeden Tag bekommen Entwicklergruppen das hin. Aber ist das einfach? Ist das so einfach, wie es sein sollte oder könnte?

Nein, ich glaube, dieser Widerstreit zehrt an der Kraft der Softwareentwicklung. Er führt zu Konflikten zwischen Entwicklern und zwischen Entwicklern und Kunde. Auf die eine oder andere Weise.

Wenn Denkmodelle ganz anders sind, dann braucht es immer wieder Übersetzungsaufwand. Das zeigen Jahrtausende Menschheitsgeschichte. Und jedes Softwareprojekt weiß das aus eigener Anschauung. Denn das Denkmodell des Kunden in Bezug auf seine Fachdomäne trifft ja dort ständig auf das Denkmodell der Entwickler in ihrer technischen Domäne. Bis Entwickler wirklich verstehen, was Kunden wollen, kann viel Zeit vergehen und können viele Tränen fließen.

Warum sollte das anders sein, wenn zwei so unterschiedliche Gedankenmodell in Bezug auf die Herstellung von Software aufeinander treffen? Ist da Verständnis, Harmonie, Einfachheit zu erwarten? Kaum.

Ziel: Kohärenz

Ich glaube, dass Softwareentwicklung mit Agilität solange an eine gläserne Decke stößt, bis sie aufhört, in Schichten und Abhängigkeiten zu denken. Erst wenn ihr primäres Gedankenmodell, d.h. ihre technische Sicht der entspricht, die ein agiler Prozess hat, in dem sie Code produziert, kann sie das nächste Level erreichen. [2]

Kohärenz zwischen agilem und technischem Gedankenmodell ist unabdingbar für eine flüssige Umsetzung von Anforderungen in Code.

Die Frage ist nun, wie kann ein technisches Gedankenmodell aussehen, das Software nicht mehr aus Schichten und Abhängigkeitsbeziehungen aufgebaut sieht, sondern sie ganz natürlich als bestehend aus Scheiben denkt?

Anmerkungen

[1] In der UML mögen “nur” 58% der Diagramme Abhängigkeitsdiagramme sein. Deren Anteil am Entwicklerleben ist aber sicherlich deutlich höher. Ich schätze, dass 80-90% aller Diagramme, die gezeichnet werden von Entwicklern, Abhängigkeitsdiagramme der einen oder anderen Form sind (egal, ob sie strikt der UML folgen oder nicht).

[2] Anders herum hat es übrigens nicht funktioniert. Jahrzehntelang hatte die Softwareentwicklung versucht, die Kunden mit rein technischer Vorgehensweise zu befriedigen. Das Ergebnis kennen wir alle. Software “von unten nach oben” zu bauen, macht niemanden glücklich. Erst das Framework, erst die Infrastruktur, dann die Logik, dann das GUI… Nein, so geht es nicht.

Agile Softwareentwicklung ist das Resultat dieses Irrweges. Sie hat der technischen Sicht eine Kundensicht entgegengestellt, die um 90° gedreht ist. Dadurch ist ein Spannungsfeld entstanden – dem sich früher oder später die Softwareentwicklung eigentlich nur ergeben kann, um effektiver und effizienter zu werden. Mit einem technischen Denkmodell, das immer nur dagegen hält, wird schlicht zuviel Kraft verschwendet.

Dienstag, 29. März 2011

Lernkartei I – Das Szenario

Flow-Design verspricht evolvierbare Software. Wenn ich ein Flow-Design Diagramm zeichne, ist das allerdings noch nicht nachzuvollziehen. So ein Diagramm mag verständlicher sein als andere Diagramme, doch warum sollte Software deshalb evolvierbarer sein?

Um die Evolvierbarkeit von Flow-Designs zu zeigen, ist mehr als ein Diagramm nötig. Nur eine Reihe von Diagramme, die zeigt, wie sich eine Software weiterentwickeln lässt, kann das Versprechen Evolvierbarkeit transportieren.

Deshalb habe ich mich entschlossen hier im Blog eine Software in kleinen Schritten zu entwickeln, zu evolvieren. Ich tue das live, d.h. ohne vorherige Planung. Ich sitze also nicht erst stundenlang, probiere herum und dokumentiere dann nur das wirklich funktionierende Endergebnis. Hier will ich vielmehr simulieren, was in größeren Projekten an der Tagesordnung ist: Unsicherheit.

Welche Features sollen wirklich in die Software rein? Welche Technologien sind die besten für den Zweck? Welcher Ansatz verspricht am meisten Erfolg? Wohin wird sich die Software entwickeln? Diese und andere Fragen treiben die Softwareentwicklung ständig um; damit will auch ich leben. Deshalb mache ich mir zunächst gar keine großen Gedanken über die Anforderungen; so ist garantiert, dass ich mich selbst mit Änderungswünschen überrasche.

Einen Ausgangspunkt muss das Ganze aber natürlich haben. Hier mein grober Wunsch, was ist haben möchte:

Auftrag Lernkartei

Ich möchte ein Lernkartei-Programm entwickeln. Mit dem kann ich dann zum Beispiel Vokabeln lernen. Der Lernstoff steht auf Karteikarten in Form von Fragen und Antworten. Auf der einen Seite jeder Karte die Frage, auf der anderen Seite die zugehörige Antwort.

Mehrere solcher Lernkarteikarten sind zusammengefasst zu einer Lernkartei, z.B. Karteikarten mit Französich-Vokabeln.

Der Trick bei einer Lernkartei ist nun, dass man ihre Karten nicht einfach von oben nach unten lernt, so wie sie auf dem Karteikartenstapel der Lernkartei liegen. Die Karten werden vielmehr in einen Kasten gesteckt, der mehrere Fächer hat.

image
Quelle: http://lernkartei.de/prinzip.php

Das Vorgehen beim Lernen ist einfach:

  • Neue Karten kommen ins erste Fach.
  • Sich abfragen kann man mit Karten in jedem Fach. Wird die Antwort gewusst, kommt die Karte ins nächste Fach; bei falscher Antwort wandert sie jedoch zurück in Fach 1.
  • Die Fächer haben unterschiedliche Kapazität. Deshalb kommen die Karten immer seltener dran, je weiter sie in den Fächern gewandert sind. Anfangen sollte man immer mit den Karten im ersten Fach. Die weiteren Fächer kommen dran, wenn sie voll sind.

Nicht alle Fächer sind also gleich. Das erste hat eine gewisse Sonderstellung, weil dorthin alle nicht gewussten Karten zurückwandern. Es füllt sich also am schnellsten mit neuen Karten und nicht gewussten.

Dazu kommen noch zwei weitere Fächer, die ich mal Halde und Archiv nenne. Die Halde sind enthält alle Karteikarten, die noch nicht in Fach 1 waren. Wer nicht kontinuierlich Karten anlegt und gleich in Fach 1 steckt, sondern eine fertige Lernkartei nutzen will, der fängt mit einer großen Halde an, von der dann einige Karteikarten in Fach 1 gesteckt werden.

Das Archiv bilden andererseits alle Karten, die aus dem letzten Fach als gewusst entnommen werden.

Bei einem Karteikasten mit n Fächern (1..n) hat die Halde die Fachnummer 0 und das Archiv die Nummer n+1.

Die Lernkarteien soll das Programm aus Textdateien laden. Ich stelle mir ein sehr einfaches Format vor:

Frage 1
Antwort 1

Frage 2
Antwort 2

Frage 3
Antwort 3

Fragen und Antworten stehen auf je einer Zeile und werden als Paare durch Leerzeilen getrennt.

Dieses Format nutzt ein Lernkarteiprogramm, das mir auf dem iPad ganz gut gefallen hat: iMemento Lernkarten. Ich möchte, dass meine Lernkartei-Dateien mit seinen kompatibel sind.

image

Die beiden Screenshots von iMemento zeigen, wie ich mir mein Programm auch ungefähr vorstelle. Es gibt ein Fenster mit einer Übersicht aller Lernkarteien und ein Fenster für das Lernen mit einer Lernkartei.

Das Programm soll zunächst mal auf dem Desktop als WPF-Anwendung laufen. Später könnte es umgestellt werden auf Silverlight oder MonoTouch oder sogar auf ASP.NET. Mal sehen…

Los geht´s…

Ich finde, das ist ein überschaubares, aber kein triviales Szenario. Es bietet mir (und vielleicht Ihnen auch) Nutzen, die Entwicklung lohnt sich also. Zu lernen gibt es immer etwas. Ein Lernkartei-Programm kann man immer mal zur Hand haben.

Zu diesem Szenario könnte ich nun natürlich viele Fragen stellen. Aber ich tue das bewusst nicht, sondern werfe mich im nächsten Artikel der Serie einfach in die Entwicklung. So will ich die in größeren Projekten quasi immer herrschende Unterspezifikation simulieren. Die übt ja einen nicht geringen Druck auf die Evolvierbarkeit aus.

WPF ist auch eine Herausforderung für mich. Mit der Technologie habe ich nicht viel Erfahrung. Allerdings treibt mit ein Ideal an: Ich möchte mit WPF eine strikte Trennung von GUI und dem Rest leben.

Wenn Sie mögen, grübeln Sie mit. Wie würden Sie dieses Szenario angehen?

Im nächsten Artikel mache ich den ersten kleinen Schritt in der Implementation. Jeder Artikel soll einen kleinen Anwendernutzen produzieren. Es gibt keine lange Planung oder Infrastrukturbastelei. Ran, rauf, rüber – aber mit Methode.

Flow im Unternehmen – Teil 3 – Engpass Programmierung

Wenn die Softwareproduktion insgesamt besser werden soll, dann muss am Engpass angegriffen werden. Das ist die Programmierung, die Anforderungen in Release Candidates transformiert.

Ober genauer formuliert: Auf einer bestimmten Detaillierungsstufe ist die Programmierung der Engpass. Tritt man weiter zurück, dann ist es die gesamte Softwareentwicklung bestehend aus Programmierung und Qualitätssicherung. Und tritt man näher heran, dann wird sich der Engpass sicher noch präzisieren lassen.

Wie sieht also die Programmierung im Detail aus? Welche Schritte sind nötig, um aus Anforderungen Release Candidate Code zu machen? Ich denke mir das so:

image

Softwareentwicklung ist offensichtlich mehr als “code slinging”. Code entsteht nicht einfach so, sondern sollte das Ergebnis eines systematischen Vorgehens sein. Dazu gehören die Schritte:

  1. Anforderungsanalyse: Definierte Anforderungen müssen von der Programmierung verstanden werden, bevor sie sie umsetzt. Die Anforderungsdefinition ist dafür nicht zuständig; sie formuliert nur Wünsche der Marktes in einer Weise, dass die Programmierung überhaupt einen Ansatzpunkt hat. Erst in der Anforderungsanalyse machen sich dann die Entwickler die Anforderungen zu eigen.

    Anforderungsdefinition und Anforderungsanalyse bilden den Übergang von Außenwelt (Kunden-/Anwendersicht) zu Innenwelt (Entwicklersicht). Den in zwei Schritte mit unterschiedlichem Schwerpunkt zu splitten, halte ich für notwendig, um Anforderungen in top Qualität zu bekommen. Denn sonst wird der ultimative Engpass nicht optimal genutzt.
  2. Sind die Anforderungen verstanden, muss die Implementierung geplant werden. Von Anforderungen “in den Code zu springen”, ist kein geeignetes Vorgehen. Es führt zu mittelfristig schlechter Qualität der Codebasis und nutzt die ultimativ knappe Ressource nicht optimal.
    1. Den Anfang der Planung macht der Architekturentwurf. Er definiert die Grobstruktur des Codes (und der Daten) in Bezug auf die nicht-funktionalen Anforderungen. Hier werden auch die wesentlichen Technologieentscheidungen getroffen.
    2. Im Rahmen des Architekturentwurfs entwirft der nächste Schritt ein Modell des Codes zur Erfüllung der funktionalen Anforderungen. Das Team definiert die nötigen Funktionseinheiten in einer codeunabhängigen Form, um sich nicht in Details zu verlieren. Hier ist auch nochmal Gelegenheit, Technologieentscheidungen zu treffen.
    3. Sind Architektur und Modell für eine Menge an Anforderungen entworfen, ist die Arbeit zu ihrer Umsetzung zu organisieren. Dass alle Teammitglieder optimal im Sinne des Ganzen eingesetzt werden, ergibt sich nicht von selbst. Die Arbeitsorganisation ist mithin die abschließende Maßnahme, um den Engpass mit Input in höchster Qualität zu versorgen.
  3. Schließlich folgt die Implementierung der mit Architektur und Modell formalisierten Anforderungen. Hier liegt der wahre Engpass der Softwareentwicklung, denn hier werden die ursprünglichen Wünsche in Code fixiert. Das kostet im Verhältnis zu den anderen Schritten am meisten Entwicklerkapazität pro Wunsch, weil dieser Schritt das abstrakteste Resultat produziert und höchster technologischer Kompetenz bedarf. Jeder Entwickler ist bei der Implementierung auch auf sich allein gestellt; das Fehler-/Fehlentscheidungspotenzial ist hier in verschiedener Hinsicht am größten.
  4. Zur Qualitätssicherung der Implementierung folgt ihr ein Review. Denn wie auf höherer Ebene klar geworden ist, muss die Softwareentwicklung bzw. die Programmierung als Engpass top Qualität liefern, um nicht durch vermeidbare Nachbesserungen belastet zu werden.

Wenn insbesondere die Prozessdetaillierung für Sie wie ein Wasserfall aussieht, dann verstehe ich das. Aber es wäre ein Missverständnis, bei Anblick eines Flows zu denken, dass am Anfang nur ein Input hineinginge, der dann in einem Durchfluss zu einem Komplettergebnis führen würde.

Der Produktionsprozess macht vielmehr keine Aussage darüber, wie oft er durchlaufen wird und wie groß insbesondere der ursprüngliche Input-Happen ist. Die für die Agilität zentrale Schleife des iterativen Vorgehens ist vielmehr in diesem Prozess von Anfang an enthalten: der Markt bzw. der Kunde steht am Beginn und am Ende des Prozesses.

image

Wasserfall und agiles Vorgehen (oder auch nur iterative Entwicklung, die es ja schon in den 1980ern gab) unterscheiden sich mithin eigentlich nur in der Zahl der Durchläufe durch den Prozess. Und die hängen davon ab, wie groß die Wünsche am Anfang und wie zahlreich die Release am Ende sind.

  • Wasserfall: 1 Wunsch und wenige Releases
  • Agilität: Viele Wünsche und viele Releases

Geschachtelte Engpässe

Ich habe es schon angedeutet: Einen Engpass gibt es in Bezug auf die Abstraktionsebene eines Prozesses. Wenn der Produktionsprozess nun schrittweise verfeinert verschiedene Abstraktionsebenen hat, dann gibt es sozusagen mehrere Engpässe – die allerdings ineinander stecken.

image

Wer die Softwareentwicklung nun verbessern will, der muss zweierlei tun:

  1. Die Engpässe auf allen Ebenen ausreizen, d.h. die Implementierung von allem befreien, was nicht zu ihrer Kernaufgabe gehört: Code für neue Wünsche produzieren, die Implementierung topfit machen in puncto Codegenerierung, die Implementierung Code von top Qualität herstellen lassen. Und dann die Programmierung als umfassenden Produktionsschritt ausreizen. Und dann die Softwareentwicklung als noch umfassenderen Schritt ausreizen.
  2. Die Qualität des Input für die Engpässe im Rahmen des Möglichen maximieren. Das sind zum einen die Anforderungen und zum anderen die “Arbeitspakete” für die Implementierung. Das heißt, Input und Output der Planung sind das A und O für eine top Implementierung.

Klingt eigentlich ganz normal, oder? Wer etwas Gutes herstellen will, der braucht erstens eine gute Vorstellung davon, was das sein soll (Anforderungen).

Und der braucht zweitens einen guten Plan, wie das Ergebnis effizient hergestellt werden und wie es aussehen soll. Bei all der Diskussion um agiles Vorgehen ist das nur, so scheint es, in Vergessenheit geraten. Da meinen viele, gerade die Planung sei überflüssig. Hauptsache, die Anforderungen schnell in Code gießen und ab damit zum Kunden.

Doch weit gefehlt! Aus der Theory of Constraints (TOC) können wir ableiten, dass dann der Engpass heiß läuft. Denn wo nicht auf Qualität geachtet wird, kehrt der Code mit Macht zurück und belastet den Engpass mit Nachbesserungen. Der kommt dann immer weniger dazu, seinen eigentlichen Job zu machen. Die TOC sagt also das voraus, was immer wieder in Softwareunternehmen zu sehen ist: überlastete Entwickler, die mit der Lieferung von neuen Features nicht hinterherkommen.

Besser leben mit dem Engpass

Was im Detail ausmacht, dass der Engpass nicht mal seine grundsätzliche Kapazität für neue Wünsche an den Start bringen kann, ist erstmal gar nicht so wichtig. Viel wichtiger ist die Anerkennung, dass es erstens überhaupt einen Engpass gibt. Und zweitens dass der für das Wichtigste freigehalten werden muss, das er dann mit Qualität produzieren muss. Also nicht nur überhaupt produzieren, sondern eben mit Qualität, innerer Qualität.

Für Entscheider ergeben sich daraus vor allem vier Fragen:

1. Wie halte ich den Engpass frei für das Wesentliche?
2. Wie sichere ich hohe Qualität für den Output des Engpasses?

Beide betreffen das Ausreizen des Engpasses (exploiting the constraint). Dazu kommt dann noch die Frage, was zu tun ist an den Nicht-Engpass Prozessschritten (subordination of non-constraints). Denn die müssen nicht mehr auf Volllast laufen.

3. Wie steigere ich die Qualität des Outputs vor dem Engpass?

Und schließlich:

4. Wie steigere ich die Kapazität des Engpasses?

Verbesserungsmaßnahmen lassen sich diesen Fragen zuordnen und somit priorisieren. Meine Rangfolge sieht so aus:

1. Qualität des Inputs für den Engpass erhöhen. Weniger Garbage in bedeutet weniger Garbage out – und insofern weniger Nachbesserungen. Die Qualität vor dem Engpass zu erhöhen, ist einfacher als im Engpass, weil die Schritte vor ihm ohnehin mehr Kapazität haben. Upstream Prozessschritte sollten Sie von Engpass-überlastenden Ausstoßmengen umstellen auf höhere Qualität.

2. Den Engpass frei halten für das Wesentliche. Das ist auch noch relativ einfach möglich, weil dafür meist keine Investitionen nötig sind, sondern nur die Veränderung von kontraproduktiven Grundsätzen.

Nach Maßnahmen dieser beiden Kategorien kann sich der Engpass mit seinen – womöglich beschränkten - Kompetenzen und Methoden zumindest voll auf die Umsetzung qualitativ hohen Inputs konzentrieren. Er tut das Wichtigste so gut er eben kann.

3. Die Qualität des Engpass-Outputs erhöhen. Mit der Kapazität, die dem Engpass nun zur Verfügung steht, sollte er unbedingt bemüht sein, die inzwischen hohe Qualität seines Input zu halten.

4. Die Produktivität des Engpass steigern. Am Schluss stehen Maßnahmen, die die vorhandenen Ressourcen stärken oder die Ressourcenzahl vergrößern. Das lohnt jetzt erst, da andere Probleme sonst nur kaschiert würden.

Und was sind nun Maßnahmen in diesen Kategorien? Wie lässt sich konkret mit dem Engpass umgehen? Mir fallen da einige Maßnahmen ein, von denen manche üblich und manche eher selten sind:

Input-Qualität erhöhen

Anforderungen

image

Anforderungen können in zweierlei Hinsicht verbessert werden.

Als erstes ist dazu die Frage zu stellen: “Braucht der Kunde das wirklich?” Der sagt reflexartig natürlich, “Klar! Das will ich haben.” Doch die Anforderungsdefinition sollte sich davon nicht beirren lassen. Jede Reduktion oder besser Fokussierung von Anforderungen hilft, den Engpass zu entlasten. Dazu gehört auch die Priorisierung. Wenn es denn wirklich wahr ist, das der Kunde etwas haben möchte, dann gleich nachhaken, “Ist das sehr wichtig, muss es sofort sein – oder kann es warten?” Dazu gehören auch Überlegungen, ob ein Wunsch komplett realisiert werden muss oder ob zumindest manches weggelassen oder niedriger priorisiert werden kann.

Als zweites ist dann für jede Anforderung die tatsächlich, tatsächlich an die Softwareentwicklung gehen soll eine absolute Präzisierung (im Rahmen des Möglichen) vorzunehmen. Unsicherheit des Kunden ist dabei wieder ein Zeichen dafür, dass die Anforderung abgelehnt werden sollte. Das ist ihm klar zu machen. Wenn er dennoch darauf besteht, dann nachhaken und Akzeptanztestfälle einfordern. Eingabe/Interaktionen und erwartete Ausgaben/Seiteneffekte sind zu protokollieren. Je maschinenlesbarer desto besser.

Requirements Engineering ist die Kunst der Anforderungsdefinition. Nicht umsonst hat sich diese Disziplin herausgebildet. Es ist schwer, Anforderungen von hoher Qualität aus dem Kunden herauszubekommen. Aber es ist nötig, um den Engpass zu schonen. Hier schlummert enormes Verbesserungspotenzial in den meisten Projekten; denn üblich ist es, sich mit Schwammigem zufrieden zu geben, weil es einen (unausgesprochenen) Grundsatzengpass gibt der lautet, man solle sich nicht solange damit aufhalten und lieber das Codieren anfangen. Und außerdem dürfe man den Kunden nicht so mit penetranten Fragen nerven oder gar Wünsche ablehnen, denn es sei ja der König Kunde, mit dem man es zu tun habe.

Bitte verstehen Sie mich richtig: Mir geht es hier um die Qualität (!) der Anforderungen, nicht die Quantität. Aus dem Produktionsprozessdiagramm leitet sich nicht ab, dass man zuerst alle Anforderungen und auch noch in höchster Qualität sammeln müsse. Im Gegenteil. So wenige Anforderungen wie möglich sollten gesammelt werden; nur soviele, bis die Architektur halbwegs festgezurrt werden kann und nur soviele bis ein erster nicht trivialer Nutzen für den Kunden produzierbar ist. Dafür sind immer wieder erstaunlich wenige Anforderungen nötig, wenn man es ausnutzt, das die ja auch auf verschiedenen Abstraktionsniveaus formuliert sein können.

Mit der Erfahrung lernen Sie aber, zwischen wichtig und weniger wichtig zu unterscheiden. Und Sie werden mutiger, mit einer kleineren Menge zu beginnen, wenn Sie wissen, dass Sie in der Programmierung Methoden einsetzen, die Strukturen produzieren, die leicht angepasst werden können.

Denn eines ist zu erkennen: Möglichst viele Anforderungen wollen nur die erheben, die Angst haben, sich mit weniger in eine Code-Ecke zu pinseln, aus der sie dann nicht mehr herauskönnen. Je korrekter und evolvierbarer Ihre Codebasis jedoch ist, desto weniger Angst müssen Sie in dieser Hinsicht haben. Je höher die Qualität der Arbeit der Programmierung, desto fitter wird sie für kleine, hochqualitative Anforderungen.

Gut verdaubar ist der Input von der Anforderungsdefinition für die Softwareentwicklung also auch, wenn er in kleinen Happen ankommt. Das ist der inhärenten, durch keine noch so peinliche Kundenbefragung zu vermeidenden Unschärfe auch ansonsten hochqualitativer Anforderungen geschuldet. Kunden können Anforderungen nicht besser formulieren als sie ihre Wünsche selbst kennen – und das ist oft nicht sehr genau. Anforderungen sorgen daher immer für ein gewisses Maß an Nachbesserung. Ohne iterative Annäherung an die Kundenzufriedenheit geht es nicht. Je kürzer die Feedbackschleife, desto besser.

Aufgaben

image

Was produziert schneller ein Ergebnis, die Verteilung von mehreren Aufgaben auf mehrere pseudo-gleichzeitige Threads auf einem Prozessor oder die echt gleichzeitige die Bearbeitung einer Aufgabe auf mehreren Prozessorkernen? Die Antwort sollte klar sein: Die Multi-Core-Verarbeitung einer Aufgabe ist schneller.

Multithreading macht Sinn, um Latenz zu verbergen. Wenn der Anwender eine langdauernde Verarbeitung anstößt, soll das UI nicht einfrieren bis zum Ergebnis. Also wird die Verarbeitung in einen Hintergrundthread ausgelagert. Dass die Verarbeitung lange dauert, ist dem Anwender somit verborgen. Stößt er mit der gewonnen Bewegungsfreiheit dann aber noch eine und noch eine Verarbeitung im Hintergrund an, dann laufen all die Bearbeitungen nur pseudo-parallel (auf einem Prozessor). Jede einzelne dauert viel zwei- oder dreimal länger als wäre sie das einzige, mit dem sich der Prozessor beschäftigt.

Gegenüber dem Kunden ist es jedoch kontraproduktiv, die Dauer der Implementierung zu verbergen. Gerade angesichts der nicht auszuräumenden Unsicherheit, die auch in hochqualitativen Anforderungen steckt, ist es wichtig, jede Anforderung so schnell wie möglich zu codieren. Latenz darf nicht verborgen, sondern muss reduziert werden.

Die Aufgaben, die die Planung an die Implementierung weitergibt, müssen deshalb so formuliert sein, dass das Implementierungsteam sie mit höchster Geschwindigkeit in Code transformieren kann. Nur so fließt zügig etwas zurück zum Kunden, zu dem er Feedback geben kann.

Das bedeutet, die Aufgaben müssen möglichst alle Teammitglieder parallel (!) an einer (!) Anforderung (bzw. einer Anforderungsscheibe) zum Einsatz bringen. Das ist sozusagen Multi-Core-Implementierung in action. Alle Ressourcen ziehen dann an einem Strang, um eine Anforderung umzusetzen.

Wenn Aufgaben das ermöglichen, ist das allerdings nur eine Facette hoher Qualität. Eine andere, nicht zu vernachlässigende ist, dass Aufgaben keine Implementierungsunsicherheiten enthalten sollten. Als Aufgabe sollte ans Implementierungsteam nur gehen, wofür 100%ige Kompetenz existiert. Ausprobieren, Lernen, Forschen: das sind keine Tätigkeiten im Produktionsschritt Implementierung. Wenn Anforderungen Elemente enthalten, die über die technische/methodische Kompetenz des Implementierungsteams hinausgehen, dann dürfen daraus (noch) keine Aufgaben gemacht werden.

Unsicherheiten und fehlende Kompetenz sind in einem separaten Prozess auszugleichen. Spike Solutions oder Prototypen sind ein probates Mittel, um Technologien wie Lösungsansätze für konkrete Anfordeurgen zu evaluieren, bevor sie an die Implementierung gehen. In die Planung im obigen Diagramm habe ich sie jedoch nicht eingezeichnet, um das Verständnis des Hauptproduktionsflusses zu erleichtern.

Konzentration auf das Wesentliche

Wenn die Input-Qualität am Engpass stimmt, dann gilt es, den Engpass ballastfrei zu machen. Er soll sich volll auf seine Aufgabe konzentrieren. Das ist die Transformation von Anforderungen in Code.

Tun das Softwareentwickler denn aber nicht den ganzen Tag? Nein. Ich kenne keinen Entwickler, der sich nicht in seiner Transformationsarbeit gestört fühlt. Es gibt keinen, der seine acht täglichen Arbeitsstunden voll den Tätigkeiten dieser Kette von Transformationsschritten im Sinne der Produktion neuer Features widmet:

image

Die Störungen fallen für mich in drei Kategorien:

  • Unterbrechungen: Jede Form von Unterbrechung behindert den Engpass. Selbst wenn der Grund der Unterbrechung zur Engpasstätigkeit gehören sollte, reduziert sie seine Kapazität. Unterbrechungen, d.h. ein nicht selbstbestimmter Fokuswechsel, haben einfach zur Folge, dass anschließend Zeit zur Refokussierung aufgewandt werden muss. Mentaler Zustand lässt sich nicht einfach auf einen Stack legen wie aktuelle Parameter einer Methode. Der unterbrochene Entwickler muss also mindestens Aufwand treiben, um “wieder reinzukommen” in was auch immer er vor der Unterbrechung getan hat.

    Leider herrscht an vielen Arbeitsplätzen eine "Unterbrechungskultur”. Jeder kann jederzeit “reinschneien” und die Arbeit anderer unterbrechen. Ein deutliches Symptom dafür sind Entwickler, die mit Kopfhörer arbeiten oder besonders früh/spät anwesen sind, “um endlich mal in Ruhe arbeiten zu können.”

    Die Agilitätsbewegung mag sogar dazu beigetragen haben, Hemmschwellen bei Unterbrechungen abzutragen. Denn wer echt agil arbeiten will, der steckt alle Entwickler in einen Raum, den Team Room. Informationen können dort maximal frei fließen.

    Das ist wahr – hat aber seinen Preis. Ob der aber immer im Blick ist? Der Preis ist Defokussierung und damit eine Vergrößerung der Wahrscheinlichkeit, dass sich Fehler einschleichen. Denn ungestörte Konzentration ist ein wesentlicher Bestandteil hoher Qualität.

    Aber auch die übliche hierarchische Struktur in Unternehmen sorgt gern für Unterbrechungen. Ein Vorgesetzter darf ja schließlich jederzeit Auskunft verlangen oder die Arbeit dirigieren. Die Steigerung ist dann die Unterbrechung durch den ultimativen Vorgesetzten: den Kunden. Wenn der Support auf die Softwareentwicklung durchgreifen kann, ist oft kein Halten; Unterbrechungen, die bis zur Änderung der aktuellen Aufgabe führen, sind dann möglich.

    Gemeinschaftliche Arbeit, ein Team sein und Unterbrechungsfreiheit stehen in einem Spannungsverhältnis. Beides ist nötig. Mir scheint jedoch, dass aus Gründen der Mitarbeiterführung und falsch verstandener Methodik derzeit das Pendel zur Seite einer “Unterbrechungskultur” ausschlägt. Wo alle in einem Raum sind und jederzeit unterbrochen werden kann, da kann kontrolliert werden. Hinzu kommt, dass größere Räume für viele Entwickler kostengünstiger sind als individuelle Büroräume für einen oder max. zwei Entwickler.

    Aber es gibt auch löbliche Gegenbeispiele. Von Microsoft kann man halten, was man will, aber erfolgreich ist das Unternehmen. Und es hat einen ungeheuren Ausstoß. Begründet ist der auch im Umgang mit den Mitarbeitern, die (in den USA) alle ihr eigenes Büro haben – egal wie klein das ist –, in dem sie sich einrichten können, wie sie mögen.

    Andere Maßnahmen gegen Unterbrechungen sind “Bitte nicht stören”-Schilder am “Entwicklerraum” zumindest für einige Stunden pro Tag. Oder die Möglichkeit, Homeoffice-Tage einzulegen. Oder die Einhaltung eines minimalen Prozesses, der verhindert, das Vorgesetzte jederzeit ihr persönliches Informationsbedürfnis bei jedem Entwickler befriedigen können. Oder ausdrückliche Supportzeiten, wenn denn der Support durch Entwickler nicht zu vermeiden ist.

    Unterbrechungen sind ein weit unterschätzter Kapazitäts- und Qualitätsfresser. Tun Sie etwas dagegen am Engpass. Nur so kommen Sie in die Nähe seiner theoretisch verfügbaren Kapazität für geldbringendes Neues.

 

  • Wiederholung: Wer etwas wiederholt, der schafft währenddessen nichts Neues. Entwickler sollen aber möglichst viel Neues schaffen – deshalb sollten sie sich nicht in Wiederholungen ergehen.

    Tätigkeiten, die mehr als drei Mal manuell ausgeführt werden, sollten auf den Prüfstand. Sind sie wirklich nötig, gar in Wiederholung? Wenn ja, lassen Sie sich automatisieren?

    Der Vorteil einer Automatisierung ist sogar dreifach: Nicht nur setzt die Automatisierung Entwicklerkapazität frei für Neues, sie reduziert auch die Fehlerträchtigkeit der Tätigkeit. Und das ist gut, weil Fehler zu Nachbesserungen führen, von denen ja nun hinreichend klar ist, dass sie unbedingt zu vermeiden sind.

    Automatisierbar ist viel. Tests auf allen Ebenen (vom Unit Tests bis zum Akzeptanztests); darüber gibt es hinlänglich Literatur. Aber auch das “Zusammenbauen” von Softwaresystem (Continuous Integration) und das Deployment (Continuous Delivery).

    Viele Softwareteams hängen da allerdings noch weit hinter dem Machbaren hinterher. Ein Release ist oft noch eine periodisch wiederkehrende Drohung für alle Mitglieder, die womöglich sogar mit Urlaubssperre belegt ist.

    Der dritte Vorteil der Automatisierung besteht in der Unabhängigkeit von bestimmten Personen. Sie löst Wissensmonopole auf. Jeder Vorgesetzte sollte schon deshalb daran interessiert sein, soviel wie möglich zu automatisieren, weil er sich damit unabhängig macht von den Grillen einzelner Entwickler.

    Automatisierung bedeutet allerdings nicht immer, dass eine Tätigkeit in Software gegossen wird. Auch die Delegation ist eine Form von Automatisierung. Wenn ein Ablauf so vereinfacht wird, dass ihn nicht mehr der teure Entwickler im Engpass, sondern vielleicht eine Hilfskraft oder gar eine anonyme Crowd-Sourcing-Menge durchführen kann, dann ist das ebenfalls ein Gewinn.

    Gegen die Automatisierung spricht für viele Entwickler und Entscheider, dass die selbst ja Zeit und damit Geld kosten würde. Das ist natürlich richtig erkannt – aber sie deshalb nicht in Angriff zu nehmen, ist zu kurz geschlossen. Wer mit dem spitzen Bleistift rechnet, der sollte richtig rechnen. Richtig bedeutet hier jedoch: auf das Gesamtsystem bezogen und nicht lokal optimierend. Dazu aber mehr in einem anderen Blog-Artikel. Die TOC hat einiges zum Thema Geld zu sagen unter dem Stichwort Durchsatzrechnungswesen (Throughput Accouting). Und danach kostet eine Stunde Entwicklerkapazität, die in eine Wiederholung geht, also den Entwickler für Geldbringendes blockiert, mehr als den Entwicklerstundenlohn. Viel mehr!

    Doch einstweilen mögen zumindest die Vorteile in Bezug auf Qualität und Personenunabhängigkeit dem Skeptiker Prozessoptimierungsfutter sein.

 

  • Abweichung: Wenn Programmierer gerade nicht unterbrochen werden oder sich in Wiederholungen ergehen, dann sind sie immer noch nicht notwendig mit dem Wesentlichen befasst. Ein noch größeres Übel als die beiden bisher behandelten Störungen sind Abweichungen vom Wesentlichen. Entwickler tun einfach häufig, was nichts mit der Produktion von Neuem zu tun hat. Das wird ihnen durch einen Grundsatzengpass aufgedrückt – oder sie wählen es selbst.

    Beispiele für verordnete Abweichungen sind Dokumentationsaufgaben, Support, allgemeine Besprechungen, Statusreports, minutiöse Zeiterfassung oder anderer “Formularkram”.

    Jede einzelne Abweichung hat für irgendwen irgendwann natürlich mal Sinn ergeben. Allemal in Summe sind die in den meisten Unternehmen jedoch parasitär. Sie rauben wertvolle Kapazität am Engpass. Hier eine Minute für eine Umständlichkeit, dort eine Stunde im unproduktiven Meeting… das summiert sich. Neulich hatte ich im Clean Code Developer Training eine Reihe von Entwicklern aus einem großen Unternehmen, die zwischen zwei Trainingsblöcken quasi nicht entwickelt haben, sondern nur dokumentiert. Das ist pure Verschwendung der Engpassressource.

    Doch nicht immer ist “das System” schuld an Abweichungen. Entwickler tendieren dazu, sich selbst vom Wesentlichen abzulenken. Typisch sind dafür in Make-or-Buy-Situationen Entscheidungen für Make.

    Statt ein Tool, eine Bibliothek von der Stange zu nehmen, wird selbst entwickelt. Typisch sind objektorientierte Datenzugriff-Frameworks oder Logging-Infrastruktur oder spezielle GUI-Steuerelemente, die 90% von dem replizieren, was Telerik & Co schon bieten, um 10% angeblich Wichtiges, nein, Zentrales, Unabdingbares für den Kunden hinzuzufügen.

    Immer wieder verschwenden Entwickler Ihre Kapazität in dem Glauben, es doch besser machen zu können (und zu brauchen), als auf eine Problemstellung fokussierte Anbieter am Markt. Das wird dann begründet mit einer Flexibilität und Unabhängigkeit, von der niemand weiß, ob sie überhaupt je relevant wird. Oder es wird mit Kundenwünschen begründet, die so unabdingbar wie exotisch seien, dass nur eine Eigenentwicklung sie abdecken könnte.

    Mein Gefühl ist jedoch, dass hier oft rationalisiert wird. Der wahre Grund für Make-Entscheidungen sind ein Gefühl von Kontrollverlust mangels Methode. Oder schlicht eine “Opferhaltung” gegenüber dem Kunden, die jedes “Widerwort” verbietet. Oder es herrscht Unkenntnis über die Möglichkeiten der kaufbaren Lösungen am Markt.

    Make-Entscheidungen verweisen mithin oft auf tieferliegende Probleme. Ihnen kann zum Beispiel entgegengewirkt werden mit besseren Anforderungen, die deutlicher Unterscheiden, was wirklich, wirklich essenziell ist und was nur nice-to-have. Die Anforderungsanylse in der Planung kann hier auch aufklärend tätig sein, indem sie aufzeigt, wie teuer Make wirklich ist. Denn nicht nur kostet Make fast immer mehr Zeit als Buy, es folgt aus Make auch die Notwendigkeit zur Pflege einer größeren Codebasis. Engpass-Kapazität wird damit doppelt abgezogen.

    Im Zweifelsfall sollte daher die Entscheidung für Buy und eine systematisch geplante Codestruktur fallen, die es erlaubt, die Entscheidung ggf. zu revidieren. Anfangen mit dem eingekaufen Persistenzframework – und zur Not später ersetzen, falls sich herausstellt, dass die Leistung nicht ausreicht. Saubere Separation of Concerns lautet der Name eines probaten Mittels gegen die Angst vor irreversiblen Entscheidungen.

    Abweichungen vom Wesentlichen, d.h. der Produktion von Neuem, lauern überall. Seien Sie sensibel dafür und schieben Sie ihnen einen Riegel vor. Das setzt ungeahnte Kapazität im Engpass frei.

Nur wenn der Engpass sich auf seine Hauptaufgabe konzentriert, kann er effizient etwas mit der hohen Qualität anfangen, die ihm geliefert wird. Zum Glück ist das nicht so schwer. Störungen der beschriebenen Art zu vermeiden, sollte im Grunde wenig bis gar nichts kosten. Das Unternehmen muss nur das Störende sein lassen. Das mag diejenigen schmerzen, die störende Grundsätze aufgestellt haben – doch als Gewinn winkt freigesetzte, fokussierte Kapazität, mit der Neues produziert werden kann.

Output-Qualität erhöhen

Was soll ein Engpass tun, der mit höchster Input-Qualität beliefert wird und darauf seine Kapazität störungsfrei anwenden darf? Er soll Qualität produzieren. Wie das?

Review Release

image

Von innen nach außen betrachtet ist der erste Engpass die Implementierung. Sie transformiert als Aufgaben formulierte Anforderungen in Code. Ihr Output ist ein Review Release. Die Implementierung muss bei ihrer Transformationsarbeit zweierlei sicherstellen:

  • Schadlosigkeit: Egal, was die Implementierung tut, ihre oberste Priorität muss sein, nicht zu schaden. Das heißt, sie darf funktionierenden Code nicht kaputt machen. D.h. die vornehmste Aufgabe der Implementierung ist es, Regressionsprobleme zu vermeiden. Code darf durch sie nicht in einen schlechteren Zustand zurückfallen. Und schlechter ist jeder Zustand, bei dem vormals Funktionierendes nicht mehr funktioniert. Das ist unter allen Umständen zu vermeiden, nicht nur weil es zu Nachbesserungen führt, sondern weil jede Regression am Vertrauen nagt, das Anwender gefasst haben.

    Anwender leben mit vielem. Sie leben sogar mit Bugs. Aber noch frustrierender als Bugs sind Bugs dort, wo vorher keine waren. Die untergraben jedes Gefühl von Verlässlichkeit, das sich eine Software mühevoll erarbeitet haben mag.

    Die Schadlosigkeit von Veränderungen lässt sich nur nachweisen, wenn die Software anschließend in allen Bereichen betestet wird. Funktionale Abhängigkeiten ziehen sich weit durch ein Softwaresystem, so dass nicht triviale Änderungen kaum vorhergesagt werden kann, auch welche Teile sie sich auswirken. Es ist daher am besten, schlicht immer alles wieder und wieder zu testen.

    Das ist natürlich nur ökonomisch machbar mit automatisierten Tests und automatisierter Integration. Der Hauptzweck von automatisierten Tests ist mithin nicht die Feststellung der Fehlerfreiheit neuen Codes, sondern die Regressionsfehlerfreiheit alten Codes zu “beweisen”.

    Hier ist eindeutig der Implementierer gefragt. Er stellt den Code her, also ist er für dessen Qualität zuständig. Regressionstest auf eine Qualitätssicherung (oder gar den Kunden) zu verlagern, ist falsch im Sinne sauberer Produktion.

 

  • Nützlichkeit: Veränderungen sind nur nützlich, wenn sie nicht nur die funktionalen wie nicht-funktionalen Anforderungen erfüllen, sondern das auch noch fehlerfrei tun. Dass bekannt ist, was diese Anforderungen sind, dafür sorgen hochqualitative Anforderungsdefinition und Planung. Die Implementierung muss sie dann “nur” noch in Code gießen.

    Das ist natürlich immer noch eine anspruchsvolle Aufgabe. Bei aller Planung bleibt für die Implementierung selbstverständlich Kreativitätsfreiraum. Code Cowboys sind dort jedoch fehl am Platze. Wer schneller Produktionscode raushaut als sein Schatten ziehen kann, ohne die Korrektheit solide geprüft zu haben, der dient nur bedingt der Nützlichkeit.

    Für die Nützlichkeit sind deshalb solides Domänenwissen unabdingbar, um die Anforderungen optimal zu verstehen. (Achtung: Die Domäne muss nicht unbedingt die Geschäftsdomäne des Softwaresystems sein! Auch Security oder Verteilte Systeme sind Domänen, in denen erheblicher Code nötig sein kann.) Dazu kommt solides Technologiewissen, um die Anforderungen/Aufgaben optimal umzusetzen. Und schließlich ist zu prüfen, dass diese Umsetzung tatsächlich gelungen ist. Fehlerfrei.

    Implementierer testen deshalb gegen aufgabenbezogene Akzeptanzkriterien, die von der Planung als Vorstufe der Implementierung geliefert werden müssen. Wenn ein Implementierer Code weiterreicht an den nächsten Prozessschritt, soll er ruhig und gewiss sein, dass er nicht nur für Funktionalität, sondern auch für Korrektheit gesorgt hat. Und zwar automatisiert, denn seine Tests müssen als Regressionstests zukünftig wiederholt werden können (s.o.).

    Im Implementierer als Kernengpass müssen Smartness und Sorgfalt vereint sein. Sie befähigen ihn, das Gewollte zu verstehen, es effizient und effektiv umzusetzen – und das auch noch fehlerfrei.

    Technologiekompetenz spielt dabei nur ein untergeordnete Rolle. Sie lässt sich vergleichsweise schnell erwerben (s.u. Produktivität steigern). Wichtiger ist eine Persönlichkeit mit schneller Auffassungsgabe und Verantwortungsbewusstsein. Wie Joel Spolsky schon sagte: “smart and getting things done”, so sollen Implementierer sein.

    Sollte es an solchen gut organisierten smarten Entwicklern im Team noch mangeln, dann kann Pair Programming helfen. Indem zwei Entwickler an einer Maschine sitzen, wird jeder einzelne entlastet. Innere und äußere Codequalität können durch zwei Personen repräsentiert werden, die jede für sich darauf achtet, dass ihre Werte Beachtung finden.

    Das dient dann nicht nur der Nützlichkeit, sondern auch dem Teamgeist sowie der Ausbildung. Ohne formale Instruktion kann hier Wissen weitergegeben werden.
Release Candidate

image

Die Programmierung ist der die Implementierung umfassende Engpass. Sie wandelt Anforderungen in Release Candidates um. Was sie verlässt, könnte aus ihrer Sicht zum Kunden gehen. Dessen ist sie sich zunächst einmal sicher, weil sie ihren Input einer Qualitätskontrolle unterzieht (Anforderungsanalyse) und die eigentliche Transformation durch die Implementierung sorgfältig vorbereitet.

Dennoch könnte der Transformationsoutput suboptimal ausfallen. Nicht unbedingt im Hinblick auf die (nicht) funktionalen Anforderungen, sondern in Bezug auf die innere Qualität. Die Fixierung von Anforderungenn in Code ist so essenziell, dass sie nicht einfach der Implementierung überlassen werden kann. Bei aller Sorgfalt soll die ja nicht die Aufgaben der Planung in Frage stellen. Dort aber können sich Unsauberkeiten oder gar Fehler eingeschlichen haben, die erst durch die Implementierung sichtbar werden.

Deshalb sollte die Programmierung im Anschluss an die Implementierung überprüfen, ob deren Output den Qualitätsansprüchen in jeder Hinsicht genügt. Nicht nur Fehlerfreiheit, sondern Konformität mit der Planung und Eignung der Planung vertragen einen genauen Blick. Die Umsetzung der Planung lässt sich auch nicht anders sicherstellen; den Code müssen sich Menschen anschauen.

Das Mittel dafür sind Codereviews. Hier sitzen Implementierer und Planer zusammen über der Frage, ob die Transformation den Erwartungen entspricht. Hält sie unmittelbar, was sie soll, d.h. ist sie funktional und korrekt? Und hält sie langfristig, was sie soll, d.h. ist sie evolvierbar. Reviews zurren die Qualität von innen fest, bevor der Code an den Kunden geht.

Darüber hinaus sind Reviews ideale Orte, um Wissen im Team zu verteilen. Technologieverständnis, Grundsätze, Konventionen breiten sich durch Reviews ganz natürlich aus. Reviews sind also nebenbei eine kostenlose Fortbildungsmaßname.

Release

image

Wenn die Programmierung mit dem Code zufrieden ist, dann ist das schon eine gute Sache. Aber ob ein Release Candidate wirklich reif für den Kunden ist, sollten nicht Programmierer festlegen. Dafür braucht es vielmehr den Blick einer codeunabhängigen Instanz.

Die Programmierung hat die Qualität des Code von innen festgezurrt. Der Markt (vertreten durch den Vertrieb) ist daran allerdings nur zum Teil interessiert. Er blickt von außen auf die Software. Deshalb sollte die Qualität auch noch von außen festgezurrt werden. Das ist die Aufgabe der Qualitätssicherung (QS).

Ihre Leistung besteht darin, einen schon grundsätzlich nützlichen Code daraufhin zu prüfen, ob er wirklich den Ansprüchen des Marktes genügt. Die misst den Code daher nochmal ganz anders an den Anforderungen. Hier geht es um Usability, flüssige Installation, Integration mit anderen Systemen, oder “Extremfälle” der Bedienung.

Die Programmierung hat nur einen begrenzten Horizont was den realen Einsatz ihres Codes bei den Anwendern angeht. Das ist notwendig so, weil Entwickler keine Anwender, keine Geschäftsdomänenexperten sind. Das sollen sie auch nicht sein. Dennoch oder gerade deshalb muss durch deren Brille eine Qualitätssicherung stattfinden - im Haus der Softwareentwicklung und nicht erst beim Kunden.

Die QS ist verbunden mit der Anforderungsdefinition. Beide sitzen im Grunde auf derselben Abstraktionsebene als Klammern um die Programmierung herum. Was vorne gefordert wird, muss hinten erfüllt sein. Das prüft die QS mittels möglichst automatisierter Tests. Dabei repliziert sie natürlich nicht alle Tests, die schon in der Implementierung gelaufen sind. QS-Tests sind Integrationstests. Sie checken, dass die Teile gut zusammen funktionieren.

Die QS braucht andere Kompetenz als die Programmierung. Deshalb sollten Programmierer nicht gleichzeitig QS-Beauftragte sein. Es ist auch zu vermeiden, dass sich durch Personalunion die QS “etwas in die Tasche lügt”. In gewisser Weise sind Programmierung und QS eher Antagonisten.

Während die Implementierung Unit Testing Frameworks einsetzt, benutzt die QS Tools wie FitNesse, Ranorex oder Scripting. Oder sie lässt sich von der Implementierung einen Prüfstand einrichten. In jedem Fall hat sie den Code nur Zugriff von außen.

Intermezzo: Qualitätsschalen

Der Engpass Softwareentwicklung ist kompliziert. Das liegt gar nicht mal so an der reinen Codierung, d.h. der Transformation von Anforderungen in textuellen Quellcode und dann lauffähige Software. Die Welt ist voll von Code, der Anforderungen erfüllt – irgendwie.

Die Herausforderung besteht darin, Code so herzustellen, dass er gleichzeitig den expliziten funktionalen wie nicht-funktionalen Anforderungen von außen dient – wie den impliziten Anforderungen von innen. Werden erstere erfüllt, kann der Vertrieb mit der Software heute Geld verdienen. Doch nur wenn letztere ebenfalls erfüllt sind, kann dieses Geld erstens zügig und zweitens auch noch morgen verdient werden. Erinnern Sie sich: Das Ziel eines Unternehmens ist es, gutes Geld heute und in Zukunft (!) zu verdienen.

Dass das mit Code auch in Zukunft geht, ist kein Selbstgänger. Das ist nur möglich, wenn die Implementierung verlässlich schadlos arbeitet und das, was sie produziert eine Form hat, die sich dem stetigen Fluss des Neuen anpassen lässt. Damit das der Fall ist, darf ein Implementierer auch nicht direkt mit dem Kunden die Anforderungen aufnehmen und sofort in Code gießen. Das Ergebnis zeigen die vielen durch RAD unwartbar gewordenen Anwendungen. Erstes Symptom sind Massen an Code in GUI-Eventhandlern.

Nein, für das komplexe Geschäft der Softwareentwicklung ist – wenn es nachhaltig betrieben werden soll – eine systematischere Überführung von Wünschen in Code nötig. Mir scheint das Bild von Qualitätsschalen passend:

image

Die äußere Schale kümmert sich darum, dass Vorschläge in eine Software überführt werden, die dem Kunden Freude macht. Dafür prüft sie die Vorschläge und formalisiert sie in Form von Anforderungen; und am Ende prüft sie den Code aus Sicht des Kunden in der Qualitätssicherung. Die äußere Schale steht für eine reine Außensicht auf die Software

Eingeschachtelt in die äußere Schale ist eine Schale, deren Thema die Strukturierung der Software ist. Sie leitet aus den Anforderungen einen Architektur- und Modellrahmen ab, sie konzeptioniert die Lösung. Und am Ende prüft sie, ob das Konzept vom Code eingehalten wird. Diese Schale bildet den Übergang von äußerer Sicht zu innerer Sicht. Sie steht unter Spannung, weil sie unmittelbare Qualität für den produzieren und gleichzeitig die Nachhaltigkeit der Programmierung sichern soll. Diese Spannung existiert immer; nur durch eine Schale jedoch, die dafür konzipiert ist, sie auszuhalten, verhindert die Softwareproduktion, sich daran aufzureiben. Die mittlere Schale ist sozusagen Schmierstoff zwischen Außensicht und Innensicht, die in entgegengesetzte Richtungen rotieren.

image

Im Kern steht schließlich die Codierung. Sie bewegt sich im Architektur- und Modellrahmen und ist nach innen gewandt. Ja, sie muss sich in einem solchen Rahmen bewegen, um effizient zu sein, ohne die Korrektheit und Evolvierbarkeit aus den Augen zu verlieren. Der Architektur- und Modellrahmen isoliert sie von der ewig unverständigen Außenwelt – und umgekehrt isoliert der Rahmen die Außenwelt von vom unverständlichen Code.

Die Außenwelt ist volatil, Code ist – trotz seiner Unstofflichkeit – vergleichsweise starr. Wenn also nur “irgendwie” Vorschläge in Code gegossen werden, dann befriedigt das höchstens kurzfristig das Kundenbedürfnis. Langfristig jedoch zerreibt sich das System ohne Schmiermittel an der Gegenläufigkeit Spähren von Kunde und Implementierer.

Wenn Software unwartbar geworden ist, dann ist das eigentlich ein Ergebnis mangelnder Entkopplung zwischen Anforderungen und Code.

Kapazität steigern

Wenn die Input-Qualität beim Engpass stimmt, kommt es darauf an, wie der seine Kapazität einsetzt.

Wenn der Engpass seine Kapazität störungsfrei einsetzen kann, kommt es darauf an, dass er das Richtige tut.

Wenn er das Richtige tut, kommt es darauf an, wieviel Kapazität überhaupt vorhanden ist.

Es kann dann sein, dass der Engpass immer noch zuwenig Kapazität dafür hat, das Richtige mit hochqualitativem Input in ausreichender Menge zu tun. Extrembeispiel: Ein schlecht ausgebildeter langsamer Entwickler hat weniger Kapazität als 5 gut ausgebildete schnelle Entwickler.

Um den Engpass endgültig aus seiner Rolle herauszuheben, sind also womöglich weitere Maßnahmen nötig. Im einfachsten Fall bestehen die darin, dem Engpass mehr Personal zuzuordnen. Das trifft allemal zu, wenn ein Prozessschritt bisher gar nicht besetzt ist, z.B. keine Qualitätssicherung betrieben wird. Die schiere Nichtexistenz eines Schrittes macht ihn per definitionem zum Engpass.

Sobald jedoch Personal im Engpass arbeitet, lautet die Frage, wie dessen Kapazität erhöht werden kann. Als erstes mögen da Anreize in den Sinn kommen. Würden Implementierer nicht das Richtige schneller erledigen, wenn man ihnen einen Bonus für frühere Auslieferung verspricht? Wie die Forschung der letzten 50 Jahre zeigt, funktioniert das leider nicht für kreative/problemlösende Tätigkeite. Jedem Entscheider sei zu diesem Thema dieses Buch empfohlen: Drive von Dan Pink. Oder zum Schnuppern im Thema dieses Video:

Nein, mehr Produktivität beim Richtigen gibt es nicht so einfach. Weder Zuckerbrot noch Peitsche helfen bei einer Arbeit wie der Softwareentwicklung.

Unterm Strich helfen wohl nur zwei Strategien: Scale-Out und Scale-Up. Mehr Entwickler oder bessere Entwickler sind der Weg zu mehr Kapazität.

Scale-Out

Scale-out bedeutet, mehr Personen in der Softwareentwicklung zu beschäftigen. Ob die dann im Hause sitzen oder in einem fernen und viel billigeren Land, ist erstmal egal. Voraussetzung ist in jedem Fall, dass die Planung es hergibt, dass mehr Entwickler auch mehr wegschaffen.

Brooks´ Law sagt, dass es kontraproduktiv sei/sein kann, Manpower einem Projekt hinzuzufügen. Die zusätzlichen Personen wollen koordiniert sein und erzeugen zusätzliche Kommunikation. Das ist selbstverständlich ganz grundsätzlich wahr – doch es gibt Regler, mit denen ein nachteiliger Effekt zumindest gemildert, wenn nicht auch bis zu einem gewissen Grad ganz vermieden werden kann.

Mehr Entwickler konflikfrei und nutzbringen zu beschäftigen, so dass sie den Engpass wirklich weiten, ist nicht unmöglich. Allerdings ist dafür Planung notwendig. Wer die Kapazität mit Scale-out erhöhen will, tut daher gut daran, den Entwicklungsprozess zu systematisieren und eine entsprechende Arbeitsorganisation vorzunehmen.

Die meisten Projekte sind in dieser Hinsicht noch schlecht aufgestellt. Sie planen die Softwarestrukturen nur ungenügend und allemal nicht mit Blick auf ein Scale-out. Deshalb fällt es ihnen schwer, diesen Weg zur Kapazitätserhöhung gehen zu können.

Ohne vernünftige Architektur, Modellierung und darauf basierend eine Arbeitsorganisation für “Multi-Core-Entwicklung” nutzt mehr Entwicklerpersonal wirklich kaum oder ist gar hinderlich.

Scale-out scheint so einfach zu sein. In Wirklichkeit ist Scale-out jedoch nur für fortgeschrittene Teams, die ihre Produktion systematisch betreiben und im Griff haben. Beim Hausbau mögen doppelt soviele Maurer ganz einfach die Bauzeit verkürzen. Bei der Softwareentwicklung geht es nicht so direkt – ist jedoch nicht prinzipiell unmöglich.

Prozessschritte, die noch nicht besetzt sind, sollten besetzt werden. Darüber hinaus allerdings Zurückhaltung beim “Entwicklerkauf”.

Scale-Up

Vor dem Zukauf von Kapazität steht die Entwicklung der vorhandenen Kapazität. Statt mehr Entwickler lieber die vorhandenen besser machen. Das hat übrigens einen zwiefachen Effekt: Nicht nur erhöht sich damit die Kapazität der Entwickler, so dass dieselben mehr verkaufbares Neues pro Zeiteinheit schaffen können. Es erhöht sich auch die Motivation und damit die Bindung ans Unternehmen. Und das ist unschätzbar, da Fluktuation einer der größten Geldverschwendungsposten ist. In einer nicht trivialen Domäne kostet der Verlust eines eingearbeiteten Entwicklers schnell 100.000 EUR und mehr.

Man rechne also einmal: Wenn alle 2 Jahre ein Entwickler geht, dann kostet es im Schnitt pro Jahr 50.000 EUR, einen neuen Entwickler einzuarbeiten. Falls irgendeine Maßnahme nun dafür sorgt, dass nur noch alle 4 Jahre ein Entwickler das Team verlässt, dann kostet sein Ersatz im Schnitt nur noch 25.000 EUR pro Jahr. Jede Maßnahme, für die weniger als 25.000 EUR pro Jahr aufgewandt werden muss, um die Fluktuationsfrequenz von 2 auf 4 Jahre zu senken, ist damit ihr Geld wert.

Entwickler besser zu machen, ist so eine Maßnahme, sogar eine mit doppeltem Effekt. Verbesserung sollte also ganz oben auf der Prioritätenliste jedes Entscheiders stehen. Die Mittel dazu sind vielfältig. Manche kosten gar nichts oder wenig, andere kosten mehr. Am Ende macht es der Mix. Regelmäßige Fachlektüre gehört dazu wie der regelmäßige Austausch mit anderen Entwicklern (online in Diskussionsgruppen oder offline bei User Groups), ebenso der Besuch von Konferenzen und Trainings.

Trainings für Methoden sind hierbei solchen für Technologien vorzuziehen. Der Grund: Technologien lassen sich leichter allein lernen, da das Feedback, ob man es schon gelernt hat, unmittelbar von der Maschine kommt. Entweder hat man WPF, WCF, WF usw. richtig bedient oder nicht. Bei Methoden jedoch, bei neuen Verhaltensweisen, da ist solches Feedback schwerer oder nur verzögert zu erhalten. Autodidaktentum hilft in diesen Fällen nur begrenzt. Besser ist es, wenn man sich von Erfahrenen/Lehrern in das Thema einführen und beobachten lässt.

Fortbildung allein ist aber nicht alles. Die legt nur den Samen für Kapazitätswachstum. Zur Fortbildung müssen Spielräume (im doppelten Sinne) treten. Eigentlich soll die Softwareentwicklung eines: performen. Das ist wie die Aufführung für einen Künstler. Da darf es keine Patzer geben.

Aber natürlich kann das ein Entwickler genauso wenig wie ein Künstler aus dem Stand. Also ist wie beim Künstler auch Übung notwendig. Wer performen soll, der muss Zeit zum Üben bekommen; allemal Neues muss erst geübt werden, bevor es in der Produktion für den Kunden zum Einsatz kommt. Wer top fit sein und bleiben will, für den ist Freiraum zum Lernen wichtig; ein Raum, in dem Fehler gemacht werden können und sollen. Nur so kann am Engpass die nötige Leistung gebracht werden.

Aber Achtung: Es wäre ein Fehlschluss zu glauben, dass Fortbildung unnötig sei, wenn man mit geringerer Performance zufrieden ist. Fehlende Kompetenz führt nämlich nicht einfach nur zu geringerer Geschwindigkeit, sondern auch noch zu geringerer Qualität. Fehlende Kompetenz ist eine doppelte Bremse. Ein halb so guter Entwickler ist nicht nur halb so schnell, sondern unterm Strich wahrscheinlich nur ein viertel so schnell wie ein guter Entwickler.

Ich behaupte daher mal: Es gibt eine inverse Korrelation zwischen Fortbildungskultur und Druck im Team. Wird Fortbildung groß geschrieben, dann ist der Druck eher gering – und umgekehrt. Dazu fällt mir ein, “Wenn du es eilig hast, gehe langsam.” Wer ein hochperformantes Team will, der muss Zeit für Fortbildung und anschließendes Üben einräumen, auch wenn das die so wertvolle Kapazität des Engpasses scheinbar reduziert.

Investition in Verbesserung ist kontraintuitiv: Da wird Geld ausgegeben für Zeit, die bei der Produktion von Nützlichem fehlt und am Ende ist dann alles besser?

Ja. Definitiv. So ist das (Aus)Bildung. Erst stecken wir in Kinder und Jugendliche ja auch mehr als ein Jahrzehnt an Ausbildung, bevor Unternehmen mit ihnen Geld verdienen. Und danach hört der Kausalzusammenhang zwischen “mehr Bildung” und “mehr Wertschöpfung” ja nicht einfach auf. Das kann nur glauben, wer auch glaubt, dass die Softwareentwicklung ein eher statisches Geschäft ist, vielleicht wie die Maurerei oder die Arbeit an der Brötchentheke. Das Gegenteil ist jedoch der Fall. Also kann die Konsequenz nur lauten: Wer auch nur gut bleiben will, muss eine Lernkultur im Unternehmen etablieren. Lernen darf nicht zum Privatvergnügen verkommen.

Doch nicht nur Fortbildung sorgt für Kapazitätssteigerung. Jede Reduktion von Gängelung weckt Kapazitätspotenziale bei Entwicklern. Denn wer unter Druck steht – und das tut der Engpass ja ständig –, der kann damit besser umgehen, wenn er im Gegenzug Autonomie bekommt, um zu entscheiden, wie er mit dem Druck am bekömmlichsten umgeht.

Kontraproduktive Gängelungen sind z.B. die Fixierung von Ort und Zeit für die Arbeit für alle. “Gearbeitet wir in diesem Büro zu diesen Konditionen in diesen Zeiträumen.” Das ist normal, deshalb aber nicht der Motivation förderlich. Warum sollen Entwickler sich nicht selbst organisieren in Bezug auf Arbeitszeit und Ort – solange die Resultate stimmen? Dieser Gedanke ist nicht neu, seine Gefolgschaft unter dem Banner ROWE wächst. Es winken mehr Produktivität und größere Zufriedenheit.

Oder wie wäre es, die Softwareentwicklung nicht mehr in ein Budget zu zwingen? Es ist eine vergleichsweise preiswerte Anreizmaßnahme, Entwicklern zuzugestehen, dass sie alles, was sie meinen, für ihre Arbeit zu brauchen, auch anschaffen dürfen. Ja, alles. Wer meint, 3 Monitoren seien besser als 2 für seine Tätigkeit, der sollte darüber nicht lange diskutieren müssen. ReSharper für alle? Klar. Eine Lavalampe als Signal für den Buildprozesserfolg? Kein Problem. Laptops mit 256 GB SSD für jeden? Absolut. Noch ein Fachbuch, noch eine Fachzeitschrift? Immer her damit.

Vertrauen Sie darauf, dass der Engpass diese Befreiung nicht ausnutzt. Ich habe noch keinen Entwickler gesehen, der den Bogen überspannt hat. Allemal als Experiment sollte jedes Unternehmen sich darauf einmal einlassen.

Wie gesagt, es winkt doppelter Gewinn für die Reduktion von Gängelungen: nicht nur stärkere Bindung entsteht – Wer würde nicht um alles in der Welt in einem Unternehmen arbeiten wollen, in dem er arbeiten kann wann und wo er will und auch noch alle Gadgets/Tools bekommt, die er sich erträum? –, nicht nur wird das Unternehmen attraktiver und zieht bessere Leute an, es steigt einfach die Motivation und damit der Arbeitseinsatz in der vorhandenen Zeit.

Boni sind untaugliche Anreize; aber ein Milieu, eine Kultur der Autonomie, der Selbstorganisation, der Orientierung am Resultat ist sehr reizvoll. Echte Wertschätzung in Form von Vertrauen ist am Ende billiger und bindender als jeder Bonus.

Zwischenstand

Puh, das ist ein langer Artikel geworden. Aber irgendwie hängt alles zusammen am Engpass. Ich habe keine rechte Sollbruchstelle gesehen, wo ich ihn hätte auftrennen können.

Wer seine Softwareentwicklung verbessern will, der muss am Engpass ansetzen. Meist ist das die Softwareentwicklung. Also, was tun, vor allem, wenn der Engpass auf unterschiedlichen Abstraktionsebenen existiert? Es gibt eine Menge Ansatzpunkte.

Als erstes sind alle Produktionsschritte zu besetzen. Das ist in den meisten Teams die vordringlichste Aufgabe. Wo kein Entwurf, kein Review, keine Qualitätssicherung existiert, da muss überhaupt mal die Produktionsmaschine angeworfen werden.

Aber danach geht es los mit der Verbesserung des Input für den Engpass, seiner Ausnutzung, seiner Qualität und schließlich der Kapazitätssteigerung.

Bleibt nur die Frage, was sich dann am meisten lohnt? Und wie das alles bezahlen? Verbesserungen kosten doch erstmal Geld. Dazu beim nächsten Mal mehr. Dann binde ich den Produktionsfluss an das liebe Geld an. Denn ultimativ muss sich jede Veränderung am Geld messen. Jede Veränderung muss ja dem Ziel des Unternehmens dienen: Geld verdienen heute und in der Zukunft.

Donnerstag, 24. März 2011

Flow im Unternehmen – Teil 2 – Qualität

Wenn die Softwareentwicklung besser werden soll, dann ist nicht jede Veränderung von gleichem Wert. Das liegt auf der Hand. Doch welche Veränderungen sind anderen vorzuziehen? Sollte ein weiterer Entwickler eingestellt werden? Oder besser auf TFS umstellen? Oder zur WCF-Schulung gehen?

Solche Fragen sollten nicht aus dem Bauch heraus entschieden werden. Es braucht vielmehr ein Rahmenwerk, in dem Sie Scrum, TFS, WCF, CCD als Werkzeuge einordnen können. Und dieses Rahmenwerk sollte mit Werten ausgestattet sein, für die Sie fragen können, ob eine Veränderung sie unterstützt oder behindert. Und darüber braucht es dann noch ein Ziel für das Ganze.

In meinem vorherigen Artikel habe ich angefangen, ein solches Rahmenwerk zu skizzieren. Es basiert auf der Theory of Constraints (TOC). Der grundsätzliche Gedanke dahinter: Sie können die Softwareentwicklung als einen Produktionsprozess ansehen, der aus irgendwelchem “Material” Software herstellt, für die am Ende Kunden Geld bezahlen.

Geld mit Software zu verdienen heute und (!) in der Zukunft, ist mithin das Ziel der Softwareentwicklung bzw. einer größeren Organisation um sie herum. Und nur, wenn eine Veränderung dazu führt, dass heute mehr Geld verdient oder das Geldverdienen in der Zukunft gesichert wird, dann ist sie für diese Organisation lohnend.

Also nochmal die Frage: Lohnt es sich, den WCF-Kurs zu machen? Bringt die Einführung von TFS etwas? Sollten alle Entwickler nach CCD-Prinzipien und Praktiken arbeiten?

Die Antwort gibt nie der Anbieter, sondern immer nur der Softwareproduktionsprozess. Dafür muss der natürlich bewusst sein.

Engpass intern oder extern?

Bisher habe ich nur die offensichtlichen Produktionsschritte einer Softwareentwicklung genannt:

image

Software wird geschrieben und dann verkauft. Das sieht nicht nach viel aus, doch auch die Formulierung dieses kleinen Prozesses bringt schon etwas. Denn mit der TOC auf ihn geblickt können wir fragen: Wo liegt der Engpass?

In jeder Sequenz von Prozessschritten gibt es einen Engpass, d.h. einen Schritt mit kleinster Kapazität.

Wieviele Einheiten kann ein Prozessschritt pro Zeiteinheit verarbeiten, aufnehmen, “verdauen”? Das ist seine Kapazität K. Gegenüber dem vorgeschalteten Schritt erscheint die Kapazität dann als Bedarf. Bedarf, weil Kapazität natürlich ausgeschöpft sein will.

Optimal ist die Lage, wenn die Kapazitäten aller Prozessschritte gleich sind und jeder Schritt einen Ausstoß A hat, der dem Bedarf des folgenden entspricht: Ai = Ki+1.

So ist es jedoch im Grunde nie. Die Kapazitäten von Prozessschritten sind erstens unterschiedlich und zweitens entspricht der Ausstoß nicht immer dem Bedarf. Wie im vorherigen Artikel erklärt, kann der Ausstoß des Gesamtprozesses dann höchstens so groß sein, wie der maximale Ausstoß des Engpasses, d.h. des Schrittes mit der kleinsten Kapazität in Bezug auf die zu produzierenden “Packerl”.

Überlegen Sie einmal, wo bei Ihnen im Unternehmen der Engpass ist. Bisher sind am Produktionsprozess nur 2 Produzenten und 2 Konsumenten beteiligt:

  • Softwareentwicklung: Produzent
  • Vertrieb: Produzent + Konsument (Prosument? ;-)
  • Markt: Konsument

Welcher hat die geringste Kapazität?

  • Kann der Vertrieb pro Zeiteinheit den Markt mit “Packerln” befriedigen? Oder dreht der Vertrieb Däumchen? Mein Gefühl ist, dass es kaum einen Vertrieb gibt, der sagt, der Markt wolle seine Software nicht. Wenn es eine Klage gibt, dann die, dass man nicht genug verkaufe, weil es der Software noch an etwas fehle. Es gibt also Bedarf, der nicht befriedigt werden kann. Das bedeutet, der Markt ist nicht der Engpass.
  • Wie ist es aber mit dem Vertrieb selbst? Er könnte selbst der Engpass sein. Dann gäbe es Bedarf und die Software wäre dem auch angemessen, alle vom Markt nachgefragten Features sind enthalten. Dennoch sind die Verkäufe schleppend. Das kann leicht bei einem Startups der Fall sein: Da haben existiert schon eine von Enthusiasten geschriebene Software, es gibt einen Markt – nur ist die Software noch unbekannt.
  • Bei etablierten Firmen scheint es jedoch am häufigsten, dass weder Markt, noch Vertrieb der Engpass sind – sondern die Softwareentwicklung. Der Markt hat Bedarf, der Vertrieb würde gern verkaufen, er sitzt auf einer Liste von Interessenten. Der Software fehlen aber immer wieder entscheidende Features, die Softwareentwicklung zu langsam für den Vertrieb produziert.
    Beispiel: Die Softwareentwicklung stellt alle 3 Monate ein neues Release her. Daraus kann der Vertrieb jeden Monat 10 “Packerl” schnüren und verkaufen. Wenn allerdings noch Feature A und B enthalten wären, dann könnten 12 “Packerl” geschnürt und verkauft werden. Das ist aber frühestens in weiteren 3 Monaten der Fall. Also ist die Softwareentwicklung der Engpass. Und das so lange, bis sie Release mit einer Frequenz ausstößt, dass es für den Vertrieb keinen Unterschied mehr macht. (Eine solche Softwareabteilung habe ich aber in 13 Jahren Beratungspraxis noch nicht gesehen.)

Sie sehen: Schon mit einem solch einfachen Diagramm lassen sich interessante Erkenntnisse gewinnen. Liegt der notwendig existierende Engpass in Ihrem Unternehmen oder außerhalb im Markt? Müssen Sie intern etwas tun, damit mehr Geld verdient wird – oder ist es Ihnen quasi aus der Hand genommen, weil die Gründe für schlechten Verdienst extern sind?

Hm… gibt es überhaupt einen externen Engpass? Kann der Markt der Engpass sein? Oder ist dann nicht auch intern etwas im Argen und man produziert die falsche Software? Ja, ich denke, so ist es wohl. So wie es kein schlechtes Wetter, sondern nur unangemessene Bekleidung gibt, so gibt es auch keinen Engpass im Markt, sondern nur Produkte, die am Bedarf vorbeigehen.

Aber darauf will ich an dieser Stelle nicht näher eingehen. Als Softwareentwickler vertrauen wir mal darauf, dass unsere Auftraggeber wissen, warum sie wollen, was sie wollen, und dass das auch bedarfsgerecht ist.

Der Gedanke, dass es eigentlich keinen externen Engpass gibt, ist jedoch insofern nützlich, als dass er die Unterscheidung zweier Arten von Engpässen motiviert. Denn offensichtlich können Grundsatzentscheidungen (“Wir produzieren eine Software mit diesen und jenen Features.” (die den Markt leider nicht interessieren) oder “Wir hauen lieber schnell neue Releases raus, als dass wir auf Evolvierbarkeit achten.”) Einfluss auf den “Pakerl”-Absatz haben – die dann als Engpass im Markt wahrgenommen werden.

In der Literatur gibt es daher nicht nur den Begriff Produktionsengpass (production constraint), sondern auch Grundsatzengpass (policy constraint). Bei ersterem geht es um die Ressource mit ihrer Kapazität, bei letzterem um die Steuerung der Ressource. Wenn eine Ressource eigentlich mehr könnte, aber durch einen Grundsatz behindert wird, die Kapazität auszuschöpfen, dann liegt ein Grundsatzengpass vor.

Prozessverfeinerung

Wenn schon eine einfache Vorstellung einem Softwareproduktionsprozess hilft, dann hilft eine differenziertere bestimmt noch mehr. Wie könnte also eine Verfeinerung des bisherigen Bildes aussehen, ohne an Allgemeingültigkeit zu verlieren? Ich denke, die Softwareentwicklung sollte nicht mehr so autonom produzieren; denn woher bekommt sie bisher den Anstoß für die Herstellung ihrer Releases?

image

Ich denke, es geht los bei einer Marktanalyse. Irgendwer sammelt am Markt die unerfüllten Wünsche der Zielgruppe. Die werden gesichtet, gefiltert, verdichtet und zu Vorschlägen für Features gebündelt. Typische Marktanalysten sind Vertriebler, Supporter oder auch der Geschäftsführer.

Mir geht es nicht darum, wer konkret als Person nin einem Unternehmen die und anderes tut. Ich spreche hier über Produktionsschritte oder Rollen. Irgendwer muss halt den Markt analysieren oder die Software entwickeln. Ob das verschiedene Personen oder dieselben tun, ist zunächst einmal egal.

Diese Vorschläge sind für die Softwareentwicklung meist zu schwammig. Deshalb nimmt sich ihrer eine Anforderungsdefinition an, die sie filtert, formalisiert und priorisiert. Scrum weist diese Aufgabe dem ProductOwner zu. Oft spielen Vertrieb oder Marketing oder Geschäftsführung auch diese Rolle.

Die Softwareentwicklung transformiert die Anforderungen dann in Releases, die der Vertrieb an den Markt bringt. Der Markt steht mithin am Anfang und am Ende der Softwareproduktion. Er äußert Wünsche, die das Softwareunternehmen mit “Packerln” befriedigt. Nur wenn der “Packerl”-Inhalt den Wünschen entspricht, ist auf Verkauf zu rechnen.

Hört sich das plausibel an? Ich hoffe. Diese Prozessschritte scheinen mir minimal und konsensfähig. Auch wenn sie in einem Unternehmen nicht explizit besetzt sein sollten, gibt es sie doch immer in mehr oder weniger sichtbarer Form. Und nur das ist hier wichtig. Selbst in einem 1-Personen-Unternehmen, wo alles von einem getan wird, geht es nicht ohne. Da mögen Marktanalyse und Anforderungsdefinition zusammenfalle – stattfinden tun jedoch beide.

Und wo ist die Geschäftsführung, das Management? Was ist mit der Buchhaltung? Mir geht es nur um den Softwareproduktionsprozess. Die Buchhaltung ist dafür irrelevant; sie spielt eine parasitäre Rolle im Unternehmen, da in ihr keine Wertschöpfung erfolgt. Sie hat höchstens eine Relevanz durch ihren Einfluss auf das Management. Denn das hat qua Grundsatzentscheidungen Einfluss auf alle Rollen; das ist schließlich ihr tradioneller Job. Im Diagramm würde ich das durch eine Abhängigkeitsbeziehung kennzeichnen:

image

Wo Abhängigkeiten existieren, da droht natürlich die Gefahr von Grundsatzengpässen. Sie können wie Einschnürungen auf den abhängigen Produktionsschritt wirken. Organigramme, die darstellen, wer wem welche Ansagen machen kann, haben also ihren Wert. Sie können helfen, Grundsatzengpässe aufzudecken.

Wie sieht es nun mit den Engpässen im verfeinerten Diagramm aus?

  • Jetzt ist klarer, warum die Softwareentwicklung ein Engpass sein kann: Sie setzt Anforderungen, die in die hineinfließen einfach nicht schnell genug in Releases um, die der Vertrieb dann absetzen kann. Kommt Ihnen das bekannt vor? Symptom ist ein langes Backlog, für dessen Einträge nicht klar ist, ob und wann sie jemals umgesetzt werden – obwohl sie ja verdichtete und formalisierte Wünsche des Marktes darstellen, d.h. greifbares Potenzial für Umsatz.
  • Dass die Anforderungsdefinition ein Engpass ist, habe ich noch nicht gesehen. Ich kenne nur Softwareunternehmungen, die schnelle Anforderungen produzieren, als die Softwareentwicklung in Code transformieren kann.
  • Dasselbe gilt für die Marktanalyse; auch hier habe ich noch kein Projekt gesehen, dass darunter gelitten hätte, dass der Markt nicht mehr Wünsche pro Zeiteinheit gehabt hätte, als umgesetzt werden konnten.

Marktanalyse und Anforderungsdefinition scheinen also kein Problem zu sein. Die Softwareentwicklung ist und bleibt der Engpass. Als hätten Sie das nicht irgendwie schon vorher gewusst ;-)

Dennoch finde ich es wichtig, diese beiden Schritte eingeführt zu haben. Denn wie Sie dem vorherigen Artikel entnehmen können, kann ein System nur optimal funktionieren, wenn man die Optimierung auf dem Ganzen ausführt und nicht nur auf Teilen. Grundsatz #3 ist zu beachten: Downstream Bedarf bestimmt upstream Produktion in allen Teilen eines Prozesses.

Die Softwareentwicklung folgt Anforderungsdefinition und Marktanalyse, liegt also downstream. Das heißt, sie hat nach Grundsatz #3 Einfluss auf beide. Nur wie?

Ausbeutung mit Qualität

Bevor der Einfluss der Softwareentwicklung auf vorgelagerte Prozessschritte klar wird und der Produktionsprozess noch weiter verfeinert werden kann, wieder ein Ausflug ins Grundsätzliche der Theory of Constraints.

Am Ende meines vorherigen Artikels habe ich die Schritte zur Optimierung eines Systems auf sein Ziel hin genannt:

  1. Engpass identifizieren
  2. Engpass ausreizen (Grundsatz #5)
  3. Nicht-Engpass Prozessschritte am Engpass ausrichten (Grundsatz #3)
  4. Enpass erweitern (Grundsatz #5)
  5. Zurück zu 1.

Schritt 3 ist darin sozusagen der sichtbar “systemische” Schritt. Er widerspricht dem landläufigen Gedanken lokaler Optimierung. Denn hier kann es zum Abbau lokaler Optima führen, um ein Gesamtoptimum zu erzielen. Prozesschritte dürfen sich also nicht autistisch in sich kehren, sondern sollen das Ganze im Blick behalten – insbesondere ihr Verhältnis zum Engpass.

Vorher geht es jedoch darum, den Engpass bestmöglich auszunutzen. Das bedeutet, dass man ihn auf das fokussiert, was er leisten soll im Sinne des Ziels. Alles, womit sich der Engpass beschäftigen muss, das nicht der Produktion hochwertigen Ausstoßes dient, ist zu vermeiden. Engpässe sollten also von jeder Ablenkung freigehalten werden.

Eine häufige und ganz allgemeine Ablenkung ist nun Wiederbearbeitung (rework). Wenn ein Engpass schlechte Qualität ausstößt, kommt die irgendwann zu ihm zurück. Der Engpass muss seinen früheren Ausstoß dann nachbearbeiten. Das kostet Zeit, die ihm für die Produktion neuen Ausstoßes fehlt.

image

Ob mangelnde Qualität der Engpass-Ausstoßes direkt zu ihm zurückkommt oder dazu führt, dass vorgelagerte Prozessschritte auch kompensieren müssen, ist egal. Am Ende muss insbesondere der Engpass Zeit aufwenden für etwas eigentlich Erledigtes, statt etwas Neues zu produzieren.

Sie kennen das sicher: Sie haben viel zu tun, takten Ihre Aufgaben eng, um rechtzeitig mit allem fertig zu werden – Sie haben keine Zeit zu verschwenden! – und dann bekommen Sie das Feedback, dass Sie das Dokument, das Sie gestern abgegeben haben, nochmal überarbeiten müssen, weil es Qualitätsmängel enthält. Das passt Ihnen natürlich gar nicht in den Kram, weil sie keinen Spielraum haben; Sie können es sich nicht erlauben, etwas, das schon fertig war, nochmal anzufassen. Genauso ist es mit dem Engpass in einem Prozess. Der hat keinen Spielraum, der muss an der Kapazitätsgrenze performen, weil er alle anderen ja schon aufhält. Der kann sich also nicht erlauben, einen Fehler zu machen, um dadurch selbstverschuldet früher oder später nachbessern zu müssen. Nachbesserungen verdienen einfach kein Geld.

Selbst wenn der Engpass jedoch an sich fehlerfrei Input in Output transformiert, kann er mit Nachbesserungen belastet werden. Es gilt ja: Garbage in, garbage out. Wenn also der Input in den Engpass schon mangelhaft ist, kann der Engpass es nicht besser machen. Wenn die Qualität des Ausstoßes des vorgeschalteten Prozessschrittes suboptimal ist, dann wird der Engpass sogar womöglich doppelt unnütz belastet. Er befasst sich mit dem mangelhaften Input, bemerkt das aber nicht selbst, sondern transformiert ihn nach bestem Wissen und Gewissen – und dann verweigert ein nachgeschalteter Schritt die Weiterverarbeitung. Das führt dann zu einem erneuten Anlauf bei einem vorgeschalteten Schritt, so dass der Engpass erneut mit der Sache befasst ist.

image

Es ist also darauf zu achten, dass der Engpass nur mit Topqualität beliefert wird und selbst nur Topqualität ausstößt. Alles andere führt zu Wiederbearbeitungen, die den Engpass vom Wesentlichen ablenken.

Wenn Nicht-Engpass Prozessschritte mit solchem “Wiederkäuen” belastet werden, mag das nicht so schlimm sein. Sie haben wegen des Engpasses wahrscheinlich Überkapazitäten und können sich (gelegentliche) Nachbesserungen leisten. Der Engpass hat diesen Luxus nicht.

Und schließlich kann der Engpass zu Wiederbearbeitungen gezwungen werden, wenn seine Topqualität von downstream Prozessschritten zerstört wird. Als Pizzabäcker mögen Sie perfekt sein – wenn dann aber der Kellner die Pizza fallen lässt, war Ihre Arbeit umsonst. Sie müssen die Pizza nochmal backen, was andere Gäste auf Ihre Bestellungen ungeplant warten lässt.

image

Es ist also darauf zu achten, dass der Engpass nur mit Topqualität beliefert wird, selbst nur Topqualität ausstößt und downstream diese Topqualität nicht verlorengeht, so dass Nachbesserungen durch den Engpass fließen.

Den Engpass ausreizen bedeutet natürlich, dass er selbst wie geschmiert funktioniert. Darüber hinaus zwingt ein Engpass aber auch zum Blick auf Qualität. Sobald mangelnde Qualität upstream, downstream oder durch ihn selbst produziert zu Nachbesserungen führt, die durch den Engpass laufen, ist das im Widerspruch zur Forderung von Schritt 2 der Systemoptimierung.

Qualität ist kein Selbstzweck. Irgendwie haben Entscheider also doch Recht, wenn sie Entwickler skeptisch beäugen, die mit einem absoluten Qualitätsbewusstsein an der Entwicklung “rumschrauben” wollen.

Mit der Theory of Constraints bekommen Entscheider wie Entwickler allerdings ein Denkmodell an die Hand, das sie beurteilen lässt, wo qualitätssteigernde Maßnahmen Sinn ergeben. Eine simple Frage reicht aus: “Führt die Qualitätssteigerung zu einer Entlastung des Engpasses?” oder “Kann der Engpass sich anschließend mehr auf die Produktion von Neuem konzentrieren?”

Wenn diese Frage mit Ja beantwortet werden kann, dann sollte die Maßnahme ernsthaft in Betracht gezogen werden.

Umgekehrt kann natürlich auch nach lohnenden Veränderungsansatzpunkten gesucht werden. Ist ein Engpass bekannt, dann kann man fragen, wie die Qualität seines Ausstoßes erhöht werden kann, wie der Ausstoß des vorgelagerten Schrittes verbessert werden kann oder wie nachgelagerte Schritte die Qualität halten können.

Die Systemoptimierung fragt also zuerst nach dem Engpass, dann danach, wie der überhaupt zu voller Kapazität gebracht werden kann – und anschließend kommt die Qualität in den Blick. Im Kern der TOC schlägt ein Herz für hohe Qualität – weil Qualität sich im wahrsten Sinne des Wortes auszahlt. Und damit ist das hohe Qualitätsempfinden der meisten Entwickler an den Sinn fürs Geld ihrer Entscheider angebunden. Entwickeridealismus und Entscheiderpragmatismus stehen nicht so im Widerspruch, wie es oberflächlich den Anschein hat. Mit einem passenden und gemeinsamen Referenzsystem kommen Geld und Qualität überein.

Qualität im Softwareproduktionsprozess

Nach diesem Ausflug in die TOC-Grundlagen stellt sich natürlich umso mehr die Frage, wo Qualität im Softwareproduktionsprozess eine Rolle spielt. Bisher ist sie noch nicht explizit sichtbar. Ich schlage vor, zwei weitere Produktionsschritte ins Bild einzuführen, die mit Qualität zu tun haben:

image

Da ist zum einen der Support. Der befasst sich mit schlechter Qualität. Die Kundschaft meldet sich beim Support mit Problemen, die vom Support entweder selbst aufgeklärt werden können – oder als Issues weitergeleitet werden an die Softwareentwicklung. Solche Issues sind Abweichungen von der Anwendererwartung jeder Art, Bugs natürlich eingeschlossen.

Dadurch steht die Softwareentwicklung von zwei Seiten unter Produktionsdruck. Die Anforderungsdefinition schiebt ihr zu, was umgesetzt werden muss, um am Markt “Packerl” abzusetzen. Und der Support schiebt ihr Nachbesserungen zu. Der Support im Bild ist somit ein deutlich sichtbarer Ausdruck dessen, dass die Softwareentwicklung ganz verlässlich immer wieder Engpass ist. Solange Support nötig ist, der mit der Softwareentwicklung verbunden ist, stimmt also mit der Qualität der “Packerl” irgendetwas nicht.

Der Support ist in vielen Unternehmen wie eine Notbremse, die die Entwicklung jederzeit anhalten kann, um ein kundenlebenswichtiges Problem zu lösen. Das behindert die Softwareentwicklung dann doppelt, weil sie nicht nur eine Nachbesserung vornehmen muss, sondern auch aus ihrem Arbeitsfluss gerissen wird. Ein ruhiger, konzentrierter Arbeitsfluss ist aber wichtig, wenn die Softwareentwicklung als hochkreative Tätigkeit ihre Kapazität ausreizen können soll.

Support-Issues kommen aber natürlich nicht von ungefähr. Sie sind nur das Symptom für Qualitätsmängel in der Produktion von “Packerln”. Deshalb ist eine explizite Qualitätssicherung gerade im Engpass als Gegenmaßnahme selbstverständlich. Sie entspricht der Erkenntnis der TOC, dass der Engpass von sich aus höchste Qualität liefern sollte, um Nachbesserungen zu vermeiden.

Damit aber nicht genug! Qualität spielt lt. TOC auch noch an anderen Stellen eine Rolle. Auf hoher Abstraktionsebene ist die Softwareentwicklung der Engpass, d.h. Input und Output müssen hohe Qualität haben. Bei näherer Betrachtung ist dann jedoch die Programmierung innerhalb der Softwareentwicklung der wahre Engpass. Auch dort muss also schon die explizit Qualität in den Blick genommen werden.

image

Die Qualitätshebelpunkte im Einzelnen:

  • Anforderungsdefinition: Können Anforderungen überhaupt von mangelhafter Qualität sein? Natürlich. Denn “mangelhafte Qualität” bedeutet, dass am Engpass Nachbesserungen nötig sind bzw. es kein Geld einbringt, sie umzusetzen. Der Engpass hat dann weniger Zeit für neue, lukrative Anforderunge. Mangelhafte Anforderungen sind mithin solche…
    • …die unnötig sind (Stichwort YAGNI). Vorschläge sind nicht einfach in Anforderungen zu transformieren, sondern auf ihre Relevanz zu prüfen. Die Anforderungsdefinition muss ein Gespür dafür haben, was wichtig, was nötig, was nice-to-have ist. Priorisierung ist das Zauberwort. Und auch ablehnen darf die Anforderungsdefinition. Nicht jeder Räusper des Marktes muss umgesetzt werden.
    • …die unklar sind. Anforderungen müssen in Form und Granularität so formuliert sein, dass bei der Softwareentwicklung möglichst wenige Zweifel existieren, was gemeint ist. Anforderungen sollten schon gar nicht Formulierungen wie “irgendwie” oder “Das sollen die Entwickler entscheiden, die haben doch Erfahrung” enthalten.
      Markstein für Klarheit sind in jedem Fall Akzeptanzkriterien, d.h. Paare von Eingaben mit erwartetem Verhalten. Ohne eine Liste solcher Paare sollte die Softwareentwicklung nicht mit der Implementierung beginnen. Sie kann dann nämlich nicht für sich feststellen, ob die Qualität ihrer Arbeit hoch ist. Das aber ist die Voraussetzung dafür, als Prozessschritt mit anderen zusammenzuarbeiten. Qualität ist ja nicht subjektiv von jedem Prozessschritt selbst zu bestimmen, sondern hat auch etwas mit den Folgeschritten zu tun.
  • Support: Was vom Support kommt, ist immer eine Störung für die Softwareentwicklung. Deshalb sollte der Support besonders sensibel sein, Issues mit geringer Frequenz und hoher Qualität zu produzieren. Mangelhaft sind Issues, wenn…
    • …sie unklar sind und der Entwickler nicht genau weiß, was zu tun ist. Wie kann er das Problem reproduzieren? Wer hat es gemeldet (für Nachfragen)? Alles was die Bearbeitung eines Issue verlängert, ist zu vermeiden.
    • …im Grunde vom Support selbst geklärt werden könnten. Das sollte für alle Issues gelten, die keine Bugs sind. Was ein Anwender für einen Fehler hält, mag nur eine falsch verstandene Anforderung sein. Deshalb sollte der Support auch eigentlich gar nicht mit dem Engpass Softwareentwicklung direkt verbunden sein. Das obige Bild stellt also nur die häufige de facto Prozesskette dar, nicht eine wünschenswerte. Wünschenswert ist vielmehr, dass die Softwareentwicklung von der Außenwelt abgeschirmt ist. Nur dann kann ein ruhiger Fluss zur maximalen Ausnutzung des Engpasses entstehen. Hier der angepasste Produktionsfluss:

image

Die Verbindung des Support mit der Anforderungsdefinition macht nicht nur zur Entkopplung der Entwicklung Sinn, sondern passt auch dazu, dass über den Support immer wieder (potenzielle) Verbesserungsvorschläge hereinkommen. Die landen nach der obigen Prozessstruktur nun ebenfalls bei der Anforderungsdefinition, also da, wo sie hingehören.

  • Programmierung: Die Programmierung ist die zentrale Transformationsstelle. Sie ist das Herz des Unternehmens. Hier werden Anforderungen in Code gegossen; hier entstehen Softwarelösungen. Und leider ist die Programmierung auch der ewige Engpass. Das hat unabhängig von suboptimaler Anforderungsqualität mit vielen Faktoren zu tun, z.B. Komplexität der Materie Softwareentwicklung an sich, heterogene Ausbildung, mangelnde Plattformkenntnis, suboptimale Teamkommunikation oder schließlich auch Grundsatzengpässe aller Art.
    Den Engpass Programmierung maximal produktiv zu halten, ist also oberstes Gebot eines Softwareunternehmens. Alles andere ist Geldverschwendung. Das bedeutet aber auch, dass Produktivität unter Verzicht auf Qualität immer ein Phyrrussieg ist. Immer. Schlechte Qualität kommt immer zurück in Form von Nachbesserungen und verstopft den Engpass Programmierung. Das gilt für Bugs wie für fehlende Usability. Die Programmierung muss deshalb sehr sensibel sein für die Qualität ihrer eigenen Arbeit. Weniger als top Qualität (nach bestem Wissen und Gewissen der Programmierer) ist also zuwenig.
    • Automatisierte Tests (insb. zur Vermeidung von Regressionsfehlern) sind also ein Muss für den Engpass Programmierung. Nur so kann die Kapazität mittel- bis langfristig für Neues eingesetzt werden, statt für Nachbesserungen.
    • Reviews am Ende der Programmierung sind ebenfalls ein unverzichtbares Mittel, um vor Übergabe des Codes nochmal die Qualität zu checken. Alles was die Programmierung verlässt und später wiederkommt bereitet ungeplanten Mehraufwand, der von der eigentlichen Arbeit ablenkt.
    • Ähnlich verhält es sich mit der Usability. Wird auf die kein Wert gelegt, fällt Zusatzaufwand für die Anwenderdokumentation an und Issues vom Support tauchen früher oder später als Sand im Getriebe auf.
    • Sensibilität ist aber auch gegenüber den Anforderungen angebracht. Was klar ist, sollte pünktlich erfüllt werden. Was unklar ist, sollte vor Arbeitsaufnahme geklärt oder abgelehnt werden. Hier ist das größte Risiko, dass die Programmierung sich überschätzt. “Das kriegen wie schon irgendwie hin…” oder “Unsere Erfahrung sagt, dass der Kunde es bestimmt so und so haben will…” sind Symptome dafür.
  • Qualitätssicherung: Hohe Qualität als Output der Softwareentwicklung ist so wichtig, dass der Programmierung ihre Prüfung nicht allein überlassen werden kann. Grundsatzengpässe, die auf die Programmierung wirken und simple psychologische Mechanismen machen es wahrscheinlich, dass selbst sorgfältig testenden Programmierern Qualitätsmängel durch die Lappen gehen. Also ist eine explizite nachgeschaltete Qualitätssicherung wichtig, die ausdrücklich die Kunden-/Anwenderbrille auf hat. Spätestens hier sind die Akzeptanzkriterien aus den Anforderungen zu überprüfen. Sie macht aus dem, was die Programmierung für ein Release hält (Release Candidate) wirklich ein Release, das der Vertrieb zu einem “Packerl” schnüren kann.

Zwischenfazit

Die Grundstuktur eines Softwareproduktionsprozesses ist nicht kompliziert. Dennoch ist sie wertvoll im Verein mit der Theory of Constraints. Denn selbst an der simplen Struktur lässt sich schon ablesen, wo Investitionen lohnen und wichtig sind.

Testautomatisierung ist keine spinnerte Idee, sondern eine Maßnahme, um den Engpass Programmierung auszureizen. Dasselbe gilt für Versionskontrolle, automatisierten Buildprozess und andere Bausteine von Clean Code Developer. Sie alle zielen darauf ab, Programmierer zu entlasten, um den Kopf frei für das Wesentliche zu bekommen.

Ob ein Release von Hand oder mit einem Werkzeug hergestellt wird, interessiert den Kunden nicht. Da hat der Entscheider recht. Unrecht hat er aber, wenn er meint, deshalb sollte auf solch neumodischen Kram verzichtet werden. Denn was den Kunden interessiert, das ist die Zeit, die der Engpass Programmierung in die Herstellung neuer (!) Features steckt. Und die sinkt, wann immer Nachbesserungen oder manuelle Tätigkeiten nötig sind.

Insofern liegt der Wert in automatisierten Tests (Unit Tests, Integrationstests) nicht darin, dass sie bei der Erstentwicklung eines Feature laufen. Bei der Erstentwicklung sind manuelle Tests womöglich schneller. Automatisierte Tests entfalten Ihren Wert vor allem als Regressionstests. Sie werden nämlich immer vor Release ausgeführt. Das ist mit manuellen Tests nicht möglich. Automatisierte Tests sind ewige Sicherungsseile für die Qualität. Die beschränkt sich mit ihnen nicht darauf, was für ein Release an manuellen Tests möglich ist – denn das wird im Verhältnis zur Gesamtfunktionalität immer weniger –, sondern deckt die Gesamtfunktionalität ab. Ob ein Programmierer nun überblickt, das er durch eine Veränderung “alte” Funktionalität nicht beeinflusst hat oder nicht, ist mit automatisierten Regressionstests unerheblich. Das ist ultimativ entlastend für die Programmierung.

Eine Begründung von CCD durch die Theory of Constraints? Das ist ein schönes Zwischenergebnis, finde ich.

Beim nächsten Mal geht es weiter mit einer Detaillierung der Programmierung.