Freitag, 21. August 2009

Dieser Blog ist tot. Ich blogge weiter auf dem «Agile Trail».

Pecha Kucha "Inkrementelles Design" (Folien und Video)

Auf der JAX '09 im Frühling diesen Jahres habe ich für it-agile in einer Pecha Kucha-Session auf dem Agile Day einen Vortrag "Inkrementelles Design" gehalten. Host war Stefan Roock (Homepage, Twitter, Xing). Das sind die Folien:

View more documents from Bernd Schiffer.

Das alles ist schon ein wenig länger her, aber jetzt hat die Konferenz-Organisation das Video auf JAX TV veröffentlicht. Danke JAX-Team! Hier das Video:


Ich rede zwar viel zu schnell, trotzdem: Viel Spaß damit :-)

Apropos Pecha Kucha I: Auf den XP Days Germany 2009 im November diesen Jahres gibt es gleich 9 Pecha Kucha-Vorträge in drei Blöcken (siehe Programm). Das sind für mich die Perlen dieser Konferenz, also nicht verpassen!

Apropos Pecha Kucha II: Auf der WJAX '09, auch im November diesen Jahres, gibt es wieder eine Pecha Kucha-Session, die ich zusammen mit Martin Heider (Xing, Twitter) auf dem Agile Day halten werde. Thema: "Mein agiler Koffer - Reisetipps mit Pecha Kucha".

Links:

Montag, 17. August 2009

Dieser Blog ist tot. Ich blogge weiter auf dem «Agile Trail».

Zu meinem Verständnis von TDD und BDD


Mein Kollege Stefan Roock schreibt in seinem Blogpost von einem "Vergleich: BDD und TDD":
"Ich [wurde] bereits früh von TDD (Test Driven Development) infiziert. Irgendwann kam eine neue Bewegung auf: BDD (Behaviour Driven Design). Wie viele andere TDDler habe ich lange nicht verstanden, was der Vorteil von BDD sein soll."
Dito. Verstehe den Vorteil von BDD bis heute nicht. Ich präzisiere: Verstehe ich bis heute nicht für mich.

Stefan scheint seinen Frieden mit BDD nun gemacht zu haben, denn er schreibt:
"[Der Vorteil] ist mir inzwischen klar gewor[d]en."
Stefan nimmt in seinem Blogpost eine Portion Ruby-Code eines TDD-Beispiels mit RUNIT her und übersetzt es in ein BDD-Beispiel mit RSpec. Dabei fällt ihm dies auf:
"Strukturell sind Test und BDD-Spezifikation identisch. Die BDD-Spezifikation ist bei den Vergleichen lediglich etwas leichter lesbar.
Der Vergleich termin.bezeichnung.should == "TDD-Dojo" ist der natürlichsprachlichen Formulierung "Die Terminbezeichnung sollte 'TDD-Dojo' sein." ähnlicher als assert_equal("TDD-Dojo", termin.bezeichnung)."
Lange habe ich gegrübelt, was mich hier stört. Und das ist mir inzwischen klar geworden. Was heißt denn leichter lesbar? Was ist natürlichsprachlich?

BDD selbst verweist als eines seiner Vorteile auf die Sapir-Whorf-Hypothese. Diese Hypothese besagt
"... dass die Sprache das Denken formt."
Nach dem, wie und was wir (be-)sprechen, nach dem handeln wir auch. Sprechen wir über Tests, so sichern wir primär Eigenschaften zu. Sprechen wir dagegen von Spezifikationen, so beauftragen wir Eigenschaften und geben an, wie sie sein sollen. Demnach weichen test und assert aus xUnit specification und should aus RSpec. Die Idee ist, dass wenn der Programmierer keine Tests mehr schreibt, sondern Spezifikationen, wenn er keine Zusicherungen über, sondern einen Auftrag (should; soll; Auftrag) an den Code schreibt, dass er dann anders denkt.

Dieses Andersdenken bezieht sich auf das letzte D in TDD: Die einen übersetzen es mit Development, die anderen mit Design. Letzteres ist für viele TDDler die eigentliche Qualität des TDD: Das Design wird getrieben durch die Tests. Es geht nicht um Verifikation, sondern um Spezifikation. Diesen Gedanken greift das BDD nun auf und fragt: Wenn wir spezifizieren statt zu testen, wenn wir schreiben, was der Code tun soll, anstatt etwas zuzusichern, dann sollten wir das auch so aufschreiben, damit wir durch die Worte wohl geleitet handeln.

Mag sein, dass das für jemanden gilt, der neu ist in TDD. Das kann ich mir gut vorstellen. "TDD? Was soll das sein? Ach, Tests? So so, verstehe, geht ums Testen von Software. Alles klar, man her damit!" Und schon ist der Neue mit falschen Annahmen bei der Sache. Nicht gut. Da hilft BDD, oder?

Seit über 8 Jahren programmiere ich testgetrieben, was mich als TDD-Neuling disqualifiziert. Meine Vorstellung von Tests sind stark kontextbehaftet. Geht's um TDD? Dann sind meine Tests keine Verifikationen, sondern meine Mittel fürs Design. Geht's um die Endabnahme, Akzeptanztests, QA? Dann sind meine Tests verifizierend. Da hilft kein BDD, um mein Handeln durch eine andere Terminologie zu besseren Ergebnissen zu leiten.
"BDD"
, frei nach Dave Astels,
"macht man, wenn man TDD richtig macht."
Und bislang war das der Strohhalm, nach dem ich gegriffen habe, wenn ich nicht verstand, warum BDD nun anders sein soll als TDD. Dieser Strohhalmgriff beruht auf meiner Annahme, dass ich bereits korrektes TDD mache. Subjektiv, vielleicht vermessen, möglicherweise anmaßend, auf jedenfall nicht objektiv bewertbar ist die Aussage, ob ich korrektes TDD mache. Das war mir immer ein sehr kleiner Strohhalm.

Wittgenstein ist da schon ein größerer Strohhalm. Von ihm las ich neulich wieder in Prechts "Wer bin ich und wenn ja, wie viele?", und von seiner Idee der Präzisionssprache. Wittgensteins Theorie besagte, dass die Sprache als Abbild der Realität dienen kann. Und er lag falsch, wurde widerlegt:
"[Der Sprache] wichtigste Funktion besteht darin, zu verstehen und verstanden zu werden. Ob etwas verständlich ist oder nicht bestimmen sowohl die Grammatik wie der Kontext. So kann der Satz 'Ich sehe schwarz' meinen, dass ich vor einem schwarzen Bild stehe und seine Farbe beschreibe. Ebenso gut aber kann er bedeuten, dass ich in einer Sache pessimistisch bin. Dem jungen Wittgenstein waren solche Sätze ein Greuel, aber die Sprache wimmelt nur so von Mehrdeutgkeiten. Die schlichte Wahrheit, die jede Idee einer Präzisionssprache zum Scheitern verurteilt, ist, dass die Bedeutung eines Satzes durch den Gebrauch der Wörter geformt wird."
Die Bedeutung wird also durch den Gebrauch der Wörter geformt. Die Wörter selbst formen nicht die Bedeutung. Es ist eine Implikation, keine Äquivalenz. Und ich benutze Worte wie Test und Zusicherung schon seit 8 Jahren. Kein Wunder also, dass die Bedeutung von TDD bei mir entsprechend geformt wurde. Das, was hinter TDD steckt, erschließt sich mir mehr über die Worte Test und Zusicherung, weniger über Spezifikation und Auftrag.

Wenn ich einem xDD-Neuling im TDD-Camp erkläre, dass er die Tests vor dem Code schreiben, dass er Einfachheit anstreben, dass er gnadenlos refaktorisieren, dass er Redundanzen eliminieren und dass er noch ein paar TDD-Gebräuche mehr anwenden soll, und wenn ich dem xDD-Neuling dann sage, dass das Testgetriebene Entwicklung ist, dann habe ich die Bedeutung von Tests im Kontext des TDD durch den Gebrauch der Worte wie Tests und Zusicherungen entsprechend geformt. Aus meiner Sicht heraus sind für einen xDD-Neuling beide Begriffsgruppen, Tests-Zusicherung und Spezifikation-Auftrag, am Anfang seiner Ausbildung gleich bedeutungsleer oder -voll. Das, was diese Wortgruppen mit dem verbindet, was hinter TDD/BDD steckt, dem Treiben des Designs also, wird erst durch den Gebrauch, also durch die Anwendung dieser Wörter geformt. Wenn das stimmt, dann ist es schnurzpiepegal, ob man nun TDD oder BDD macht.

Mein Fazit: Taten mögen den Worten folgen (Sapir-Whorf-Hypothese; BDD), sicherlich wird Bedeutung durch den Gebrauch von Worten erlangt (Widerlegung Wittgensteins; xDD). Egal, ob ich BDD oder TDD anwende, beide benutzen eine jeweils eigene Terminologie, die Bedeutung durch den Gebrauch derselben erlangt. Ergo hat weder BDD noch TDD einen Vorteil gegenüber der jeweils anderen Technik.

Versöhnlich möchte ich schließen. Precht schreibt:
"Und die entscheidende Frage beim Verständnis von Sätzen ist nicht, ob etwas wahr ist oder falsch, sondern ob die Verständigung im beabsichtigten Sinne gelingt oder nicht gelingt."
Verständigung im beabsichtigten Sinne: Egal ob TDD oder BDD, es geht nicht darum, ob Tests oder Spezifikationen, es geht darum, zu verstehen, dass in beiden Fällen Design getrieben wird.

Wir verstehen uns?

Freitag, 14. August 2009

Dieser Blog ist tot. Ich blogge weiter auf dem «Agile Trail».

Wenn's mal passt


Bin gerade in einer sehr glücklichen Beziehung. Vor Kurzem hat es angefangen. Wir kannten uns schon ein wenig vorher, aber so richtig zusammen sind wir erst seit fünf Wochen. Wir wußten damals nicht mit Sicherheit, ob es mit uns beiden klappen würde. Umso glücklicher sind wir jetzt darüber, dass wir anscheinend richtig gut zusammenpassen.

Woran ich es erkannt habe, dass es gut passte? Da war dieses Bauchgefühl, dass mir in der ein oder anderen Situation Bestätigung gab. Und natürlich haben wir unsere Differenzen über die ein oder andere Sache. Sogar über gegenteilige Ansichten hinaus kommen wir miteinander gut aus.

Wir sehen uns fast jeden Tag und verbringen dann viel Zeit miteinander. Ich würde es gar nicht aushalten, wenn wir ständig Probleme miteinander hätten. Darum finde ich es geradezu notwendig, dass wir uns gegenseitig riechen können, dass wir auf einer Wellenlänge funken. Gar nicht auszudenken, dass ich so eng mit jemandem zusammen sein müsste, mit dem ich mich nicht gut verstehe.

Wir lernen viel voneinander. Wir beide haben schon viele Beziehungen mitgemacht und haben daraus viel geschöpft. Und es sind nicht nur die Techniken (obwohl das schon jede Menge Spass machen kann, sich gegenseitig die abgefahrensten Praktiken vorzustellen und dann miteinander auszuprobieren). Es ist der Respekt, der uns gegenseitig zuhören lässt, wenn der andere spricht; es ist das offene Feedback, dass wir uns geben und vom anderen annehmen; es ist der Spass, den wir miteinander haben, ohne unser gemeinsames Ziel aus den Augen zu verlieren; es ist der Flow, in dem wir zusammen agieren.

Es ist nur ein kurzes Projekt, etwa sechs Wochen. Es ist nur ein kleines Projekt, wir zwei eben. Das Risiko war also sehr gering, zwei, die sich nicht kennen, zusammen da reinzustecken. Trotzdem hat das Nahezu-blind-miteinander-Arbeiten schon nach drei bis fünf Wochen geklappt. Wenige Zeilen Code sind entstanden, als wir nicht zusammen im Paar programmiert haben. Jedes Mem, das mindestens einer von uns für wichtig hielt, haben wir besprochen, sind dabei richtig in die Tiefe gegangen, und sind jeweils beide gestärkt daraus hervorgegangen. Architektur, Design, Pattern, solche Dinge meine ich. Shortcuts, Programmiersprach-Idiome, Tipps & Tricks, die meine ich auch. Coole Tweets, Youtube-Videos und Blogposts, auch die gehören dazu.

Ich genieße diese Zeit. Es kommt nicht oft vor, dass man so gut miteinander kann innerhalb eines Projektes. Fast nie kann ich mir aussuchen, mit wem ich programmiere. Und dann ist es eben eine gewisse Chance bishin zu reinem Zufall, wenn's passt. Das kommt vor, aber weitaus weniger oft, als man annehmen könnte.

Kernaussage dieses Posts soll sein... - nun, keine Liebeserklärung jedenfalls. Dass ich gut mit meinem Kollegen kann, und er mit mir, dass wissen wir beide seit einigen Retrospektiven. Dieser Gewissheit bedürfte es keines Blogposts. Nein, Kernaussage dieses Posts soll sein, Wert auf gute Beziehungen innerhalb eines Projektes zu legen lohnt sich. Nie arbeite ich so produktiv, so effizient, so effektiv, so nachhaltig gut, als wenn ich einen guten Partner habe.

Schönes Gefühl, wenn alles passt.

Freitag, 7. August 2009

Dieser Blog ist tot. Ich blogge weiter auf dem «Agile Trail».

Beispiel für Refactoring von Beispiel für Closures

Vor ein paar Wochen hat mein Kollege Stefan Roock (Xing, Twitter) auf seinem Blog von einem "Beispiel für Closure" geschrieben. Wie so oft geht mir beim Lesen (fremden) Codes mein Das-ist-nicht-DRY-Alarm an. So auch bei Stefans Post. Es folgt ein Refactoring.

Stefan will die Laufzeit je Methode für eine Menge von Methoden messen. Die Menge hat er so bechrieben:


Ich konnte in seinem Post die Implementierung von tueA(), tueB() und tueC() nicht finden. Meine Annahme ist, dass sie ein wenig Laufzeit verbrauchen und etwas ausgeben:

Führt man nun die Menge an Methoden aus, so ist das die Ausgabe:

Stefan misst nun die Laufzeit der Methoden, und sein Output sieht (mit meiner Implementierung der Methoden) so aus:

Da ich ein Refactoring beabsichtige, darf sich das Verhalten des Codes, in diesem Falle der Output, nicht ändern.

Aber warum eigentlich Refaktorisieren? Mit Stefans Implementierung als solcher bin ich eigentlich zufrieden. Naja, da kann man noch ein Semikolon weglassen sowie eine Variable duration einführen und im GString hinterm println substituieren. Aber das ist Kleinkram, nebenbei machbar und hier kaum der Rede wert. Stefans Implementierung der Closure:

Nein, es geht mir um den Aufruf von Stefans Lösung (siehe Stefans komplette Lösung). Was muss ich tun, um die Laufzeit einer Menge von Methoden zu messen? Wo ist der Schalter, den ich einschalten muss? Stefan legt diesen Schalter um:

Seht Ihr die Redundanz? Stefan legt nicht einen Schalter um, sondern drei. Drei Mal muss er vor die Methoden timeLogged schreiben, inklusive geschweifte Klammer vor und nach der zu messenden Methode. Das ist nicht DRY.

DRY wäre es, eine Menge von Methoden einzeln zu messen. Das hier schwebt mir vor:

Und das geht. Die Closure-Magie, mit der das geht, hat Ted Naleid (Twitter, LinkedIn) in seinem Blogpost "Groovy closures make unit testing with “soft asserts” simple" ausführlich beschrieben. Hier ist meine Lösung:

Keep on DRYin', Stefan! "Bleib trocken, Stefan!" lag mir auf der Zunge, ging aber hier nun echt nicht... :-)

Links: