it-swarm-eu.dev

TDD vs. Produktivität

In meinem aktuellen Projekt (ein Spiel in C++) habe ich beschlossen, Test Driven Development zu 100% während der Entwicklung zu verwenden.

In Bezug auf die Codequalität war dies großartig. Mein Code war noch nie so gut gestaltet oder fehlerfrei. Ich erschrecke nicht, wenn ich Code ansehe, den ich vor einem Jahr zu Beginn des Projekts geschrieben habe, und ich habe ein viel besseres Gespür dafür gewonnen, wie man Dinge strukturiert, nicht nur einfacher testbar, sondern auch einfacher zu implementieren und zu verwenden .

Es ist jedoch ein Jahr her, seit ich das Projekt gestartet habe. Zugegeben, ich kann nur in meiner Freizeit daran arbeiten, aber TDD verlangsamt mich immer noch erheblich im Vergleich zu dem, was ich gewohnt bin. Ich habe gelesen, dass die langsamere Entwicklungsgeschwindigkeit mit der Zeit besser wird, und ich denke mir Tests definitiv viel leichter aus als früher, aber ich bin jetzt seit einem Jahr dabei und arbeite immer noch im Schneckentempo.

Jedes Mal, wenn ich über den nächsten Schritt nachdenke, der Arbeit erfordert, muss ich jedes Mal anhalten und darüber nachdenken, wie ich einen Test dafür schreiben würde, damit ich den eigentlichen Code schreiben kann. Manchmal stecke ich stundenlang fest und weiß genau, welchen Code ich schreiben möchte, aber ich weiß nicht, wie ich ihn fein genug aufschlüsseln kann, um ihn vollständig mit Tests abzudecken. In anderen Fällen werde ich mir schnell ein Dutzend Tests ausdenken und eine Stunde damit verbringen, Tests zu schreiben, um ein winziges Stück echten Codes abzudecken, dessen Schreiben sonst einige Minuten gedauert hätte.

Oder nachdem ich den 50. Test abgeschlossen habe, um eine bestimmte Entität im Spiel und alle Aspekte ihrer Erstellung und Verwendung abzudecken, schaue ich auf meine To-Do-Liste und sehe die nächste zu codierende Entität und erschrecke vor Entsetzen bei dem Gedanken an das Schreiben weitere 50 ähnliche Tests, um es umzusetzen.

Es ist zu dem Punkt gekommen, dass ich angesichts der Fortschritte des letzten Jahres erwäge, TDD aufzugeben, um "das verdammte Projekt fertig zu stellen". Ich freue mich jedoch nicht darauf, die damit verbundene Codequalität aufzugeben. Ich fürchte, wenn ich aufhöre, Tests zu schreiben, werde ich es mir nicht mehr zur Gewohnheit machen, den Code so modular und testbar zu machen.

Mache ich vielleicht etwas falsch, um dabei immer noch so langsam zu sein? Gibt es Alternativen, die die Produktivität beschleunigen, ohne die Vorteile vollständig zu verlieren? BISSCHEN? Weniger Testabdeckung? Wie überleben andere Menschen TDD, ohne jegliche Produktivität und Motivation zu beeinträchtigen?

136
Nairou

Lassen Sie mich zunächst danken, dass Sie Ihre Erfahrungen teilen und Ihre Bedenken äußern ... was ich sagen muss, sind keine Seltenheit.

  • Zeit/Produktivität: Das Schreiben von Tests ist langsamer als das Nichtschreiben von Tests. Wenn Sie dies berücksichtigen, stimme ich zu. Wenn Sie jedoch eine parallele Anstrengung ausführen, bei der Sie einen Nicht-TDD-Ansatz anwenden, besteht die Möglichkeit, dass Sie durch die Zeit, die Sie für die Erkennung, das Debuggen und das Korrigieren von vorhandenem Code aufwenden, negativ bewertet werden. Für mich ist TDD das schnellste, das ich fahren kann, ohne mein Code-Vertrauen zu beeinträchtigen. Wenn Sie in Ihrer Methode Dinge finden, die keinen Mehrwert bieten, beseitigen Sie sie.
  • Anzahl der Tests: Wenn Sie N Dinge codieren, müssen Sie N Dinge testen. um eine der Zeilen von Kent Beck zu paraphrasieren "Testen Sie nur, wenn Sie möchten, dass es funktioniert."
  • Stundenlang stecken bleiben: Ich auch (manchmal und nicht> 20 Minuten, bevor ich die Leitung stoppe). Es ist nur Ihr Code, der Ihnen sagt, dass das Design etwas Arbeit benötigt. Ein Test ist nur ein weiterer Client für Ihre SUT-Klasse. Wenn ein Test Schwierigkeiten hat, Ihren Typ zu verwenden, ist dies wahrscheinlich auch für Ihre Produktionskunden der Fall.
  • Ähnliche Tests langwierig: Dies erfordert etwas mehr Kontext, damit ich ein Gegenargument verfassen kann. Das heißt, hör auf und denke über die Ähnlichkeit nach. Können Sie diese Tests irgendwie mit Daten steuern? Ist es möglich, Tests gegen einen Basistyp zu schreiben? Dann müssen Sie nur noch die gleichen Tests für jede Ableitung ausführen. Hören Sie sich Ihre Tests an. Seien Sie die richtige Art von Faulheit und sehen Sie, ob Sie einen Weg finden können, um Langeweile zu vermeiden.
  • Es ist keine schlechte Sache, anzuhalten, um darüber nachzudenken, was Sie als Nächstes tun müssen (Test/Spezifikation). Im Gegenteil, es wird empfohlen, dass Sie "das Richtige" bauen. Wenn ich mir nicht vorstellen kann, wie ich es testen soll, kann ich normalerweise auch nicht an die Implementierung denken. Es ist eine gute Idee, Implementierungsideen auszublenden, bis Sie dort ankommen. Vielleicht wird eine einfachere Lösung von einem YAGNI-artigen Präventivdesign überschattet.

Und das bringt mich zur letzten Frage: Wie werde ich besser? Meine (oder eine) Antwort lautet Lesen, Reflektieren und Üben.

z.B. In letzter Zeit habe ich den Überblick

  • ob mein Rhythmus RG [Ref] RG [Ref] RG [Ref] widerspiegelt oder RRRRGRRef ist.
  • % Zeitaufwand im Status Rot/Kompilierungsfehler.
  • Bin ich in einem Red/Broken Builds-Zustand festgefahren?
78
Gishu

Sie benötigen keine 100% ige Testabdeckung. Sei pragmatisch.

34
Alistair

TDD verlangsamt mich immer noch erheblich

Das ist eigentlich falsch.

Ohne TDD verbringen Sie einige Wochen damit, Code zu schreiben, der meistens funktioniert, und verbringen das nächste Jahr damit, viele (aber nicht alle) Fehler zu "testen" und zu beheben.

Mit TDD verbringen Sie ein Jahr damit, Code zu schreiben, der tatsächlich funktioniert. Anschließend führen Sie einige Wochen lang endgültige Integrationstests durch.

Die verstrichene Zeit wird wahrscheinlich dieselbe sein. Die TDD-Software wird eine wesentlich bessere Qualität aufweisen.

23
S.Lott

Oder nachdem ich den 50. Test abgeschlossen habe, um eine bestimmte Entität im Spiel und alle Aspekte ihrer Erstellung und Verwendung abzudecken, schaue ich auf meine To-Do-Liste und sehe die nächste zu codierende Entität und erschrecke vor Entsetzen bei dem Gedanken an das Schreiben weitere 50 ähnliche Tests, um es umzusetzen.

Ich frage mich daher, wie sehr Sie dem Schritt "Refactor" von TDD folgen.

Wenn alle Ihre Tests bestanden sind, ist es Zeit für Sie, den Code umzugestalten und Duplikate zu entfernen. Während sich die Leute normalerweise daran erinnern, vergessen sie manchmal, dass es auch an der Zeit ist, ihre Tests umzugestalten, um Doppelarbeit zu entfernen und Dinge zu vereinfachen.

Wenn Sie zwei Entitäten haben, die zu einer zusammengeführt werden, um die Wiederverwendung von Code zu ermöglichen, sollten Sie auch deren Tests zusammenführen. Sie müssen wirklich nur inkrementelle Unterschiede in Ihrem Code testen. Wenn Sie Ihre Tests nicht regelmäßig warten, können sie schnell unhandlich werden.

Einige philosophische Punkte zu TDD, die hilfreich sein könnten:

  • Wenn Sie trotz umfangreicher Erfahrung beim Schreiben von Tests nicht herausfinden können, wie man einen Test schreibt, dann ist das definitiv ein Codegeruch. In Ihrem Code fehlt es irgendwie an Modularität, was das Schreiben kleiner, einfacher Tests schwierig macht.
  • Wenn Sie TDD verwenden, ist es durchaus akzeptabel, ein bisschen Code herauszugeben. Schreiben Sie den gewünschten Code, um eine Vorstellung davon zu bekommen, wie er aussieht, löschen Sie den Code und beginnen Sie mit Tests.
  • Ich sehe das Üben von extrem strenger TDD als eine Form der Übung. Wenn Sie anfangen, schreiben Sie auf jeden Fall jedes Mal zuerst einen Test und schreiben Sie den einfachsten Code, um den Test zu bestehen, bevor Sie fortfahren. Dies ist jedoch nicht erforderlich, sobald Sie sich mit der Praxis vertraut gemacht haben. Ich habe nicht für jeden möglichen Codepfad, den ich schreibe, einen Komponententest, aber durch Erfahrung kann ich auswählen, was mit einem Komponententest getestet werden soll und was durch Funktions- oder Integrationstests abgedeckt werden kann stattdessen. Wenn Sie TDD seit einem Jahr streng praktizieren, würde ich mir vorstellen, dass Sie auch diesem Punkt nahe sind.

EDIT: Zum Thema Philosophie des Unit-Testings denke ich, dass dies für Sie interessant sein könnte: The Way of Testivus

Und ein praktischerer, wenn nicht unbedingt sehr hilfreicher Punkt:

  • Sie erwähnen C++ als Ihre Entwicklungssprache. Ich habe TDD ausgiebig in Java geübt und dabei exzellente Bibliotheken wie JUnit und Mockito verwendet. Ich habe jedoch festgestellt, dass TDD in C++ aufgrund des Mangels an verfügbaren Bibliotheken (insbesondere spöttischen Frameworks) sehr frustrierend ist. Obwohl dieser Punkt in Ihrer aktuellen Situation nicht viel hilft, hoffe ich, dass Sie ihn berücksichtigen, bevor Sie TDD ganz fallen lassen.
20
jaustin

Sehr interessante Frage.

Was wichtig ist, ist, dass C++ nicht sehr einfach zu testen ist und Gaming im Allgemeinen auch ein sehr schlechter Kandidat für TDD ist. Sie können nicht testen, ob OpenGL/DirectX mit Treiber X ein Dreieck rot und mit Treiber Y leicht gelb zeichnet. Wenn der Bump-Map-Normalvektor nach der Shader-Transformation nicht gespiegelt wird. Sie können auch keine Clipping-Probleme über Treiberversionen mit unterschiedlichen Genauigkeiten usw. testen. Undefiniertes Zeichenverhalten aufgrund falscher Aufrufe kann auch nur mit genauer Codeüberprüfung und verfügbarem SDK getestet werden. Sound ist auch ein schlechter Kandidat. Multithreading, das wiederum für Spiele sehr wichtig ist, ist für Unit-Tests so gut wie nutzlos. Es ist also hart.

Grundsätzlich ist Gaming eine Menge GUI, Sound und Threads. Die GUI ist selbst mit Standardkomponenten, an die Sie WM_ senden können, schwer zu testen.

Was Sie also testen können, sind Modellladeklassen, Texturladeklassen, Matrixbibliotheken und dergleichen, die nicht viel Code enthalten und häufig nicht sehr wiederverwendbar sind, wenn es nur Ihr erstes Projekt ist. Außerdem sind sie in proprietären Formaten verpackt, sodass es nicht sehr wahrscheinlich ist, dass sich die Eingaben von Drittanbietern stark unterscheiden, es sei denn, Sie veröffentlichen Modding-Tools usw.

Andererseits bin ich kein TDD-Guru oder Evangelist, also nimm das alles mit einem Körnchen Salz.

Ich würde wahrscheinlich einige Tests für Hauptkernkomponenten schreiben (zum Beispiel Matrixbibliothek, Bildbibliothek). Fügen Sie bei unerwarteten Eingaben in jeder Funktion eine Reihe von abort() hinzu. Und vor allem konzentrieren Sie sich auf resistenten/belastbaren Code, der nicht leicht zu brechen ist.

Die clevere Verwendung von C++, RAII und ein gutes Design tragen wesentlich dazu bei, diese Fehler zu vermeiden.

Grundsätzlich müssen Sie viel tun, um die Grundlagen zu behandeln, wenn Sie das Spiel veröffentlichen möchten. Ich bin mir nicht sicher, ob TDD helfen wird.

10
Coder

Ich stimme den anderen Antworten zu, möchte aber auch einen sehr wichtigen Punkt hinzufügen: Refactoring-Kosten !!

Mit gut geschriebenen Unit-Tests können Sie Ihren Code sicher neu schreiben. Erstens bieten gut geschriebene Komponententests eine hervorragende Dokumentation der Absicht Ihres Codes. Zweitens werden alle unglücklichen Nebenwirkungen Ihres Refactorings in der vorhandenen Testsuite erfasst. Somit haben Sie garantiert, dass die Annahmen Ihres alten Codes auch für Ihren neuen Code zutreffen.

6
Morten

Wie überleben andere Menschen TDD, ohne jegliche Produktivität und Motivation zu beeinträchtigen?

Das ist völlig anders als meine Erfahrungen. Sie sind entweder erstaunlich intelligent und schreiben Code ohne Fehler (z. B. durch einen Fehler) oder Sie erkennen nicht, dass Ihr Code Fehler enthält, die das Funktionieren Ihres Programms verhindern, und sind daher nicht wirklich fertig.

Bei TDD geht es darum, die Demut zu haben, zu wissen, dass Sie (und ich!) Fehler machen.

Für mich ist das Schreiben von Unittests mehr als Zeitersparnis bei der Reduzierung der Debugging-Zeit für Projekte, die von Anfang an mit TDD ausgeführt werden.

Wenn Sie keine Fehler machen, ist TDD für Sie vielleicht nicht so wichtig wie für mich!

4
Tom

Ich habe nur ein paar Bemerkungen:

  1. Es scheint, dass Sie versuchen zu testen alles. Sie sollten es wahrscheinlich nicht tun, nur die Hochrisiko- und Edge-Fälle eines bestimmten Codes/einer bestimmten Methode. Ich bin mir ziemlich sicher, dass hier die 80/20-Regel gilt: Sie verbringen 80% damit, Tests für die letzten 20% Ihres Codes oder für Fälle zu schreiben, die nicht behandelt werden.

  2. Priorisieren. Machen Sie sich mit der agilen Softwareentwicklung vertraut und erstellen Sie eine Liste der Dinge, die Sie wirklich wirklich tun müssen, um sie in einem Monat zu veröffentlichen. Dann einfach so loslassen. Dies lässt Sie über die Priorität von Funktionen nachdenken. Ja, es wäre cool, wenn dein Charakter einen Backflip machen könnte, aber hat er Geschäftswert?

TDD ist gut, aber nur, wenn Sie keine 100% ige Testabdeckung anstreben, und nicht, wenn es Sie davon abhält, tatsächlichen Geschäftswert zu erzielen (d. H. Funktionen, Dinge, die Ihrem Spiel etwas hinzufügen).

3
Cthulhu

Ja, das Schreiben von Tests und Code kann länger dauern als nur das Schreiben von Code. Das Schreiben von Code und zugehörigen Komponententests (mit TDD) ist jedoch viel vorhersehbarer als das Schreiben von Code und das anschließende Debuggen.

Das Debuggen wird durch die Verwendung von TDD fast eliminiert - was den gesamten Entwicklungsprozess viel vorhersehbarer und letztendlich viel schneller macht.

Ständiges Refactoring - Ohne eine umfassende Unit-Test-Suite ist kein ernsthaftes Refactoring möglich. Der effizienteste Weg, um dieses auf Unit-Tests basierende Sicherheitsnetz aufzubauen, ist während der TDD. Gut überarbeiteter Code verbessert die Gesamtproduktivität des Designers/Teams, das den Code verwaltet, erheblich.

1
ratkok

Erwägen Sie, den Umfang Ihres Spiels einzuschränken, und bringen Sie es dahin, wo jemand es spielen kann, oder Sie veröffentlichen es. Behalten Sie Ihre Teststandards bei, ohne zu lange warten zu müssen, um Ihr Spiel zu veröffentlichen. Dies könnte ein Mittelweg sein, um Sie zu motivieren. Das Feedback Ihrer Benutzer kann langfristig Vorteile bringen, und Ihre Tests ermöglichen es Ihnen, sich mit den Ergänzungen und Änderungen wohl zu fühlen.

0
JeffO