Diamond Kata mittels Flow-Design und ISOP

Zuvor gelesene Blogs:

Meine Vorgehensweise

Um das Problem zu verstehen, habe ich selbst diese Kata vorab mittels Flow-Design entworfen. Zuvor habe ich das Problem genau unter die Lupe genommen, heißt ich habe anhand von Beispielen (mittels Papier und Bleistift) nach notwendiger Funktionalität gesucht. Dann habe ich mein Flow-Design erstellt. So stelle ich mir also eine Lösung des Problems vor.

clip_image001

Testfälle zu finden war aufgrund des einfachen Problems, nicht wirklich schwierig. „A“ als Input stellt IMHO den einzigen Sonderfall dar (keine Leerzeichen notwendig). Um die Implementierung voranzutreiben, waren nach „A“, zuerst „B“ und dann „C“ als Input sinnvoll. Das war es allerdings auch schon an priorisierten Testfällen.

Dann habe ich mit der Implementierung des ersten Testfalls („A“) begonnen und ein Walking Skeleton basierend auf meinem Flow-Design erstellt. Das einfache zurückgeben von „A“ (hartcodiert), erschien zu wenig, jedoch für die Implementierung des Grundgerüsts eine gute Hilfe um sicherzustellen, dass die Daten durch alle Methoden fließen. D.h. ich habe das „A“ vom Input durch mein Walking Skeleton zum Output fließen lassen.

Walking Skeleton

image

Somit war der erste Test auf Grün und das Grundgerüst platziert. Man sieht, mein Flow-Design entspricht genau der Implementierung. In diesem Fall war die Implementierung reines Handwerk und daher schnell getippt. Kreativ war ich beim Flow-Design, hier wurde also Ingenieurstätigkeit von mir erbracht.

Mein nächster Testfall war der Input „B“. Dafür war es notwendig, den nächsten Teil des Walking Skeleton zu implementieren:

Walking Skeleton für Testfall „B“

image

Jetzt hätte ich mittels Informed TDD die Methoden die derzeit noch nicht implementiert waren, jede für sich umsetzen können. Erschien mir allerdings zu viel Aufwand für das einfache Problem zu sein. Hier hätte man mit Sicherheit in kleineren Schritten vorgehen können.

Implementierung

image

Ich muss gestehen, hier habe ich einmal auf einen Commit vergessen. Ich habe Prepend_Spaces_To() und Append_Spaces_To() in eine Methode zusammengefügt, da die Implementierungen fast ident waren. Dabei war der Test für den Input „B“ bereits zuvor auf Grün. Somit handelte es sich um ein legitimes Refactoring. Außerdem sind zwei Hilfsfunktionen hinzugekommen, um die notwendigen Leerzeichen zu erzeugen. IMHO handelt es sich dabei um Designdetails, die ich in der Phase des Flow-Design nicht entdeckt habe (was jedoch OK ist).

Die in der Skizze mit Refactoring gekennzeichneten Änderungen im Flow-Design nachgezogen. Es handelt sich also um die zweite Version meines Flow-Designs:

clip_image002

Mein letzter Testfall „C“ sollte eigentlich aufgrund der bis dahin implementierten Funktionalität sofort auf Grün laufen. Allerdings hatte ich einen Fehler in meiner Implementierung der Methode zur Erstellung der Leerzeichen, die in der Mitte von Buchstaben injiziert werden.

Behebung des Fehlers von Leerzeichen

image

Aufgrund der Kompaktheit und Verständlichkeit der Methode, war die Fehlerbehebung allerdings trivial. Zuletzt habe ich noch ein paar Umbenennungen durchgeführt, und Parameternamen hinzugefügt, um die Verständlichkeit zu erhöhen. Hinzufügen von neuer Funktionalität war zu diesem Zeitpunkt nicht mehr notwendig.

Soweit ich die von mir weiter oben erwähnten Blog-Posts verstanden habe, hat Seb Rose des Öfteren das Problem, dass seine Testfälle zu grobgranular sind, d.h. zu viel an Implementierung erfordern, bis sie tatsächlich auf Grün sind. Somit ändert er kontinuierlich bestehende Testfälle, damit er kleinere Schritte in seiner Implementierung vornehmen kann. Diese Testfälle sind dann letztendlich in der finalen Version nicht mehr sichtbar.

IMHO entspricht das in etwa dem „Informed TDD„-Gedanken. D.h., nachdem meine Walking Skeletons auf Grün waren, hätte ich eigene Testfälle für diese Funktionseinheiten entwerfen können. Dabei hätte ich jeweils immer nur eine Methode implementiert und die jeweils anderen ge-stubbed. Natürlich könnte man auch die Integrationsfunktion Insert_Spaces() in eine eigene Klasse verschieben. Diese hätte dann ebenfalls isoliert getestet werden können.

Was mir beim Flow-Design außerordentlich gut gefällt, ist das umgesetzte Integration Operation Segregation Principle (IOSP). Ausschließlich in den grün gekennzeichneten Funktionseinheiten ist Logik enthalten (if-Statements, etc.). Integrationsmethoden machen nichts anderes, als andere Funktionseinheiten zusammenzufügen. Operationseinheiten haben absolut keine Abhängigkeiten auf andere Operationen. Ausschließlich Integrationen haben Abhängigkeiten.

Hier sieht man die Version von Seb Rose. Was auffällt, in dieser Implementierung wird nicht zwischen Integration und Operation getrennt. Ich hätte sogar gesagt, dass hier eine Operation (Create()) von einer Integration (BuildLine()) abhängt. Operationen sollten jedoch als Blätter in einem Baum implementiert werden, sofern man das IOSP umsetzen möchte.

Ich möchte hier nicht alle Vorteile von Flow-Design, IOSP und Informed TDD aufzählen. Das kann Ralf Westphal natürlich viel besser. Ich empfehle daher sowohl seinen englischen, als auch seinen deutschen Blog nach diesen Themen zu durchsuchen. Auch seine Bücher sind natürlich eine spitzen Quelle, um sich intensiver mit der Thematik zu beschäftigen.

Hier noch die endgültige Version von meiner Lösung:

Über sageniuz

https://about.me/ClausPolanka
Dieser Beitrag wurde unter Flow-Design, IOSP, Kata, TDD veröffentlicht. Setze ein Lesezeichen auf den Permalink.

Eine Antwort zu Diamond Kata mittels Flow-Design und ISOP

  1. Ralf Westphal schreibt:

    Schöne Idee, mal diese Kata mit Informed TDD zu machen.

    Ich habe mich dann auch mal dran versucht. Hier meine Lösung: https://dotnetfiddle.net/Vg0Srg
    Allerdings ohne Tests😉 Ich habe stattdessen zuerst in Main() ein paar Probeausgaben geschrieben und dann mit der DiamondFactory{} begonnen. In kleinen Schritten. Der Flow ist direkt im Code entstanden. Dabei ist die Ausgabe immer näher an das Ziel herangerückt.

    Das könnte man noch etwas refaktorisieren, z.B. eine Klasse für das Padding einführen. Aber ich denke, so geht es auch erstmal.

Schreibe einen Kommentar

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s