Primus inter pares

Es gibt diesen einen Test. Diesen Test, der die Story – genauer: das Szenario – in die Sprache der Applikation übersetzt. Und ich suche nach einem Namen. Wenn die Story mit den Szenarien die Akzeptanzkriterien ausdrückt. Und wenn ein Akzeptanztest diese Kriterien in die Sprache der Applikation übersetzen, dann handelt es sich bei diesem einen Test, um den der den Akzeptanztest als Unittest implementiert.
Akzeptanztests können auf ganz unterschiedliche Weise implementiert sein. Es mag sich um Test mit Hilfe eines Akzeptanztest-Frameworks handeln, wie bspw. Fitness, Fit oder Cucumber. Es mag sich um einen Test handeln, der über das Userinterface auf die Anwendung zugreift, wie bspw. Seleniumtests die Webschnittstelle adressieren. Oder es kann sich um Akzeptanztests handeln, die ein Unittestframework nutzen um ausgedrückt zu werden. In jedem dieser Fälle ist es wichtig, dass der Test die gesamte Anwendung testet, dass der Test anzeigt, ob die Funktionalität in der angezielten Weise implementiert ist oder nicht.
Unittest übernehmen eine andere Aufgabe. Sie zeigen auf, dass diese Klasse oder diese Gruppe von eng kollaborierenden Klassen eine bestimmte Funktion erfüllt. Um den gleichen Umfang wie der Akzeptanztest abzudecken, ist eine ganze Kette von Unittests notwendig. Und unter diesen ist der oberste, derjenige der die Story in die Sprache der Applikation (eben auch in die Programmiersprache) übersetzt, der erste unter gleichen – primus inter pares.
Wenn die Akzeptanztests in der Sprache der Anwendung geschrieben sind, ist der Unittest in gewissem Sinne mit dem Akzeptanztest identisch. Sein Setup ist ein anderes, er legt Wert darauf die Funktionalität an einer Klasse in Isolation zu testen, aber die Schnittstelle, die er benutzt, sollte die gleiche sein. [Wenn das nicht so ist, weil die Story bspw. gar keinen spezifischen Ort in der Applikation hat, ließe sich von einem Code Smell sprechen. Aber das - der Ort einer Story in der Applikation (UseCaseController, Manager, anämisches Objektmodell) - ist Thema für eine andere Gelegenheit.]
Die Rolle des Ersten unter den Unittests ist in unserem Coding-Dojo aufgetaucht. Immer wenn wir diesen Test nicht hatten, verloren sich Entwicklungen in tieferen Schichten der Applikation im Spekulativen, wenn er da war, gab er den anderen eine Richtung vor. Wir haben das zunächst als Primat des Top-Down-Ansatzes verhandelt. Erst mit dem Gedanken des Top-Down-Ansatzes wurde im Dojo explizit, dass es sich besser anfühlt, wenn man die Frage beantwortet hat, welches ist die zentrale Einstiegsfunktion für die Story und wie sehen die Tests für diesen Einstiegspunkt aus. Aber – und deshalb wiederstrebt es mir hier von einem Top-Down-Ansatz zu sprechen – wenn der oberste Unittest erst einmal gefunden ist, ist es auch möglich in unteren Schichten der Applikation zu beginnen, ohne sich zu verlieren. Der oberste Unittest gibt der Implementierung eine Richtung, auch wenn diese syntaktische und programmatisch noch nicht in allen Ebenen und Schichten explizit ist. In einer anderen Sprache und einem anderen Land könnte man vielleicht von Führung und einem führenden Test sprechen, aber bei uns?

Kanban, Scrum und die Frage des Übergangs

Es gibt Beispiele, die sind komplizierter als das, was sie illustrieren sollen. Aber irgendwie – und dieses irgendwie muss man groß schreiben – IRGENDWIE veranschaulichen sie einen Aspekt so überdeutlich, dass sie doch wichtig sind.
So geht es mir mit der Frage des Übergangs. Ich habe einmal in einer Veranstaltung gesessen, ich weiß heute nicht mehr wie ich dahin kam, in der es um die Entstehung der 12-Ton-Musik ausgehend vom späten Bruckner ging. Ich verstehe eigentlich nichts von Musik, ich kann mit der 12-Ton Musik Schönbergs, wenn ich sie höre, nichts anfangen, und ich kenne kein einziges Werk des späten Bruckner mit Namen, aber die Veranstaltung beschrieb ein Muster so plastisch und anschaulich, dass ich fasziniert war.
Musikstücke – jetzt sollte jeder Nichtlaie weghören – haben eine Tonart. Ich kann mir das am einfachsten am Klavier vorstellen. Die 8 weißen Tasten angefangen beim C bilden die Grundtöne der Tonart C-Dur. Die Abstände der Tasten beim Klavier – egal ob weiß-weiß oder weiß-schwarz – bestehen aus einem Halbton. Da nicht zwischen allen weißen Tasten eine schwarze ist, gibt es weiße Tasten, die einen halben Ton und weiße Tasten, die einen ganzen Ton auseinander liegen. Wenn ich beim C anfange und nur die weißen Tasten drücke, habe ich eine Tonleiter, die klingt. Dabei habe ich zwei Ganztonsprünge, einen Halbtonsprung, dann wieder drei Ganztonsprünge und einen Halbtonsprung. Diese Reihe (1-1-0,5-1-1-1-0,5) kann ich jetzt bei jedem Ton starten. Wenn ich z.B. beim G beginne habe ich die G-Dur-Tonleiter. Ich muss in den Tonarten entsprechend viele schwarze Tasten drücken, um auf meinen Grundtönen zu bleiben. Was bleibt sind immer die Abstände der Töne in der Grundtonleiter.
Wo war ich? Ach ja! Musikstücke haben eine Tonart. Diese ist am Anfang eines Stückes markiert. Ich lege damit fest, welche acht Tasten ich drücke darf. Wenn ich nun der Meinung bin, ich brauche mal einen anderen Ton, der jetzt eigentlich nicht erlaubt ist, kann ich diesen einzelnen Ton mit einem Vorzeichen versehen und darf außer der Reihe drücken. Der Vortrag, von dem ich erzählen wollte, beschäftigte sich mit der Musik des ausgehenden 19. und beginnenden 20. Jahrhunderts, insbesondere mit der Musik Anton Bruckners. Es hieß im Spätwerk Bruckners würde eine schwebende Tonalität herrschen. Das meinte, die Stücke hätten zwar eine Tonart – ganz am Anfang des Stücks wäre eine notiert – es gäbe aber so viele Vorzeichen an einzelnen Noten im Stück, dass diese Tonart kaum noch zu erkennen sei – eben schwebend. Bruckner hätte mit den Mitteln der klassischen Tonalität das ausgereizt, was sich komponieren liesse, wenn man den Begriff der Tonart nicht aufgeben wolle. Den nächsten Schritt, ob das musikhistorisch überhaupt Sinn macht kann ich nicht beurteilen, stellte die 12-Ton-Musik Arnold Schönbergs dar. Schönberg ‘befreite’ die Musik vom Korsett der Tonalität. Er schuf eine Musik, die alle Tasten (12) gleichberechtigt nebeneinander stellte. Damit wäre es leicht gewesen, die Musik zu notieren, die der späte Bruckner komponiert habe. Mit der Befreiung von der Tonalität entstanden ganz neue Möglichkeiten von Musik, die neue Notation eröffnete Felder, die im Kontext der alten Notation nur als Randgebiete sichtbar waren.
Mich faszinierte an dem Vortrag das Muster, welches überdeutlich wurde. Das Neue – Schönbergs 12-Ton-Musik – was keine Erfindung, mit der man dann neue Sachen machen konnte. Im Gegenteil. Das Alte, die klassische Form der Musik hatte sich an eine Stelle entwickelt, an der ihr formales Gerüst bis an ihre Grenzen belastet wurde, an eine Stelle, an der sich die Sinnhaftigkeit dieser formalen Struktur stellte. Das Neue befreite nur den schon vorhandenen neuen Inhalt aus der alten Form und ließ ihm Raum sich weiter zu entwickeln.
Ich denke dass es sich mit vielen neuen Dingen so verhält, das sie auf dem Boden des alten entstehen, dieses bis an die Grenzen des Sinnhaften beanspruchen und so den Übergang zu etwas Neuem – nicht nur vorbereiten -, sondern erzwingen.
Wer zum Beipiel den Text von Winston Royce ‘Managing the Development of Large Software Systems’ liest, der gemeinhin als Manifest des Wasserfallmodells gilt, wird finden, dass dieser Aufsatz im Gegenteil sehr viele Anmerkungen zum Wasserfallmodell macht, die in Richtung einer agilen Sofwareentwicklung weisen. Mehr Agilität geht im Modell des Wasserfalls wahrscheinlich gar nicht. (Ich habe versucht das hier auszuführen.)
Etwas ähnliches scheint sich im Moment im Bereich Scrum/Kanban zu vollziehen. Wir setzen auf der Arbeit in unseren Projekten Taskboards ein. Die genaue Gestalt variiert von Team zu Team, aber ein Taskboard haben fast alle. Wenn ich mir die Boards der Projekte anschauen, die Tagesbetrieb/Wartung und Kleinprojekte machen, dann haben die nie den Charakter eines Scrum-Taskboards. (Ein echtes Scrum-Taskboard: Am Anfang der Iteration sind alle Karten links und am Ende rechts.) In den Tagesbetriebsprojekten führt es dazu, dass die Wochenplanungen immer wichtiger werden als die Releasemeetings, sofern es sie für das ganze Projekt noch gibt. Und es führt dazu, dass das Team das Gefühl hat, etwas falsch zu machen. ‘Eigentlich muss das doch anders gehen.’ Das Werkzeug ‘Prozess’ verwandelt sich in ein Korsett. Die Stellschrauben, die Scrum einführt, greifen in diesen Projekten nicht wirklich. Das Messen der Geschwindigkeit funktioniert nicht wirklich, weil sehr viele Aufgaben als dringende während des Sprints dazukommen. Das widerspricht zwar dem Gedanken des Sprints ist aber in Wartungsprojekten unerläßlich. Natürlich gibt es Workarounds: rote Karten, die nicht mitgemessen werden oder Puffer, die von vornherein für Wartung und Bugfixing reserviert werden. Es ist aber nicht sehr befriedigend einen großen Teil der Arbeit während eines Sprints nicht in die Messung einzubeziehen.
Die Kanban-Diskussion hat den befreienden Effekt, dass sie die Diskussion in eine andere Richtung lenkt. Es heisst nicht mehr Scrum Ja oder Nein, sondern es werden Instrumente sichtbar, mit denen man einen Prozess gestalten kann, der in einem Umfeld stattfindet, das keine feste Timebox mehr erlaubt. Die Diskussion um Kanban zeigt bspw. wie man den Durchsatz messen kann, wenn es einem nicht möglich ist die Geschwindigkeit im klassischen Sinne zu messen. Mit Beschränkungen der Warteschlangengrößen wird eine Stellgröße sichtbar, die der klassische Scrumprozess nicht kannte und auch nicht brauchte, da er in einem andern Umfeld zu hause ist. Insofern habe ich dass Gefühl Kanban ist das Neue, was auf dem Boden des Alten entstanden ist. Jetzt gilt es allerdings nicht mehr die Diskussion Alt gegen Neu zu führen, sondern auszuprobieren, wie sich die Instrumente, auf die Kanban die Aufmerksamkeit lenkt, einsetzen und erweitern lassen. Die Beipiele, die ich bisher in den verbreiteten Präsentationen gesehen habe – vor allem Verklemmungen beim Deployment – haben etwas Triviales, man hat den Eindruck, hier hätte nicht Kanban, sondern etwas gesunder Menschenverstand genügt.

Leanproduction und das Eintüten eines Briefes

Die MIT-Studie über die zweite Revolution in der Automobilindustrie unterscheidet drei Weisen der Produktion. Die fordistische, amerikanische Massenproduktionsweise, die japanische Produktionsweise und die skandinavische Manufakturproduktionsweise. Da es einige Beispiele dafür gibt, Produktionsweisen am Beispiel des Eintütens von Briefen zu verdeutlichen, will ich in diesem Bild bleiben und versuchen den Unterschied der drei Weisen zu verdeutlichen.

Die Aufgabe besteht darin, 100 Briefe mit 100 DIN A4-Blättern zu füllen, die Umschläge zu zu kleben und diese mit 100 Briefmarken zu frankieren. Die erste – auch historisch erste – Form das Problem zu erledigen, die Manufakturproduktion, besteht darin, alle Briefe einzeln zu bearbeiten. Arbeiter 1 nimmt sich einen Brief, versieht ihn mit Inhalt, klebt ihn zu und frankiert ihn. Wären mehrere Arbeiter zugange, würde sie ebenfalls diese Tätigkeit ausführen. Jeder macht das gleiche. Der Arbeitsprozess zerfällt nicht in seine Bestandteile, jede Arbeitskraft vollzieht ihn ganz.

Die zweite Form das Problem zu lösen, die fordistische Produktionsweise, besteht darin, den Prozess zu zerlegen und ihn durch ein Medium wie das Fließband wieder zusammen zu setzen. Arbeiter 1 füllt die Briefe und gibt sie weiter. Arbeiter 2 klebt die Briefe zu und gibt sie weiter. Arbeiter 3 frankiert sie und legt sie auf den Stapel der fertigen Briefe. Jede Arbeitskraft vollzieht nur noch einen Teil der gesamten Arbeit. Weil die Arbeiten  unterschiedlich lange dauern, werden zwischen den unterschiedlichen Stationen Puffer aufgebaut und die Stationen werden skaliert. Es gibt drei Tütenkleber, zwei Frankierer und einen Füller. Jede Station wird optimiert. Möglichst schnell füllen, möglichst schnell frankieren und möglichst schnell kleben. Diese zweite Form der Produktion verdrängte historisch in vielen Bereichen die Manufakturproduktion und wurde als industrielle Produktionsweise bekannt.

Die Manufakturproduktionsweise wird in den Bereichen geschätzt, in denen Qualität wichtig ist. So gab es – vom MIT in der Studie untersucht – in der skandinavischen Automobilindustrie Versuche die Manufakturarbeitsweise unter industriellen Bedingungen wieder zu beleben. Man setzte bspw. ein Team auf das Fließband, ließ es an allen Stationen vorbeifahren und ein Auto als Ganzes montieren.

Die dritte Form der Produktion – die toyotistische Massenproduktion – trat historisch auf den Plan, als die zweite, Fließband, Industrie, über die erste, Manufaktur, gesiegt hatte. Wie wird hier der Brief eingetütet. Der Grundgedanke ist: Arbeitsteilung wie in der Industrie, Arbeitsfluss wie in der Manufaktur. Was meint das? Wenn ich mich kurz in einen Brief verwandle, dann fühlt sich die erste Arbeitsweise so an, dass ich in einem Fluss gefüllt, verklebt und frankiert werde. Bei der zweiten Weise werde ich gefüllt und muss warten, werde verklebt und muss warten, werde frankiert und bin fertig. Bei der toyotistischen Arbeitsweise -besser: ihrem Ideal – fühlt es sich wieder so an wie in der ersten, ich werde in einem Rutsch gefüllt, verklebt, frankiert. Und das obwohl Arbeitsteilung herrscht und die füllenden, klebenden und frankierenden Hände unterschiedliche sind. Man nennt das ‘Single Piece Flow’. Die Kunst bei der dritten Weise der Produktion ist es also die Vorteile der zweiten Weise beizubehalten, aber ihre Nachteile, Warteschlangen, Verschwendungen, die den Prozess stocken lassen, zu überwinden. Single Piece Flow ist dabei ein Maßstab um den Prozess zu verbessern. Es ist kein Ideal in sich selbst. Gemessen am Single Piece Flow werden die Verschwendungen des Prozesses sichtbar und es kann an seiner Verbesserung gearbeitet werden. Hätte das Ideal einen Wert in sich, wäre es eine mögliche Option, zur alten Weise der Produktion – zur Manufaktur - zurückzukehren, doch diese Option besteht leider (?) nicht.

Der Tod des Navigators

Wir machen auf der Arbeit regelmäßig ein Coding-Dojo: vier Leute, drei Monate, zwei mal in der Woche anderhalb Stunden, eine Aufgabe, rotierendes Pairprogramming am Beamer. Die Frage nach der Rolle des Navigators, des Beifahrers, beim Pair Programming hat uns dabei schon öfter beschäftigt. Wir rotieren alle 5 Minuten (btw: Minuteur ist ein wuenderbares Tools um das auf dem Mac zu steuern). In der Literatur, in Vorträgen findet sich ein gängiges Muster: Der Fahrer sei zuständig für die taktischen Fragen, der Navigator für die Strategie. Den Fahrer kümmere die Syntax, den Navigator der große Plan, die Route. Obwohl diese Beschreibung sich durchgängig findet, hat das Beschriebene bei uns einfach nicht funktioniert. Das mag  verschiedene Gründe haben: falsch angewendet, unerfahren, unqualifiziert, zu wenig Disziplin, eine falsche Vorstellung davon wie es auszusehen hat.

Und nun sind wir auf zwei Studien gestoßen: Pair Programming an the Mysterious Role of the Navigator und The Social Dynamics of Pair Programming. Beide untersuchen die Frage der Kommunikation beim Pair Programming empirisch. Und beide Studien kommen zu dem Ergebnis, dass es die Rollenaufteilung in Navigator und Fahrer nicht gibt. Die Anteile beider Rollen an verschiedenen Ebenen der Betrachtung des Programms sind gleichverteilt. Es gibt keinen Unterschied in dem, was ich betrachte – und dann auch verbalisiere -, der sich aus meiner Rolle ableiten läßt. Und dass obwohl die Beteiligten selber ihre Rollen vor dem Experiment als Fahrer und Navigator beschrieben und der Meinung waren, so funktioniere ihr Pairing. Wenn die Rolle des Navigators als permanentem Code Reviewer oder als Steuermann eine Chimäre ist, was kennzeichnet denn dann das Gespräch zwischen den beiden? Die Rollen seien zumindest nicht sehr unterschiedlich, sehe man einmal vom trivialen Umstand ab, dass der eine die Tastatur hat und der andere nicht. Das Gespräch spiele sich eher auf einer Ebene von ‘abstract chunks of code’ ab. Damit seien Fragen von Namensstandards, Fragen allgemeiner Programmierstrategien, Umsetzungen von Programmstrategien im konkreten Programm gemeint. Der Bereich – so die eine Studie – der ‘abstract chunks of code’ sei der Vermittlungsbereich zwischen der Diskussion über konkrete Methode, Variablen und Syntax auf der einen und Fachdomänen bzw. der Übersetzung von Fachdomänenfragen ins Programm auf der anderen Seite. Pair Programming sei am effektivsten, wenn beide Teilnehmer ständig beide Rollen ausfüllten.

Einen wirklichen Unterschied sieht die eine Studie, wenn erfahrene mit unerfahreneren Programmierern pairen. Bei einem grossen Unterschied werde der unerfahrene Programmierer passiv. Diese Passivität führe dazu, dass er nicht mehr wirklich handle, sondern mehr zuschaue, und nicht mehr viel lerne. Pair Programming eigne sich nicht für den Wissenstransfer bei grossen Unterschieden in der Erfahrung oder Qualifikation. Die eine Studie schliesst eine Beobachtung an, die sie nicht mehr verifiziert, weil sie beendet wurde. Neu ins Team gekommene Programmierer, hätten nicht so viele Probleme die Erfahrenen zu unterbrechen, sie würden nicht so schnell passiv werden, das könne ein Indiz sein, dass bei ihnen der Transfer auch bei einem grossen Wissensunterschied noch funktioniere.

Die Lektüre der zwei Studien wirkte sich befreiend aus. Vorher hatte ich das Gefühl, unsere Betrachtungen müssten in die Richtung eigener Unzulänglichkeiten gehen, warum machen wir das noch nicht richtig. Danach würde ich sagen, die Frage, wie Pair Programming zu lehren uns zu kultivieren sei ist wieder offen oder aber schon beantwortet, weil man sich eben so verständigt, wie man sich verständigt: auf der mittleren Ebene und gleichberechtigt.

Sinn und Grenzen eines Fluent Interfaces

Auf der JAOO hatte ich das Glück ein Tutorial zum  Thema domänenspezifische Sprachen (Domain Spezific Language – DSL) besuchen zu können. Interessant war es, die verschiedenen Elemente des Themas einmal in einen Zusammenhang gebracht zu bekommen. Und wie immer, wenn Martin Fowler etwas darstellt, bekommt man ein paar neue Begriffe beigebracht, die es erlauben das bisher Gesehene und Gefühlte besser zu benennen und in einen systematischen Zusammenhang zu stellen.

Fluent Interfaces sind eine Form einer DSL, genauer einer internen DSL, genauer: sie sind ein syntaktisches Mittel eine interne DSL zu realisieren. Und Fluent Interfaces sind angesagt. Ich habe gesehen wie in einigen Projekten mithilfe eines Fluent Interfaces ein Bereich modelliert wurde. Mein Arbeitsfeld ist der eCommerce und so sind es oftmals Regeln, die den Checkout-(Bezahl-)Prozess steuern, die so modelliert werden. Ich kenne diese Form des Interfaces aber auch aus Konvertern, die eine Form von Daten in eine andere übersetzen. Bisher, vor dem Tutorial, hatte ich ein ungutes Gefühl, wenn ich die Beschreibung der Regeln in einem Fluent Interface sah und die Implementierung der Regeln mit der Interpretation der internen DSL verbunden war. Seitdem, seit dem Tutorial, kann ich das etwas genauer beschreiben. DSLs seien, so Fowler, dafür da ein Semantisches Modell zu instantiieren. Das Sematische Modell modelliere den Gegenstandsbereich. Es sei kein Domänenmodell, weil auch Bereiche, die nicht zur Domäne gehörten, mit einer DSL modelliert werden könnten. (Insofern sei aber jedes Domänenmodell ein Semantisches Modell.) Nehmen wir das Beispiel des Regelwerks für einen Checkoutprozess. Ich brauche ein Sematisches Modell, das meine Regeln, meine Lieferzeiten, meine Bezahlarten modelliert. Dieses Modell ist als solches testbar. Um jetzt für einen konkreten Shop ein spezifisches Regelwerk zu instantiieren, benutze ich eine DSL. Die kann ich ebenfalls separat testen. Der Test besteht darin, zu kontrollieren ob eine bestimmte Beschreibung eine bestimmte Form des Regelwerkes instantiiert. Der Test ist vollständig entkoppelt vom Test der Funktion des Regelwerks. Das entscheidende in diesem Zusammenhang ist das Sematische Modell. Es ist substantiell, dass hier der Bereich, der abgebildet werden soll, möglichst explizit modelliert ist. Ich kenne Implementierungen, die die DSL nutzen um eine sehr allgemeine Datenstruktur zu befüllen, bspw. einen Hash, und diese dann in entsprechend imperativen Code nutzen. Hier ist die DSL eher kontraproduktiv, weil sie verdeckt, dass die Domäne nicht wirklich modelliert wurde. Durch die DSL entsteht der Eindruck, es gäbe die Konstrukte, die die Domäne abbilden.

Der Sinn einer DSL lässt sich, Fowler folgend, auch so beschreiben: Anstatt das Command/Query-API des Sematischen Modells zu benutzen, wird eine Fluent Interface eingesetzt, um das Modell zu popularisieren.Das Semantische Modell stellt ein alternatives Berechnungsmodell dar – bspw. ein Regelwerk. Wird das Command/Query-API dieses Modells benutzt, ist das alternative Programm – implizit in der Instantiierung des konkreten Regelwerks enthalten – unsichtbar. Die DSL erlaubt es das alternative Programm als solches sichtbar zu machen.

(Fussnote: Wer mit einer internen DSL programmiert hat oftmals das Gefühl einem deklarativeren Programmierstil zu folgen. Das liegt nicht daran, dass DSLs per se einem deklarativeren Programmierstil folgen, sondern daran dass ein Semantisches Modell instantiiert wird, welches ein regelorientiertes Paradigma ausdrückt.)

Ein ganz kleines Beispiel: Mocha, die Ruby-Mock-Library, mit einem fiktiven Command/Query-API. Hier wird ein Mock programmiert.

# Command/Query-API
object = mock()
expectation = object.create_expectation()
expectation.set_method_name(:expected_method)
expectation.set_parameters([:p1, :p2])
expectation.set_return_value(:result)

Das Gleiche als interne DSL (mit Original-Mocha-Syntax)

# Fluent Interface
object = mock()
object.expects(:expected_method).with(:p1, :p2).returns(:result)

Im zweiten Fall ist die Programmierung des Mocks deutlich zu erkennen. Seine Programmierung nähert sich dem programmierten Methodenaufruf an. Im ersten Fall muss ich mir den zu erwartenden Methodenaufruf beim Lesen im Kopf zusammensetzen.

(Fussnote: Der Begriff Command/Query-API meint ein sinnvolles Prinzip für die Konstruktuion von Objekten. Eine Methode sollte entweder eine Query sein, das bedeutet, sie liefert einen Wert zurück und ändert den Zustand des Objektes nicht, oder ein Command, was bedeutet, dass die Methode eine Zustandveränderung des Objektes bewirkt, aber keinen Wert zurückliefert (Javasprech: void). Ein Fluent Interface gegen die Unterscheidung, weil es in der Regel den Zustand eines Objektes verändert und das Objekt zurückliefert, damit solche Methodenketten wie oben möglich werden.)

Platzen oder Lean & Zen

Ich habe manchmal das Gefühl, ich platze gleich, wenn ich eine Idee nicht loswerde, wenn ich nicht über etwas reden kann, was mich gerade bewegt.

Ich bin im Moment in Arhus und habe an der JAOO teilgenommen. Die ersten Tage waren so lala. Das mag an mir liegen. Ich hatte mir vor allem Talks ausgesucht, bei denen ich schon etwas von den Sprechern gelesen hatte. Ich wollte sie gerne mal live sehen und als Mensch erleben. In der Regel finde ich das sehr spannend, weil mein Bild von dem, was sie schreiben, sich präzisiert. (So ist es mir bspw. auch mit der Stimme von Stefan Tilkov gegangen, seitdem ich ihn beim heise-Developer-Podcast gehört habe, lese ich seinen Blog ganz anders.) Nun denn – ich habe die Leute jetzt gesehen, habe ein präziseres Bild von ihnen, aber was sie gesagt haben, hat micht nicht überrascht, wie auch, wenn ich vorher schon ein paar ihrer Gedanken kannte. Ich war ein wenig enttäuscht.

Aber heute hat sich das geändert. Ich habe einen Talk von Richard Durnell gehört und war – wie sagt man? – begeistert, angefixt, inspiriert. Es mag sein, dass der Talk gar nicht so besonders war, ich bin sicher derjenige, der das am schlechtesten sagen kann, aber in dem Talk fiel ein Gedanke, der für mich genau richtig war. Nicht zu klein, nicht zu gross, genau passend um etwas auszulösen, was sich wohl irgendwie angestaut hatte. Für alle anderen, die diesen Stau nicht haben, ist der Gedanke vielleicht banal, aber hier ist er. Richard hat 5 Jahre lang mit Leuten von Toyota daran gearbeitet ene Fordfabrik auf Leanproduction umzustellen. Er verglich das Lean-Denken mit dem Zen und dem was dort ‘Beginners Mind’ heisst. Er beschrieb, wie sein Mentor, immer wenn er dachte ‘jetzt habe ich es verstanden’, etwas tat oder sagte, was seinem bisherigen Verständnis zuwieder lief. Ganz ähnlich dem Zenmeister, der in unzähligen Geschichten immer wieder den Schüler verblüfft.

Ich hatte mit dem Lean-Ansatz bisher gewisse Schwierigkeiten. Ich fand die einzelnen Ideen spannend, hatte aber dabei die Frage im Hinterkopf: ‘Was ist denn nun Lean’. Nicht dass es da keine Definitionsversuche gibt, aber irgendwie wirken sie alle etwas untersetzt. Nach dem Talk denke ich, es ist gerade das Wesen von Lean, dass es keinen Kern hat. Es ist gerade mein Problem, dass ich immer versuche, die Idee zu strukturieren, in eine tayloristische Form zu bringen. Dem sperrt sich Lean und das ist seine Essenz. Richard schloss seinen Vortrag mit einem Zitat von Konosuke Matsushita (Matsushita Electrics aka Panasonics, Technics).

“We are going to win and the industrial west is going to lose: there’s nothing much you can do about it, because the reasons for your failure are within yourselves. Your firms are built on the Taylor model; even worse, so are your heads….”

Ja das verdammte westliche Tayloristische Hirn.

Das schöne an einem Blog ist, dass man das, was einen zum Platzen bringt, einfach aufschreiben kann und egal ob es einer liest oder nicht, der Druck verringert sich.

El-Oh-De revisited

Einmal im halben Jahr komme ich an Dan Mangles’ Blogeintrag über Missverständniss des Gesetz von Demeter vorbei. Und meistens – das scheint eine Eigenart von mir zu sein – lese ich ihn nochmal. So auch vor ein paar Tagen. Und auch dieses Mal habe ich das Gefühl ihn bisher noch nicht richtig gelesen zu haben.

Der Inhalt ist eine nette kleine Geschichte – weniger: ein Geschichtsfragment -, das von einem Kunden, einem Zeitungsjungen und einer Brieftasche handelt. Zunächst wird die Geschichte in Form der naivsten Implementierung (die Geschichte ist eigentlich nur Ruby-Code) erzählt. Der Zeitungsjunge bekommt die Brieftasche des Kunden und nimmt sich selbst das Geld für die Zeitung. Da niemand freiwillig dem Zeitungsjungen seine Brieftasche gibt, wird das Gesetz von Demeter (‘Sprich nicht mit Fremden’) (oder technisch: ‘keine Aufrufe mit mehr als einem Punkt’) eingeführt und die Geschichte wird noch einmal erzählt, jetzt wird die Brieftasche aber nicht aus der Hand gegeben.

Dan Mangles untersucht die Richtung der Delegation der Aufrufe – und das ist mir erst dieses Mal so richtig aufgefallen. Bei der Datendelegation ist die Richtung genau umgekehrt zur Verhaltensdelegation. Datendelegation: Der Zeitungsjunge bekommt den Kunden und nimmt sich vom Kunden die Brieftasche. Der Zeitungsjunge hat also die Brieftasche in der Hand. Bei der Verhaltensdelegations sagt der Zeitungsjunge dem Kunden ‘bezahl’ und der Kunde sagt der Brieftasche ‘Geld her’. Es ist nicht das Datum (Brieftasche) was nach außen, sondern das Verhalten (‘Bezahl’) was als Aufforderung nach innen wandert.

Diese Unterscheidung ist so interessant, weil sie davor schützt LOD-Verletzungen einfach durch Datendelegation zu lösen. Wenn der Kunde auf einmal eine Geldmenge hätte, er also seine Innereien ausstellen würde, wäre dem Gesetz der ‘Zwei-Punkte-Vermeidung’ genüge getan, aber substantiell hätte sich nichts geändert. Also: Richtungsumkehr und Verhaltensdelegation.

Dan Mangles kluge Gedanken gehen noch weiter. Er bringt ein Beispiel aus einem View. Dort wird eine Bestellung dargestellt. Diese Bestellung hat einen Kunden, der Kunde hat einen Namen. Das bedeutet wir haben im View eine Stelle mit zwei Punkten: bestellung.kunde.name. Die Verletzung lässt sich in der bekannten Art auflösen. Die Bestellung bekommt neben dem Kunden eine Methode kunde_name. Das ist fachlich unsinnig, eine Bestellung sollte keinen Kundennamen haben. Dan Mangles fragt sich, was das für das Gesetz von Demeter bedeutet. Er kommt zu dem Schluss, das ein View kein Geschäftsobjekt sei und deshalb sei für die Darstellung eine Verletzung des Gesetzes von Demeter erlaubt, besser: er sagt das Gesetz von Demeter beziehe sich eigentlich nur auf das Verhältnis von Geschäftsobjekten.

Und das habe ich erst beim zweiten oder dritten Besuch verstanden. Was wohl beim nächsten Besuch auf mich wartet?

GIT oder die Suche nach der richtigen Abstraktion

Ich glaube von Marshall McLuhan stammt der Gedanke, dass neue Medien immer in Gestalt der alten die Welt erblicken. Sie finden ihre eigene Form erst im Laufe ihrer Entfaltung. Der Gedanke ist wahrscheinlich eine spezifische Fassung eines Allgemeineren. Das Neue tritt prinzipiell immer zuerst in Gestalt des Alten auf und wird auch in seinen Kategorien gedacht. So war das Auto zunächst eine Kutsche ohne Pferde und das Internet war ein Sammelsurium von Texten.

Das Gleiche scheint mir auch für die Geschichte der Versionskontrollsysteme zu gelten. Von Generation zu Generation ändern sich ihre Kernkonzepte, die Konzepte mit denen der Begriff Versionskontrolle gedacht wird.

Die ersten Versionskontrollsysteme systematisierten nur das, was vorher in Form von manueller Versionskontrolle vollzogen wurde. Versionskontrolle ohne System bestand im Kopieren und Umbennen von Dateien. Neben httpd.conf lag httpd.conf.old und vielleicht noch httpd.conf.backup. Die ersten Systeme wie RCS pakten diese Infos – Version 1, 1.1, 1.2 – einfach in eine eigene Datei. Der Wildwuchs war gebannt.

Die zweite Generation der Systeme löste das Problem, dass jetzt mehrere Leute in einem Projekt miteinander arbeiten wollten. Es gab einen Server, der ein Repository verwaltete, und Cientsoftware, die mit diesem Server kommunizierte. Ganze Verzeichnisbäume konnten  ausgecheckt werden, die Versionierung auf dem Server folgte allerdings weiterhin den Gesetzen des RCS: Pro Datei eine Datei mit allen Versionen. (Ich glaube die erste Version des CVS bestand nur aus Shellskripten, die RCS benutzten.)

Die dritte Generation (eher die zweieinhalbte) trat unter dem Motto an, das gleiche zu tun wie CVS, aber jetzt alles richtig zu machen: SVN. Die Daten wurden jetzt serverseitig in einer Datenbank gespeichert. SVN erhielt die Historie eine Datei auch bei einer Umbenennung. SVN kannte das Konzept der Transaktion beim Commit: Entweder gelangen alle Dateien in der neuen Fassung in das Versionskontrollsystem oder keine.

Die vierte oder dritte Generation der Versionskontrollsysteme – GIT – kennt nun verteilte Repositories. Es gibt nur Repositories, die miteinander sprechen, es gibt kein Zentrum mehr, keinen zentralen Server um den sich alles dreht. Die Commits im System existieren nicht mehr implizit wie bei SVN, sondern explizit in einem Baum. GIT folgt nicht mehr der Commit-Semantik einer Datenbank, die nach einem Commit die Transaktion vergessen darf, sondern es baut eine Historie auf, in der jeder Commit ein Knoten bleibt und der Weg zu den Dateien nur über die Commits im Baum funktioniert. In SVN wird die Version eines Verzeichnisbaumes erschlossen. Es ist die höchste Version einer seiner Dateien, in GIT ist die Verbindung von Commit (Version) und Dateibaum als Graph modelliert.

Zurück zum Anfang. Welches ist die alte Form in der sich zunächst das Neue zeigt? Und was ist der neue Begriff, der immer stärker wird, bis er in Form von GIT/Mercurial/bazaar seine aktuelle Form findet? Zwei Konzepte werden in der Geschichte immer schwächer. Die Datei verliert immer mehr an Bedeutung. Im RCS war sie das einzige Konzept, das es gab, im GIT ist sie nur noch über einen Baum erreichbar und in zwei Knoten (Beschreibung/Attribute und Inhalt) zerfallen. Die ersten Systeme – bis zum SVN – speicherten und kommunizierten an Stelle der Dateien nur mit Diffs, um Netzwerklast und Platz zu minimieren, in GIT spielt das – im Prinzip – keine Rolle mehr, die Datei ist komprimiert als ganze in jeder Version abgelegt.

Das zweite Konzept das verschwindet ist das technisch festgelegte Zentrum. Im CVS war es ganz klar, was der Hauptpfad der Entwicklung war und was ein Nebenpfad. Im SVN gab es – technisch – zwischen beiden keinen Unterschied mehr, der Unterschied wurde durch die Konvention gemacht. Das eine wurde Trunk genannt, die anderen wurden unter der Überschrift branch einzeln abgespeichert. In SVN gab es immer noch den Unterschied von zentralem Repository und lokalen – ja was eigentlich? – Auscheckungen. In GIT ist auch die Differenz von Peripherie und Zentrum beseitigt. Es gibt – technisch – nur gleichtberechtigte Repositories. Unterschiede werden hier über die Konvention gemacht.

Welche Abstraktion ist in der Geschichte der Versionskontrolle stärker geworden? Ein Commit, eine Version ist immer expliziter und deutlicher formuliert worden. Für RCS gab es verschiedene Versionen einer Datei – und das lokal. Das Problem das GIT-Commits lösen bestand noch gar nicht. Keine Bäume, keine verschiedenen Benutzer, keine Merges. Im CVS wurde der Commit auf der Datei-Ebene abgebildet. Der Commt über einem Verzeichnisbaum konnte bei ein paar Dateien funktionieren, bei anderen scheitern, und der Benutzer hatte das Problem, dass er die verschiedenen Stände wieder zusammensetzen musste. (Ignoriert habe ich in meiner kleinen Geschichte hier den Unterschied von pessimistischem – SCCS – und optimistischem Locking – CVS). SVN gibt dem Commit eine Semantik wie eine Datenbanktransaktion. Entweder er klappt als Ganzer oder nicht. Wenn er klappt ist er verschwunden und nur noch aus der Historie der Dateien – der Version – zu rekonstruieren. In GIT wird der Commit zu einem expliziten Konzept. Nun ist es auch möglich einen Merge zu modellieren: ein Commit mit zwei Commits als Eltern.

Ergo: Datei und Zentralismus werden immer schwächer, Baum und Historie (explizit als Baum – Graph der Commits) wird immer stärker. Ob das schon das Ende der Entwicklung ist werden wir sehen.

Fussnote: Subversion 1.5 hat das Merge-Tracking eingeführt, 1.6 hat es verbessert. Das ist sicher hilfreich für viele SVN-Projekte und adressiert ein zentrales Problem von SVN, aber ich glaube die konzeptuelle Schwäche im Kern des Systems wird das nicht ausgleichen. SVNs Tage sind gezählt, wenngleich wir auch wissen, wie lange Systeme leben können, die im Interface Schwächen ausgleichen, die sie im Kern enthalten.

GIT und warum SVN-Merges keine Merges sind

Seit zwei Wochen arbeiten wir im Projekt wirklich mit GIT. Bisher kannte ich es nur als Tool, um Open-Source-Projekte zu bekommen, oder für Spielzeug-Repositories auf der eigenen Platte. Die wirklichen Fragen kommen erst jetzt – im realen Leben. ‘Bekomme ich wirklich jedesmal alle Updates aller Branches aus dem Repository oder nur den HEAD?’ ‘Wie läuft denn das mergen, wenn ich gleichzeitig mehrer Branches bekomme?’ Ich merke bei meinen Fragen, dass ich noch in SVN denke.

GIT könne endlich Mergen, Branchen mache Spass, weil das Mergen kein Problem sei, habe ich im Vorfeld von den GIT-Befürwortern gehört und nie so richtig geglaubt. SVN kann doch auch mergen. Nachdem ich den ersten Konflikt hatte und die GIT-merge-Datei genauso aussah wie ich das von SVN gewohnt war (letztlich unix-merge), fühlte ich mich bestätigt.

Was ist eigentlich das Problem beim Mergen? In unseren Projekten passiert es öfter, dass es einen Branch gibt, der mehrere Wochen existiert. Sei es, dass hier der Umstieg auf eine neue Version der Software vorbereitet wird, sei es, dass hier Feature programmiert sind, die erst am Tag X in Erscheinung treten sollen, oder dass der Kunden im Live-Betrieb seine Infrastruktur noch erweitern muss. Diese Branches entwickeln sich parallel zum Trunk. Damit das Mergen nicht so kompliziert wird, werden alle paar Tage die Änderungen aus dem Trunk in den Branch gemergt. Und das kann SVN – irgendwie, oder eigentlich doch nicht. Es gibt zwar ein Kommando ‘svn merge’, doch das merged nur ein Changeset (die Differenz von zwei Versionen – bspw. Trunk zum Zeitpunkt 1 und zum Zeitpunkt 2) in den Branch. Ich sitze dann da mit all den Konflikten, die mir der Merge beschert hat und muss sie auflösen. Danach committe ich wieder und habe eine neue Version im Branch. Das SVN weiss nichts davon, das es sich bei diesem Comit um einen Merge von Version X und Version Y gehandelt hat. Svn hat die Version  geliefert und die Tools angestoßen, die dann den Merge durchführen, den ich selbst als unabhängigen Commit speichere. Wenn ich also den nächsten Merge aus dem Trunk in den Branch mache, muss ich wissen, was ich denn beim letzten Mal gemergt habe. Nur dann kann ich ein neues Changeset so definieren, dass ich alle neuen Änderungen bekomme. Ich kann mir helfen, indem ich in der Commit-Message speichere, was ich beim letzten Mal getan habe, aber das ist nur eine Krücke.

Ganz anders GIT. In GIT nur ein paar Entitäten. Es gibt Blobs, das sind die Inhalte der Dateien. Es gibt Baumobjekte, die die Dateien benennen und die aufeinander verweisen. Und es gibt Commits, die auf ein Baumobjekt und andere Commits verweisen. Branches sind nur PostIts an Commits. Jeder Branch ist also ein Commit mit einem anderen Commit als Vater. Mache ich einen Merge, ist das ein Commit mit zwei Müttern. Die Geschichte meiner Merges und Branches ist explizit im Versionskontrollsystem abgelegt. Ich habe nicht das oben beschriebene Problem. GIT weiss genau, was ich gemergt habe und was noch aussteht. Ich muss nicht durch Kommentare dafür sorgen, das meine Merges funktionieren. (Und natürlich: Beim Mergen auf Dateieben kann GIT auch nicht hexen.)

Was ist jetzt der Unterschied beim Mergen? Für GIT ist ein Merge ein essentielles Konzept, welches explizit modelliert ist. In svn gibt es den Merge nur auf der Ebene der Benutzungsschnittstelle. Die Kernkonzepte kennen ihn nicht. (svn 1.5 soll – Achtung: Hörensagen – den Merge explizit modellieren, allerdings nicht als Kernkonzept.)

Kanban versus Scrum

Im März waren Arthur und ich in Hamburg bei einer Veranstaltung des ObjektForum Nord zum Thema Lean Software Development. Referent war Stefan Roock. Der Vortrag bestand aus zwei Teilen. Im ersten referierte Stefan die Thesen der Poppendieks zum Thema Lean Software Development, wie sie auch in ihren Büchern veröffentlicht sind. Im zweiten Teil beschrieb er Kanban und Kanban-Boards wie sie im Moment im Scrum-Kontext diskutiert werden.

Durch den Vortrag habe ich zum ersten Mal verstanden, wie Scrum und Kanban in Toyotas Philosophie verwurzelt sind und doch so unterschiedlich sein können. Scrum hat seine Wurzeln im Toyota-Produkt-Entwicklungs-System. Die frühen Artikel zu Scrum beziehen sich immer auf einen Aufsatz aus der Harvard Business Review The New New Product Development Game. In diesem Aufsatz geht es um die Art wie neue Produkte entwickelt werden. Dabei spielt die japanische Automobilindustrie eine entscheidende Rolle. Einer der Grundgedanken des Artikels sind crossfunctional Teams.

Kanban dagegen ist das Herzstück des Toyota-Produktions-Systems. Kanban stellt die Logik der Prozessverkettung unterschiedlicher Stationen eines Produktionsprozesses dar. Die Stationen werden durch einen ‘ich sage dir was ich brauche’-Mechnismus (pull) verbunden. (Das Pushprinzip, zentrale Planung der Mengen, fordistisch/tayloristische Organisation, wäre ein anderes, genauer das entgegengesetze Prinzip.)

Während Scrum seine Anleihen bei der Entwicklung neuer Produkte macht, orientiert sich Kanban an der Herstellung von Produkten. Scrum steht für den kreativeren Prozess, der immer das ganze Team braucht, weil sich erst im Prozess zeigt, wann welche Fähigkeit benötigt wird. Kanban optimiert einen per Definition arbeitsteiligen Prozess. Die Reibungsverluste an den Übergängen werden durch Nachfragesteuerung optimiert. Das Was der Produktion steht im Kanban-Prozess nicht zur Disposition, nur das Wie seiner Herstellung.

Vielleicht könnte hier auch der unterschiedliche Fokus der Adaption beider Methoden in der Softwareentwicklung liegen. Scrum für die neuen Dinge, Kanban für die Wartungsprojekte.