it-swarm-eu.dev

Warum ist TDD an Universitäten nicht beliebter?

Kürzlich stellte eine Person hier eine grundlegende Frage zum Berechnen in Python alle Permutationen von Elementen aus einer Liste. Wie bei den meisten Fragen, die von Schülern gestellt wurden, habe ich den tatsächlichen Quellcode in nicht angegeben meine Antwort, sondern erklärte, wie man das Problem angeht, was im Wesentlichen in einer grundlegenden Darstellung der testgetriebenen Entwicklung endete.

Als ich über das Problem selbst nachdachte, erinnerte ich mich an all die ähnlichen Probleme, die ich lösen musste, als ich selbst Programmieren an der Universität studierte. Wir wurden nie über testgetriebene Entwicklung oder eine vergleichbare Methode unterrichtet, wurden aber ständig gebeten, Algorithmen zu schreiben, die Elemente aus einer Liste sortieren oder Towers of Hanoi-Rätsel lösen usw. Auch scheinen nicht alle Schüler, die auf SoftwareEngineering.SE kommen zu wissen, wie TDD (Test Driven Development) ihnen helfen würde, die Probleme zu lösen, die ihnen gestellt werden: Wenn dies der Fall wäre, hätten sie ihre Fragen sehr unterschiedlich formuliert.

Tatsache ist, dass all diese Probleme ohne TDD in der Tat ziemlich herausfordernd sind. Ich betrachte mich als professionellen Entwickler, aber ich würde immer noch einige Zeit damit verbringen, einen Algorithmus zur Listenreihenfolge ohne TDD zu schreiben, wenn ich gefragt würde, und ich wäre größtenteils ahnungslos, wenn ich gebeten würde, alle Permutationen der Elemente in einer Liste zu berechnen, immer noch ohne mit TDD. Mit TDD hingegen löste ich das Permutationsproblem in wenigen Minuten, als ich die Antwort an den Schüler schrieb.

Was ist der Grund, warum TDD entweder überhaupt nicht oder zumindest sehr spät an Universitäten unterrichtet wird? Mit anderen Worten, wäre es problematisch, den TDD-Ansatz zu erklären, bevor die Schüler gebeten werden, Listensortieralgorithmen und ähnliches zu schreiben?


Nach den Ausführungen in zwei der Fragen:

In Ihrer Frage scheinen Sie TDD als "Problemlösungsgerät" zu präsentieren [...] In der Vergangenheit wurde TDD als "Lösungserkennungsmechanismus" vorgestellt, aber selbst Bob Martin (der Hauptanwalt von TDD) räumt dies ein Sie müssen eine erhebliche Menge an Vorkenntnissen in die Technik einbringen.

und speziell:

Ich bin gespannt, warum TDD Ihrer Meinung nach ein kniffliges Algorithmusproblem mit einer genau definierten Spezifikation einfacher macht.

Ich finde es notwendig, etwas mehr zu erklären, was meiner Meinung nach an TDD so magisch ist, wenn es darum geht, Probleme zu lösen.

In der High School und an der Universität hatte ich keine spezifischen Techniken, um Probleme zu lösen, und dies galt sowohl für die Programmierung als auch für die Mathematik. Rückblickend nehme ich an, dass eine dieser Techniken darin besteht, die aktuelle/letzte Lektion/Vorlesung zu überprüfen und eine Beziehung zur Übung zu suchen. Wenn es in der Lektion um Integrale geht, besteht die Möglichkeit, dass das Problem, das der Lehrer lösen möchte, die Verwendung von Integralen erfordert. Wenn es in der Vorlesung um Rekursion ging, besteht die Möglichkeit, dass das den Schülern gegebene Rätsel durch Rekursion gelöst werden kann. Ich bin mir auch sicher, dass es gut formalisierte Ansätze zur Lösung von Problemen in der Mathematik gibt, und diese Ansätze können auch auf die Programmierung angewendet werden. Ich habe jedoch nie etwas gelernt.

Dies bedeutet, dass mein Ansatz in der Praxis einfach darin bestand, das Problem zu lösen und zu versuchen zu erraten , wie es gelöst werden sollte. Wenn ich damals die Herausforderung hätte, Permutationen von Elementen aus einer Liste zu generieren, würde ich nicht mit einer leeren Liste als Eingabe beginnen, sondern mit einem anschaulichen Beispiel wie [4, 9, 2], Um herauszufinden, warum Gibt es sechs mögliche Permutationen und wie kann ich sie durch Code generieren? Von dort aus muss ich viel nachdenken, um einen möglichen Weg zur Lösung des Problems zu finden. Dies ist im Wesentlichen das, was der Autor in der rsprüngliche Frage getan hat und am Ende random verwendet hat. In ähnlicher Weise, als ich Student war, begannen keine anderen Studenten in meinem Alter mit []: Alle eilten sofort mit zwei oder drei Elementen zum Fall und blieben dann eine halbe Stunde lang stecken und endeten manchmal mit Code, der nicht kompiliert oder nicht ausgeführt wird.

Der TDD-Ansatz scheint mir kontraintuitiv zu sein. Ich meine, es funktioniert sehr gut, aber ich hätte selbst nie herausgefunden, bevor ich ein paar Artikel über TDD gelesen habe, dass (1) ich mit dem einfachsten Fall beginnen sollte, (2) den Test schreiben sollte, bevor ich Code schreibe, und (3) ) Niemals eilen und versuchen, mehrere Szenarien im Code zu erfüllen. Wenn ich mir anschaue, wie Anfängerprogrammierer denken, habe ich den Eindruck, dass ich nicht der einzige bin, der dies als kontraintuitiv empfindet. Ich glaube, es kann für Programmierer, die eine funktionierende Sprache gut verstehen, intuitiver sein. Ich nehme an, dass es in Haskell beispielsweise selbstverständlich wäre, das Permutationsproblem zu lösen, indem zuerst ein Fall einer leeren Liste, dann ein Fall einer Liste mit einem Element und dann ein Fall einer Liste mehrerer Elemente betrachtet wird. In Sprachen, in denen rekursive Algorithmen möglich sind, aber nicht so natürlich wie in Haskell, ist ein solcher Ansatz jedoch viel weniger natürlich, es sei denn, man praktiziert natürlich TDD.

123

Ich bin ein Teilzeit-Programmierlehrer an einem örtlichen Community College.

Der erste Kurs, der an diesem College unterrichtet wird, ist Java-Programmierung und -Algorithmen. Dies ist ein Kurs, der mit grundlegenden Schleifen und Bedingungen beginnt und mit Vererbung, Polymorphismus und einer Einführung in Sammlungen endet. Alles in einem Semester für Studenten, die noch nie zuvor eine Codezeile geschrieben haben, eine Aktivität, die für die meisten von ihnen völlig exotisch ist.

Ich wurde einmal zu einem Lehrplanprüfungsausschuss eingeladen. Der Vorstand stellte eine Reihe von Problemen mit dem CS-Lehrplan des Colleges fest:

  1. Zu viele Programmiersprachen werden unterrichtet.
  2. Keine Kurse zum Software Development Life Cycle.
  3. Keine Datenbankkurse.
  4. Es ist schwierig, Credits für die Übertragung an staatliche und lokale Universitäten zu erhalten, auch weil diese Schulen sich nicht auf eine einheitliche Definition der Begriffe "Informatik", "Informationstechnologie" und "Software-Engineering" einigen können.

Mein Rat an sie? Fügen Sie dem Lehrplan eine Abschlussklasse für zwei Semester hinzu, in der die Schüler eine Full-Stack-Anwendung schreiben können. Dieser Kurs deckt den gesamten Lebenszyklus der Softwareentwicklung von der Erfassung der Anforderungen bis zur Bereitstellung ab. Dies würde sie bei lokalen Arbeitgebern (auf Lehrlingsebene) anstellbar machen.

Wo passt TDD in all das? Ich weiß es ehrlich gesagt nicht.

In Ihrer Frage scheinen Sie TDD als "Problemlösungsgerät" zu präsentieren. Ich sehe TDD hauptsächlich als einen Weg, um das Design und die Testbarkeit von Code zu verbessern. In der Vergangenheit wurde TDD als "Lösungserkennungsmechanismus" vorgestellt, aber selbst Bob Martin (der Hauptanwalt von TDD) räumt ein, dass Sie eine erhebliche Menge an Vorkenntnissen in die Technik einbringen müssen.

Mit anderen Worten, Sie müssen zuerst wissen, wie Sie Probleme im Code lösen können. TDD bringt Sie nur in die richtige allgemeine Richtung in Bezug auf die Besonderheiten des Software-Designs. Das macht es zu einem Kurs der oberen Ebene, nicht zu einem Kurs der unteren Ebene.

135
Robert Harvey

Zunächst müssen wir grundsätzlich zwischen Informatik und Software Engineering unterscheiden. ). (Und vielleicht in geringerem Maße zwischen Software Engineering und Programmierung oder "Codierung".)

Wie einer meiner CS-Professoren es ausdrückte: Wenn Sie eine Tastatur benötigen, machen Sie keine CS.

TDD ist in hohem Maße eine Software-Engineering-Praxis. Es hat nicht wirklich viel mit Informatik zu tun. Wenn Sie sich also fragen, warum CS-Schüler TDD nicht lernen, liegt das daran, dass TDD nicht wirklich viel mit CS zu tun hat.

Nun, Software Engineering, das ist ein ganz anderer Fischkessel. Ich stimme sehr zu, dass TDD dort unterrichtet werden sollte. Ich hatte einen Software Engineering Kurs (90 Minuten pro Woche für ein Semester) und in diesem Kurs lernten wir Wasserfall, V-Modell, RUP, CMM, CASE , RAD, Spiral, Iterative und wahrscheinlich einige andere Dinge, die ich vergessen habe. Sicherlich hätte TDD Platz geboten, insbesondere wenn Sie es in den Rest der Kurse integrieren und TDD auf alle Hausaufgaben und Klassenarbeiten in allen Kursen anwenden, in denen Programmierung erforderlich ist.

Um fair zu sein, war in meinem Fall das Agile Manifest noch nicht geschrieben worden, und TDD war eine obskure Nischentechnik.

Wenn Sie sich meinen persönlichen Favoriten für den Programmierunterricht ansehen, Wie man Programme entwirft , werden Sie feststellen, dass sie sehr unterrichten Zu Beginn sollten Funktionen mit Verwendungsbeispielen geliefert werden, und nur wenig später führt das Buch automatisierte Komponententests ein und schlägt vor, diese Verwendungsbeispiele in Form von Tests zu schreiben. Sie lehren auch, dass Verwendungsbeispiele und sogenannte "Zweckanweisungen" (Sie können sich das als Zusammenfassungszeile eines JavaDoc-Kommentars vorstellen) vor dem Code geschrieben werden sollten.

Sie unterrichten TDD nicht explizit (sie haben ihre eigene Methodik), aber dies ist zumindest etwas eng. HtDP wurde für Schüler entwickelt, die in weniger als einem Jahr unterrichtet werden sollen. Ich denke, es ist mehr als machbar, es in einem einzigen Semester an der Universität zu unterrichten.

Um ehrlich zu sein, wäre es bereits ein großer Gewinn für die Schüler, denen einfach beigebracht wurde, dass sie den Code, den sie geschrieben haben, tatsächlich mit verschiedenen Eingaben ausführen können. (Mit anderen Worten, eine grobe Form des manuellen Testens.) Ich bin erstaunt, wie oft Schüler diesen mentalen Schritt nicht ausführen können.

Zum Beispiel habe ich mehrere Fragen zum Stapelüberlauf gesehen, die sich im Wesentlichen auf "welche Methode muss ich implementieren, damit dieser Code funktioniert" belaufen. Beachten Sie, dass es nicht um den Code der Methode ging (der Fragesteller wusste, wie die Methode implementiert wird), sondern nur um den Name . Nicht einer der Fragesteller kam jedoch auf die Idee, einfach den Code auszuführen und den Namen der fehlenden Methode in NoMethodError Ausnahme, die immer ausgelöst wird.

97
Jörg W Mittag

TDD ist ein netter Prozess in der "realen" Programmierung, da Probleme häufig auf unseren Schreibtischen auftreten, die nicht genau spezifiziert sind. "Fügen Sie eine Funktion hinzu, die X ausführt", "Beheben Sie den Fehler, bei dem das Falsche angezeigt wird, wenn Sie Y ausführen" usw. TDD zwingt uns, eine Spezifikation zu erstellen, bevor wir mit der Programmierung beginnen.

In CS/Programmierklassen kommen die Probleme normalerweise sehr genau auf uns zu. "Schreiben Sie eine Funktion, die ein Array von Ganzzahlen verwendet und ein Array mit denselben Ganzzahlen zurückgibt, die in nicht absteigender Reihenfolge angeordnet sind." Die Spezifikation wird uns übergeben.

Ich bin gespannt, warum TDD Ihrer Meinung nach ein kniffliges Algorithmusproblem mit einer genau definierten Spezifikation einfacher macht. Insbesondere möchte ich, dass Sie dies erklären:

Ich wäre größtenteils ahnungslos, wenn ich gebeten würde, alle Permutationen der Elemente in einer Liste zu berechnen, immer noch ohne Verwendung von TDD. Mit TDD hingegen löste ich das Permutationsproblem in wenigen Minuten, als ich die Antwort an den Schüler schrieb.

Ich vermute, Sie werden sagen, weil Sie Testfälle geschrieben haben, in denen P([]) -> [[]], P([1]) -> [[1]], P([1, 2]) -> [[1, 2], [2, 1]] usw. bestätigt wurde, und die Sie veranlasst haben, zu sehen, wie die Rekursion funktionieren sollte . Aber das ist nicht TDD, das ist nur ... über das Problem nachzudenken. Sie können über das Problem nachdenken, ohne tatsächliche Unit-Tests zu schreiben, die fehlschlagen.

53
MattPutnam

Ich vermute, das liegt hauptsächlich daran, dass das Schreiben automatisierter Tests schwieriger ist als das Schreiben des zu testenden Codes. Wenn Sie immer noch mit der Grundmechanik zu kämpfen haben, ist es schwierig, eine weitere Ebene hinzuzufügen. Wie andere Antworten gezeigt haben, wird TDD auch als Softwareentwicklungsprozess wahrgenommen, obwohl seine Praktiker es eher als didaktisches Gerät betrachten. Außerdem ist es eine Fähigkeit für sich, zu wissen, welche Tests zuerst geschrieben werden müssen.

Wenn ich einen Einführungskurs unterrichten würde, würde ich Tests einige Tests in TDD-Reihenfolge bereitstellen und die Schüler anweisen, die Tests nacheinander in dieser Reihenfolge zu bestehen. Das ist eine sehr ähnliche Erfahrung wie die Paarprogrammierung mit einem erfahrenen Mentor. Persönlich denke ich, dass dies das Unterrichten von Klassen wie Algorithmen erleichtern würde, was die für die Technik aufgewendete Zeit aufgrund des schrittweisen Fortschritts ausgleichen würde. Die Schüler würden über Fragen nachdenken wie: "Ich habe einen bewährten Arbeitscode, der alle Permutationen einer Liste mit zwei Elementen findet. Wie verwende ich so viel Code wie möglich wieder, damit er für mehr als drei Elemente funktioniert?"

33
Karl Bielefeldt

Das Grundproblem ist, dass die Tests erfinden im TDD-Prozess nichts mit Informatik oder Software-Engineering zu tun hat. Es erfordert Kenntnisse der Anwendungsdomäne.

Das ist natürlich die Stärke von TDD in realen Anwendungen: Sie können sich nicht entziehen, darüber nachzudenken, wofür das System, das Sie erstellen, tatsächlich verwendet wird. Bei typischen CS- und SE-Aktivitäten haben die Aufgaben, die dem Schüler übertragen werden, nur einen minimalen Kontext und dienen nur dazu, ein Lernziel zu testen oder zu veranschaulichen.

Wenn das Lernziel beispielsweise darin besteht, das Verständnis des Konstrukts "case" in einer Programmiersprache zu demonstrieren, ist TDD irrelevant: Sie können Software schreiben, die alle TDD-Tests besteht, ohne "case" zu verwenden. Wenn das Beispiel künstlich wäre, könnte die Nichtverwendung von "case" tatsächlich eine bessere Lösung für das Problem in der realen Welt sein, jedoch nicht in Bezug auf das beabsichtigte Lernziel.

Ermutigen Sie die Schüler auf jeden Fall, ihre eigenen Testfälle zu erfinden und auszuführen, aber der Versuch, einen formalen TDD-Prozess zu verwenden, ist nebensächlich.

Ein zweites Problem hat vielleicht mehr mit der Art und Weise zu tun, wie CE und SE unterrichtet werden, aber es ist immer noch ein praktisches: Wie bewerten Sie die Sammlung von Tests des Schülers, wenn Sie TDD verwenden? Es gibt keine offensichtliche Möglichkeit, diesen Prozess zu automatisieren.

Selbst wenn Sie eine Modelllösung erstellen, die besagt, dass Sie für die folgenden 15 oder 20 Situationen getestet haben sollten, müssen Sie manuell identifizieren, welcher der Tests des Schülers (ganz oder teilweise) jedem Teil Ihrer Modellantwort entspricht. Und außer in trivialen Fällen hat der Schüler möglicherweise eine Reihe guter Tests erstellt, die logisch anders strukturiert sind als die Modellantwort.

9
alephzero

Der durchschnittliche Schüler hat wirklich einen schlechten Überblick darüber, was er wissen und tun soll. Um TDD zu unterrichten, müssten sie verstehen:

  1. So beheben Sie technische Probleme. Am Anfang denken sie, dass Code auf einmal geschrieben wird. Erst später, wenn sie grundlegende Debugging-Strategien realisieren, wechseln sie zu mehr inkrementellem Schreiben. Selbst wenn Sie ihnen dies im Voraus sagen, werden sie es trotzdem so machen, weil sie denken, dass die Dinge so gemacht werden (dies ist übrigens auch der Grund, warum die Leute nicht wissen, wie man zeichnet, Klavier spielt, Mathe macht usw. usw.). )

  2. So überprüfen Sie Ihre eigenen Handlungen, damit Sie wiederholbare Muster in Ihrem eigenen Verhalten finden können. Sobald Sie dies tun können, können Sie Ihre eigene Arbeit automatisieren. Dies ist den meisten Menschen jedoch völlig fremd, bis sie ein bestimmtes Niveau erreicht haben.

  3. Wie schreibe ich Anforderungen?.

  4. Eckfälle Ihres Problembereichs verstehen.

  5. Verständnis der technischen Philosophie des Risikomanagements. (ha, aber du weißt nicht einmal, dass du ein Ingenieur bist)

  6. Grundlegendes zum Refactoring und zur Wartung von Code.

  7. Verstehen, wie Programmieren in einem realen Unternehmen funktioniert.

Tatsächlich hatte ich Kollegen, die viel zu früh in TDD eingeführt wurden, sie haben nicht wirklich viel davon profitiert. Es ist jedoch weiterhin möglich, kleine Schritte in Richtung dieses Effekts zu unternehmen. Es ist nur so, dass die Menschen einige Erfahrung hinter sich brauchen, um davon zu profitieren.

Sie können es also unterrichten, aber nicht etwas, mit dem Sie beginnen. Zumal es Code gibt, der sich nicht so leicht für TDD eignet.

8
joojaa

TDD ist an Universitäten nicht beliebter, da (im Allgemeinen) Universitäten sehr schlechte Arbeit leisten, um sicherzustellen, dass das Wissen, das den Studenten vermittelt wird, in reale Kontexte übertragen werden kann.

Das ist wohl nicht in erster Linie die Rolle der Universität, sondern es geht mehr darum, die Grundlagen und Kernkonzepte von CS zu vermitteln. Das ist lehrreich, wichtig und unabdingbar, wenn die Studenten an einer Karriere im akademischen Bereich interessiert sind. Es ist jedoch nicht ausreichend, wann die Studenten ihr Studium abschließen und sich in der Branche einschreiben und in einem Team arbeiten, das der Entwicklung folgt Best Practices, CI/CD usw.

Natürlich gibt es Kreuzungen, und beide können voneinander profitieren, aber letztendlich ist die Universität einfach noch nicht auf dem neuesten Stand, was getan werden muss, um leistungsfähigere, relevantere und aktuellere Software-Ingenieure zu absolvieren.

6
Bruno Oliveira

Um die Frage direkt zu beantworten:

Wie jemand vorgeschlagen hat, gibt es genug Lernen für ein ganzes Semester. Ein separater Kurs? Könnte sein. Ich konnte sehen, dass TDD mit Software-Design-Themen kombiniert wurde. Der größte Wert von IMO TDD besteht darin, vorhandene Verhaltensweisen zu sperren, damit wir später neue Verhaltensweisen hinzufügen und das Design so ändern können, dass es für diese neuen Verhaltensweisen geeignet ist. Also eine Software-Design-Klasse?

Es wäre schön zu sehen, dass der Denkprozess hinter TDD (schlecht benannt, und ich habe Kent Beck einmal gefragt, ob er es sich noch einmal überlegen würde; er sagte, "dieser Zug hat den Bahnhof verlassen") so früh wie möglich eingeführt wird. Ich schleudere seit 1976 Code und ich weiß, dass TDD sich anfangs sehr unnatürlich anfühlte. Aber jetzt fühlt es sich ganz natürlich an. Meine Zeit wird nicht durch das Schreiben von Testcode wieder gut gemacht, sondern später, wenn ich nur einmal im Jahr einen schwerwiegenden Fehler beheben muss (die OTIS2-Software des UofM Transplant Center, die vollständig testgetrieben geschrieben wurde, hatte 2004 ihren letzten "Software-Notfall" ).

Ich ermutige neue Absolventen, es einen Monat lang auszuprobieren. Aber es wäre für sie viel einfacher, wenn sie viel früher TDD ausgesetzt wären. Ich finde die Verwendung des Unit-Test-Frameworks nützlich, wenn ich eine neue Sprache lerne (Wahre Geschichte: "Wie kann ich diesen Test in Ruby bestehen? Vielleicht funktioniert das ... HEY IT WORKED!") Oder beim Erkunden eine neue Bibliothek ("Die Dokumente sind vage über die Reihenfolge, in der diese zurückgegeben werden ... Ich werde einen Test schreiben ...").

Ich finde TDD wertvoll, wenn ich einen Algorithmus implementiere (NICHT einen erfinde ... darauf komme ich zurück) oder sozusagen eine leicht komplizierte Geschäftsregel von Grund auf aufbaue. Jeder Test, der besteht, ist für alle Ewigkeit "eingesperrt". Wenn der Test diskret genug ist, muss er sich nie ändern (aber das dauert viel länger als einen Monat, um gut zu werden).

Es wäre also interessant, TDD in frühere Programmierklassen aufzunehmen. Drei Verbesserungspunkte:

  1. Wir könnten uns weniger auf Debugging und Breakfix konzentrieren, was die meisten Entwickler für die Natur ihres Jobs halten. Ist es nicht. Es muss nicht so schmerzhaft oder zeitaufwändig sein.
  2. Unit-Test-Frameworks sind ein einfacher Ersatz für #ifdef DEBUG/printf ("...")/#endif - daher haben wir seit Beginn der Zeit etwas Ähnliches (aber riskanteres) getan.
  3. Wenn wir hören "Sie müssen zuerst den Test schreiben", werden wir irregeführt. Ich will, um meine Erwartungen an den Code aufzuschreiben, den ich schreiben werde. Ich möchte das laufen lassen, während ich mich auf das nächste Verhalten konzentriere oder das Design bereinige.

Eine andere Sache, die nützlich sein könnte, ist ein Lehrbuch oder zumindest ein komprimierter No-Nonsense-Lehrplan mit Labors, die verschiedene Aspekte der TDD-Praxis vermitteln sollen. Ich habe einen Vorschlag dafür (siehe Erfahrung/Haftungsausschluss später).

Um den Kritikern zu antworten:

Ich bin neu hier, aber ich stelle fest, dass einige "Antworten" die Frage nicht beantworten, sondern faire Kritik an TDD sind. Ich vermute also, dass es in Ordnung ist, einige dieser Bedenken auszuräumen?

  1. Es ist wahr, Studien, die durchgeführt wurden, um TDD mit Unit-Test-After (UTA?) Zu vergleichen, zeigen, dass TDD anfangs langsamer war. Die UTA-Gruppe hatte jedoch eine viel geringere Testabdeckung und mehr Defekte. Ich denke, es war diese Studie: Längsschnittstudie zur Verwendung einer testgetriebenen Entwicklungspraxis in der Industrie

Wenn Entwickler, die länger als ein paar Monate an einem Produkt gearbeitet haben, den größten Teil ihrer Zeit damit verbringen würden, neue Funktionen zu schreiben, wäre dies negativ. Aber die sechs TDD-Teams, an denen ich als Entwickler gearbeitet habe, haben ihre Zeit auf diese Weise verbracht, während das Jahrzehnt, in dem ich Code vor TDD geschleudert habe, hauptsächlich im Debugger verbracht wurde oder vorsichtig kopiert/eingefügt/geändert wurde, damit ich nicht älter werde/jemand anderes Code. Die Vorteile von TDD sind nicht alle augenblicklich, aber sie waren bemerkenswert zuverlässig und erstaunlich wertvoll, gemessen an geringeren Überstunden (und Stress) der Entwickler und höhere Einnahmen = . Fazit: Ich habe mich immer darauf gefreut, mit diesen TDD-Teams zusammenzuarbeiten. (Einmal hatte ich etwas Tee getrunken.)

  1. Es ist auch wahr, dass TDD keinen neuen Algorithmus erfinden kann. Ich denke, es war Ron Jeffries, der versuchte, mit TDD einen Sudoku-Löser zu erstellen, und versuchte, seine eigenen Sudoku-Fähigkeiten nicht in die Implementierung einfließen zu lassen. Er hat versagt. Ich bin nicht überrascht. TDD hilft dabei, Geschäftsregeln aufzuschlüsseln, zu vereinfachen und umzusetzen. hilft zu bestätigen, dass wir einen richtigen Algorithmus haben (z. B. einen komplexen Verschlüsselungsalgorithmus, der möglicherweise nicht reduzierbar ist); hilft uns, den Code später umzugestalten, damit wir sicher neue Funktionen hinzufügen können; Dies geschieht, indem die Investition, die wir bereits in das Verhalten des Produkts getätigt haben, festgehalten wird.

Wenn Sie einen "Test" schreiben (auch bekannt als Spezifikation, auch bekannt als Szenario), müssen Sie die Antwort kennen! Außerdem möchten Sie einen Test schreiben, der so klein ist, dass Sie bereits eine Vorstellung (Vorkenntnisse) davon haben, wie Sie ihn implementieren werden.

Was oft überrascht, ist, wie klar und einfach das Design werden kann, wenn wir auf Code-Gerüche achten und nach Bedarf umgestalten, wenn alle Tests in Bezug auf diesen Code bestanden werden.

Niemand schlägt vor, dass wir unser gutes Wissen über Designmuster oder Sprachsprachen oder SOLID Prinzipien, oder wie man Sudoku spielt oder wie man eine Heap-Sortierung schreibt) verwerfen.

Bei TDD geht es darum, ein Sicherheitsnetz zu schaffen, das uns das Vertrauen gibt, schnell neue Funktionen hinzuzufügen und das Design so zu ändern, dass es diesen neuen Funktionen entspricht, ohne etwas anderes zu beschädigen.

UTA repariert das Sicherheitsnetz, nachdem jemand durch ein Loch in den Tod gefallen ist. (Interessante Randnotiz: Das OTIS2-Projekt ist ein lebenswichtiges System, daher war das Risiko des Todes eines Patienten für uns kein Scherz. Über 20.000 Tests, die alle in 10 Minuten ausgeführt wurden, sind jetzt das ist ein Sicherheitsnetz!)

Erfahrung/Haftungsausschluss:

Ich habe von 1998 bis 2004 fast Vollzeit TDD gemacht und mit ~ 6 verschiedenen Teams. Alle waren mindestens 6 Monate Entwicklungszeit. Davor hatte ich 13 Jahre damit verbracht, Software in die andere Richtung zu schreiben, und habe Debugger und manuelle Tests mit printf () gehasst.

Ich habe 2001 angefangen, Softwareentwicklungspraktiken zu unterrichten, jetzt einschließlich TDD-, BDD- und SA-CSD-Kursen. Sicher, es ist ein guter Lebensunterhalt, aber ich weiß auch, dass TDD eine einfache Möglichkeit ist, die teamorientierte Softwareentwicklung wieder vernünftig und unterhaltsam zu gestalten. Damit...

Ich schreibe, was ich hoffe, ein Lehrbuch für ein College oder eine High School zu werden (natürlich mit Online-Repos, Labors, Videos usw.): Essential Test-Driven Development

4
user30938

Ich habe TDD nie als hilfreich angesehen, um ein Problem tatsächlich zu lösen, und nachdem ich Ihre Frage gelesen habe, tue ich es immer noch nicht.

TDD zwingt Sie lediglich dazu, ein Problem von einem Ende aus zu betrachten: dem Ende des Kunden. Dies kann dazu beitragen, dass Sie keine Lösung finden, die nicht der Frage des Kunden entspricht. Dies ist im Allgemeinen eine gute Sache, obwohl es Sie auch einschränken könnte, es Sie davon abhält, das Problem aus einem weiteren Blickwinkel zu betrachten. Möglicherweise gibt es eine bessere, allgemeinere Lösung für das Problem, das Ihr Kunde nicht in Betracht gezogen hat.

Eine andere Sichtweise ist, dass dies der ultimative Top-Down-Ansatz ist. TDD könnte für Top Down Development stehen. Sie beginnen die Entwicklung auf höchstem Kursniveau und zoomen schrittweise hinein.

In jedem Fall ist es ein abstraktes Konzept. Sie können einem Schüler davon erzählen, eine Definition angeben, aber das wird es sein. Sie können nicht so viele Fragen dazu in einer Prüfung stellen. Obwohl es in einer SE- oder CS-Klasse in einem SE-Kontext nützlich ist, kann es sich nie um mehr als eine Randnotiz handeln.

4
Martin Maat

In den 1970er Jahren wurde mir Informatik beigebracht, lange bevor das Akronym TDD erfunden wurde, und natürlich wurde uns diese Technik nie explizit beigebracht. Aber für eine der Programmierübungen, die wir erhielten, wurden uns eine Reihe von Testfällen geliefert und uns wurde gesagt, dass unsere Lösung die Tests bestehen musste. Also habe ich den Wert des Ansatzes gelernt, ohne ihn jemals explizit gelernt zu haben, und habe ihn seitdem verwendet.

4
Michael Kay

Während das Schreiben von Tests eine wesentliche Fähigkeit für die Softwareentwicklung ist, deuten die wissenschaftlichen Erkenntnisse nicht darauf hin, dass TDD letztendlich eine bessere Software produziert als die iterative Test-Last-Entwicklung (ITL) (OTOH, dies ist auch nicht der Fall ) schlimmer ).

Als Beweis können Sie Davide Fucci et al. "Eine externe Replikation zu den Auswirkungen testgetriebener Entwicklung unter Verwendung eines Multi-Site-Blindanalyse-Ansatzes" ( Link ) und die Metaanalyse von Turhan et al. In Making Software ( Link ).

Wenn wir also keine gegenteiligen Beweise dafür sehen, dass TDD tatsächlich messbare Gewinne liefert, ist es weniger wichtig, dass TDD als spezifische Praxis gelehrt wird, als einfach die gute Angewohnheit des Testschreibens zu einem bestimmten Zeitpunkt im Entwicklungsprozess zu vermitteln.

3
Anzel

aber ich würde immer noch einige Zeit damit verbringen, einen Listenordnungsalgorithmus ohne TDD zu schreiben, wenn ich gefragt würde, und ich wäre größtenteils ahnungslos, wenn ich gebeten würde, alle Permutationen der Elemente in einer Liste zu berechnen, immer noch ohne Verwendung von TDD. Mit TDD hingegen habe ich das Permutationsproblem in wenigen Minuten gelöst

Das verwirrt mich ernsthaft.
Testgetriebene Entwicklung bedeutet für mich, frühzeitig über Tests nachzudenken und sich die Zeit zu nehmen, Tests zu implementieren und sie mit Code auf dem neuesten Stand zu halten.
Natürlich ist das Überlegen, was getestet werden soll, eine gute Gelegenheit, das zu lösende Problem zu erläutern und in einigen Fällen ein gutes Bild von den Fallstricken zu erhalten.
Aber TDD nicht zu machen, sich nicht zuerst auf Tests zu konzentrieren, verbietet sowieso nicht, über das zugrunde liegende Problem nachzudenken. Sie sollten immer darüber nachdenken, was Sie tun, und die Situation klarstellen, egal ob Sie noch einen Schritt weiter gehen und Tests jetzt implementieren möchten oder nicht.

wäre es problematisch, den TDD-Ansatz zu erklären, bevor die Schüler gebeten werden, Listensortieralgorithmen und ähnliches zu schreiben?

Es hängt davon ab, inwieweit Sie TDD erklären würden.
Es ist hilfreich, etwas zu hören. Aber die Schüler hören eine Menge Dinge, die sie noch nicht interpretieren können, weil andere Grundlagen noch fehlen. Sie sollten also nicht zu tief in ein Konzept eintauchen, das ohne Kenntnis der Grundlagen ein nutzloses und entfremdendes Durcheinander unbekannter Begriffe für sie wäre.
Außerdem wissen wahrscheinlich viele Programmierer, wie es sich anfühlt, wenn Sie nach einer Anleitung für ein Problem suchen und Beispiele finden, die zwar eine Lösung zeigen, aber zunächst alle anderen irrelevanten Dinge klären müssen der Autor fügte hinzu.

Um diese Frage zu beantworten: Wenn ich Student wäre, würde ich mir wünschen, dass die Dinge getrennt werden. Wenn Sie uns erklären, wie wir eine Liste sortieren sollen, sagen Sie uns bitte, wie das geht, aber verlassen Sie nicht den Pfad, um Testmaterial auszufüllen. Wenn Sie mit der Erläuterung von Tests beginnen möchten, geben Sie nicht an, die Sortierung zu implementieren, da dies noch lange nicht der Fall ist.
Auch hier sind einige Überlegungen erforderlich, bevor wir mit dem Schreiben der Sortierung oder der Tests beginnen. Wie sehen Listen vor und nach dem Sortieren aus? Machen Sie Beispiele, denken Sie über Fallstricke nach, was berücksichtigt werden muss, um Fehler zu vermeiden, wenn eine Liste leer ist und so weiter. All dies muss berücksichtigt werden, aber es ist noch keine Testreihe geschrieben.

Im Allgemeinen würde ich sagen, dass Sie zwei Dinge verwechseln, die getrennt aufbewahrt werden sollten.

  • Denken Sie über die Art des Problems nach, das Sie lösen möchten.
  • Denken Sie über die Eingabe in Ihren Code nach und darüber, welche Ausgabe erfolgen soll.

Das Nachdenken über das Problem unterscheidet sich stark von der Konzentration auf das Schreiben von Testfällen.

Wie man es schlecht macht

Einmal stieß ich auf ein Beispiel für TDD von jemandem, der von TDD besessen war.
Leider schien es mir, dass der Autor sein Tutorial zu sehr mochte, so dass er nicht wusste, was für ein Mist es tatsächlich war.

Der Autor nur konzentrierte sich auf Testfälle, nicht auf das Problem, mit dem der Code umgehen sollte. Da Sie nie alle Eingabepermutationen finden können, müssen Sie einen Überblick darüber haben, was Sie tatsächlich tun. Sie müssen das gesamte Problem sehen. Sie können nicht immer mit leeren Eingaben beginnen, anschließend weitere Eingaben hinzufügen und immer Code anhängen, um neue Eingaben korrekt zu verarbeiten.
Sie müssen eine Vorstellung davon haben, womit Sie sich im Allgemeinen tatsächlich befassen. Aber der Autor hat es nicht getan.

Wenn ich versuche, es in das Sortieren einer Liste zu übersetzen, beginnen wir mit einer leeren Liste, dann einem Element, das so zurückgegeben werden kann, wie es ist, einer Liste mit zwei Elementen, die möglicherweise ausgetauscht werden müssen und möglicherweise in einer Rekursion enden, weil Drei Elemente sind wie zwei (das haben wir bereits gelöst) plus eins mit einem zusätzlichen Schritt ...
Ein schreckliches Szenario für einen Sortieralgorithmus - aber niemand wird es erkennen, weil wir uns nur auf unsere Testfälle konzentrieren.

Fazit

Die Kommentare lassen mich etwas mehr über meine Meinung schreiben.

Ich denke, der Begriff "testgetriebene Entwicklung" ist falsch. Es sollte eine "testgestützte Entwicklung" sein, was bedeutet, dass wir nicht nur programmieren und hoffen, sondern auch über das Testen nachdenken und wissen, dass es immer gut ist, frühzeitig zu wissen, wenn etwas schief geht.

Wenn die Entwicklung von Tests als getrieben bezeichnet wird, kann dies bedeuten, dass alles nur von Tests abhängt und wir fertig sind, sobald einige Testfälle erfüllt sind. Diese Anforderung würde auch durch sehr unzureichenden Code erfüllt, der nie versucht hat, ein Problem als Ganzes zu erkennen, sondern hin und her gehackt wurde, bis alle Testfälle versehentlich grün werden - und dann im realen Betrieb fehlschlägt.

2
puck

Sie haben Ihre Frage so aktualisiert, dass sie mehr lautet: "Warum wird TDD nicht als zentrales Lernwerkzeug unterrichtet?". Andere Antworten erklären bereits gut genug, warum TDD kein gutes Thema für die Codierung von 101 ist, aber die Hauptantwort ist wirklich nur, dass TDD im Kern kein Werkzeug zur Problemlösung ist. Es kann für diesen Zweck verwendet werden, aber wie bei jedem Tool muss man zuerst verstehen, wann und wie man es verwendet.

TDD ist ein Testprozess und wird daher ganz natürlich entweder als Teil eines Entwicklungsprozesskurses oder als Teil eines Softwaretestkurses unterrichtet. Bei der Codierung von 101 Kursen ist es nicht das Ziel der Schüler, Probleme zu lösen, sondern ihnen den Umgang mit verschiedenen Programmierkonzepten beizubringen. Im Allgemeinen werden die meisten Codierungsprojekte 101 und 102 sehr explizit beschreiben, wie das Problem gelöst werden kann. Die Schüler müssen nur verstehen, was sie gelernt haben, um die Aufgabe auf eine Art und Weise zu erledigen, die nicht kopiert und eingefügt werden kann.

Jeder Schüler lernt auf unterschiedliche Weise. Einige Schüler müssen darüber lesen, andere müssen es ihnen mündlich erklären, und andere werden es nur dann bekommen, wenn sie tief im Code stecken. TDD zu lehren, um den Lernprozess zu unterstützen, hilft den meisten Schülern nicht wirklich, und denjenigen, denen es hilft? Die Lehrer müssen entscheiden, ob die Zeit zum Unterrichten von TDD die zusätzliche Lerngeschwindigkeit wert war. Insgesamt ist das Unterrichten einer Lernmethode nicht die Unterrichtszeit wert, die für aktuelle kursspezifische Themen aufgewendet werden könnte. (Im Allgemeinen werden Lern- und Problemlösungsfähigkeiten normalerweise den Schülern überlassen, um selbst zu lernen, da nur der Schüler herausfinden kann, was für sie am besten funktioniert.)

TL: RD; Unterschiedliche Menschen haben unterschiedliche effektive Prozesse. Die Universitäten schreiben nicht vor, wie Sie etwas tun sollen. Geben Sie einfach die Werkzeuge, damit Sie das tun können, was für Sie am besten funktioniert.

1
Tezra

TDD ist ein fantastisches Implementierungswerkzeug, und ich denke, Sie haben Recht damit, dass es von Vorteil ist für diejenigen, die Software schreiben möchten.

Was ist der Grund, warum TDD entweder überhaupt nicht oder zumindest sehr spät an Universitäten unterrichtet wird? Mit anderen Worten, wäre es problematisch, den TDD-Ansatz zu erklären, bevor die Schüler gebeten werden, Listensortieralgorithmen und ähnliches zu schreiben?

Der wahrscheinlich größte Grund ist, dass die Professoren, die diese Programme unterrichten, selten wissen, wie man Software entwickelt, da dies nicht ihr Fachgebiet ist. Wie andere Antworten bereits erwähnt haben, sind Informatik und Software-Engineering unterschiedliche Disziplinen, und ich würde die Erwartung vergleichen, dass Informatik-Studenten Software-Engineering mit Physik-Studenten lernen, die lernen, wie man Autos entwirft. TDD ist eine Fähigkeit, die eine angemessene Menge an Übung erfordert, um wirklich effektiv unterrichten zu können, und Informatikprofessoren verbringen den größten Teil ihrer Karriere mit Informatik. Sie erwarten daher, dass die Fakultät für Informatik TDD wirklich auf eine Art und Weise unterrichten kann Das wird ihre Schüler nicht nur verwirren, ist meiner Meinung nach ziemlich unrealistisch.

Wir müssen Informatik und professionelle Softwareentwicklung als die deutlich getrennten Bereiche behandeln, die sie sind. Wenn Ihr Ziel darin besteht, Informatik zu lernen, sollten Sie nicht mit der Zahlung von Tausenden von Dollar belastet sein, um zu lernen, wie man Websites in React falsch von jemandem, der die letzten 30 Jahre seiner Karriere damit verbracht hat, Grafiken zu erstellen) Theorie auf einer Kreidetafel. Wenn Ihr Ziel darin besteht, Software-Ingenieur zu werden, weiß ich auch nicht, warum Sie 4 Jahre und Zehntausende von Dollar damit verbringen möchten, etwas zu lernen, was im Wesentlichen nur ein bestimmtes Gebiet der Mathematik ist. Es ist gut Um ein grundlegendes Verständnis auf diesem Gebiet zu haben, genau wie jemand, der einen Auspuffkrümmer entwirft, ein gewisses Maß an Physik verstehen muss, braucht die Person, die den Auspuffkrümmer entwirft, jedoch kein allzu tiefes Verständnis in der Quantenmechanik, der speziellen Relativitätstheorie, und Elektromagnetismus, um ihre Arbeit zu erledigen.

Wenn Sie ein Buchhalter sein möchten, können Sie einen Abschluss in Buchhaltung machen und Ihre Professoren werden wahrscheinlich alle zu dem einen oder anderen Zeitpunkt CPAs gewesen sein. Wenn Sie Maschinenbauingenieur werden möchten, können Sie einen Abschluss in Maschinenbau erwerben, und Ihre Professoren waren wahrscheinlich alle zu dem einen oder anderen Zeitpunkt lizenzierte Ingenieure. Wenn Sie jedoch Softwareentwickler werden möchten, ist jeder Abschluss in Softwareentwicklung eigentlich nur ein Abschluss in Informatik, wobei einige Ihrer Wahlfächer bereits für Sie ausgewählt wurden, und fast keiner Ihrer Professoren wird jemals ein professioneller Softwareentwickler gewesen sein. Der Abschluss in Buchhaltung ist nicht Teil der mathematischen Abteilung, und der Abschluss in Maschinenbau ist nicht Teil der Abteilung für Physik, aber der Abschluss in Softwaretechnik wird fast immer Teil der Abteilung für Informatik sein. Bis die Wissenschaft als Ganzes diese beiden Bereiche vollständig in verschiedene Abteilungen unterteilt, die von verschiedenen Mitarbeitern geleitet werden, wird es meiner Meinung nach immer eine lange Liste von Dingen wie TDD geben, die Studenten, die Software-Ingenieure werden möchten, nicht beigebracht werden.

1
Dogs