Was verliere ich durch testgetriebenes Design?
Nur Negative auflisten; Nennen Sie keine negativ geschriebenen Leistungen.
unit-testing
testing
tdd
IanL
quelle
quelle
Antworten:
Mehrere Nachteile (und ich behaupte nicht, dass es keine Vorteile gibt - insbesondere beim Schreiben der Grundlage eines Projekts - es würde am Ende viel Zeit sparen):
quelle
Wenn Sie "echtes" TDD durchführen möchten (lesen Sie: Testen Sie zuerst mit den Schritten Rot, Grün und Refactor), müssen Sie auch Mocks / Stubs verwenden, wenn Sie Integrationspunkte testen möchten.
Wenn Sie nach einer Weile mit der Verwendung von Mocks beginnen, sollten Sie mit der Verwendung von Dependency Injection (DI) und einem IoC-Container (Inversion of Control) beginnen. Um dies zu tun, müssen Sie Schnittstellen für alles verwenden (die selbst viele Fallstricke haben).
Am Ende des Tages müssen Sie viel mehr Code schreiben, als wenn Sie es einfach auf die "einfache alte Art" tun. Anstelle einer Kundenklasse müssen Sie auch eine Schnittstelle, eine Scheinklasse, eine IoC-Konfiguration und einige Tests schreiben.
Und denken Sie daran, dass der Testcode auch gepflegt und gepflegt werden sollte. Tests sollten genauso lesbar sein wie alles andere und es braucht Zeit, um guten Code zu schreiben.
Viele Entwickler verstehen nicht ganz, wie man all dies "richtig" macht. Aber weil ihnen jeder sagt, dass TDD der einzig wahre Weg ist, Software zu entwickeln, versuchen sie einfach das Beste, was sie können.
Es ist viel schwieriger als man denkt. Oft haben Projekte, die mit TDD durchgeführt wurden, eine Menge Code, den niemand wirklich versteht. Die Unit-Tests testen oft das Falsche, den falschen Weg. Und niemand ist sich einig, wie ein guter Test aussehen soll, nicht einmal die sogenannten Gurus.
All diese Tests machen es viel schwieriger, das Verhalten Ihres Systems zu "ändern" (im Gegensatz zum Refactoring), und einfache Änderungen werden einfach zu schwierig und zeitaufwändig.
Wenn Sie die TDD-Literatur lesen, gibt es immer einige sehr gute Beispiele, aber in realen Anwendungen müssen Sie häufig über eine Benutzeroberfläche und eine Datenbank verfügen. Hier wird TDD sehr schwierig, und die meisten Quellen bieten keine guten Antworten. Und wenn doch, dann immer mehr Abstraktionen: Scheinobjekte, Programmierung auf eine Schnittstelle, MVC / MVP-Muster usw., die wiederum viel Wissen erfordern, und ... Sie müssen noch mehr Code schreiben.
Seien Sie also vorsichtig ... Wenn Sie kein begeistertes Team und mindestens einen erfahrenen Entwickler haben, der weiß, wie man gute Tests schreibt und auch ein paar Dinge über gute Architektur weiß, müssen Sie wirklich zweimal überlegen, bevor Sie den TDD-Weg gehen .
quelle
Wenn Sie an einem Punkt angelangt sind, an dem Sie eine große Anzahl von Tests haben, müssen Sie zum Ändern des Systems möglicherweise einige oder alle Ihrer Tests neu schreiben, je nachdem, welche durch die Änderungen ungültig wurden. Dies könnte eine relativ schnelle Änderung in eine sehr zeitaufwändige ändern.
Möglicherweise treffen Sie auch Entwurfsentscheidungen, die mehr auf TDD als auf tatsächlich guten Entwurfsprinzipalen basieren. Während Sie möglicherweise eine sehr einfache Lösung hatten, mit der sich die Anforderungen von TDD nicht testen lassen, haben Sie jetzt ein viel komplexeres System, das tatsächlich anfälliger für Fehler ist.
quelle
if part of the system is covered by tests and they pass, then everything is fine (including design)
.Ich denke, das größte Problem für mich ist der RIESIGE Zeitverlust, den ich brauche, um mich darauf einzulassen. Ich bin noch sehr am Anfang meiner Reise mit TDD (siehe mein Blog für Updates meiner Testabenteuer, wenn Sie interessiert sind) und ich habe buchstäblich Stunden verbracht , loszulegen.
Es dauert lange, bis Ihr Gehirn in den "Testmodus" wechselt, und das Schreiben von "testbarem Code" ist eine Fähigkeit für sich.
TBH, ich bin mit Respekt nicht einverstanden Jason Cohens Kommentaren zur Veröffentlichung privater Methoden , darum geht es nicht. Ich habe in meiner neuen Arbeitsweise nicht mehr öffentliche Methoden angewendet als zuvor . Es beinhaltet jedoch Änderungen an der Architektur und ermöglicht es Ihnen, Codemodule "Hot Plug" zu machen, um alles andere einfacher zu testen. Das solltest du nicht die Interna des Codes besser zugänglich werden machen , dies zu tun. Ansonsten sind wir wieder auf dem ersten Platz, da alles öffentlich ist. Wo ist die Verkapselung darin?
Also, (IMO) auf den Punkt gebracht:
PS: Wenn Sie Links zu Positiven wünschen, habe ich mehrere Fragen dazu gestellt und beantwortet. Schauen Sie sich mein Profil an .
quelle
In den wenigen Jahren, in denen ich Test Driven Development praktiziert habe, muss ich sagen, dass die größten Nachteile sind:
Verkauf an das Management
Verkauf an andere Entwickler
Pflege des Testcodes zusammen mit Ihrem Produktionscode
Schreiben von Tests, damit Sie alles abdecken (100% Codeabdeckung)
Damit würde ich jedoch sagen, dass die Vorteile von TDD die Nachteile für die einfache Idee bei weitem überwiegen, dass Sie es tun werden, wenn Sie eine gute Reihe von Tests erzielen können, die Ihre Anwendung abdecken, aber nicht so zerbrechlich sind, dass eine Änderung sie alle bricht Sie können an Tag 300 Ihres Projekts immer wieder neue Funktionen hinzufügen, wie Sie es an Tag 1 getan haben. Dies passiert nicht bei allen, die TDD ausprobieren und glauben, es sei ein Wundermittel für all ihren fehlerbehafteten Code, und sie glauben, dass dies möglich ist funktioniert nicht, Punkt.
Persönlich habe ich festgestellt, dass ich mit TDD einfacheren Code schreibe, weniger Zeit damit verbringe, darüber zu debattieren, ob eine bestimmte Codelösung funktioniert oder nicht, und dass ich keine Angst habe, eine Codezeile zu ändern, die die von festgelegten Kriterien nicht erfüllt Die Mannschaft.
TDD ist eine schwierige Disziplin, und ich bin seit einigen Jahren dabei und lerne immer wieder neue Testtechniken. Es ist eine enorme Zeitinvestition im Voraus, aber auf lange Sicht wird Ihre Nachhaltigkeit viel größer sein, als wenn Sie keine automatisierten Komponententests hätten. Wenn nur meine Chefs das herausfinden könnten.
quelle
Bei Ihrem ersten TDD-Projekt gibt es zwei große Verluste: Zeit und persönliche Freiheit
Sie verlieren Zeit, weil:
Sie verlieren die persönliche Freiheit, weil:
Hoffe das hilft
quelle
Bei TDD müssen Sie planen, wie Ihre Klassen funktionieren, bevor Sie Code schreiben, um diese Tests zu bestehen. Dies ist sowohl ein Plus als auch ein Minus.
Es fällt mir schwer, Tests in einem "Vakuum" zu schreiben - bevor Code geschrieben wurde. Nach meiner Erfahrung neige ich dazu, über meine Tests zu stolpern, wenn ich beim Schreiben meiner Klassen unweigerlich an etwas denke, das ich beim Schreiben meiner ersten Tests vergessen habe. Dann ist es Zeit, nicht nur meine Klassen, sondern auch meine Tests umzugestalten. Wiederholen Sie dies drei oder vier Mal und es kann frustrierend werden.
Ich ziehe es vor, zuerst einen Entwurf meiner Klassen zu schreiben und dann eine Reihe von Unit-Tests zu schreiben (und zu warten). Nachdem ich einen Entwurf habe, funktioniert TDD gut für mich. Wenn beispielsweise ein Fehler gemeldet wird, schreibe ich einen Test, um diesen Fehler auszunutzen, und behebe dann den Code, damit der Test erfolgreich ist.
quelle
Prototyping kann mit TDD sehr schwierig sein. Wenn Sie sich nicht sicher sind, welchen Weg Sie zu einer Lösung einschlagen sollen, kann es schwierig sein, die Tests im Voraus zu schreiben (außer bei sehr umfassenden). Dies kann ein Schmerz sein.
Ehrlich gesagt glaube ich nicht, dass es für die "Kernentwicklung" bei der überwiegenden Mehrheit der Projekte einen wirklichen Nachteil gibt; Es wird viel mehr geredet, als es sein sollte, normalerweise von Leuten, die glauben, dass ihr Code gut genug ist, dass sie keine Tests benötigen (es ist nie so), und von Leuten, die einfach nicht die Mühe haben, sie zu schreiben.
quelle
Nun, und diese Dehnung müssen Sie Ihre Tests debuggen. Es gibt auch einen gewissen Zeitaufwand für das Schreiben der Tests, obwohl die meisten Leute der Meinung sind, dass es sich um eine Vorabinvestition handelt, die sich über die Lebensdauer der Anwendung sowohl beim zeitsparenden Debuggen als auch bei der Stabilität auszahlt.
Das größte Problem, das ich persönlich damit hatte, ist es, die Disziplin aufzubauen, um die Tests tatsächlich zu schreiben. In einem Team, insbesondere in einem etablierten Team, kann es schwierig sein, sie davon zu überzeugen, dass sich die aufgewendete Zeit lohnt.
quelle
Wenn Ihre Tests nicht sehr gründlich sind, könnten Sie in ein falsches Gefühl von "alles funktioniert" geraten, nur weil Sie die Tests bestehen. Theoretisch funktioniert der Code, wenn Ihre Tests bestanden wurden. Aber wenn wir beim ersten Mal perfekt Code schreiben könnten, bräuchten wir keine Tests. Die Moral hier ist, sicherzustellen, dass Sie selbst eine Überprüfung der geistigen Gesundheit durchführen, bevor Sie etwas Vollständiges anrufen. Verlassen Sie sich nicht nur auf die Tests.
In diesem Sinne, wenn Ihre Überprüfung der geistigen Gesundheit etwas findet, das nicht getestet wurde, gehen Sie zurück und schreiben Sie einen Test dafür.
quelle
Der Nachteil von TDD ist, dass es normalerweise eng mit der 'Agile'-Methodik verbunden ist Dokumentation eines Systems keine Rolle spielt, sondern das Verständnis, warum ein Test einen bestimmten Wert zurückgeben sollte, anstatt dass irgendein anderer nur beim Entwickler liegt Kopf.
Sobald der Entwickler den Grund verlässt oder vergisst, dass der Test einen bestimmten Wert und keinen anderen zurückgibt, sind Sie fertig. TDD ist in Ordnung, wenn es angemessen dokumentiert und von einer lesbaren Dokumentation (dh einem spitzen Manager) umgeben ist, auf die in 5 Jahren verwiesen werden kann, wenn sich die Welt ändert und Ihre App dies auch muss.
Wenn ich von Dokumentation spreche, ist dies kein Klappentext im Code, sondern eine offizielle Schrift, die außerhalb der Anwendung existiert, wie z. B. Anwendungsfälle und Hintergrundinformationen, auf die Manager, Anwälte und der arme Kerl, der aktualisiert werden muss, verweisen können Ihr Code im Jahr 2011.
quelle
Ich habe mehrere Situationen erlebt, in denen TDD mich verrückt macht. Um einige zu nennen:
Wartbarkeit des Testfalls:
Wenn Sie in einem großen Unternehmen tätig sind, besteht die Möglichkeit, dass Sie die Testfälle nicht selbst schreiben müssen oder zumindest die meisten davon von jemand anderem geschrieben werden, wenn Sie in das Unternehmen eintreten. Die Funktionen einer Anwendung ändern sich von Zeit zu Zeit. Wenn Sie kein System wie das HP Quality Center haben, um sie zu verfolgen, werden Sie in kürzester Zeit verrückt.
Dies bedeutet auch, dass neue Teammitglieder ziemlich viel Zeit benötigen, um zu erfahren, was mit den Testfällen los ist. Dies kann wiederum dazu führen, dass mehr Geld benötigt wird.
Komplexität der Testautomatisierung:
Wenn Sie einige oder alle Testfälle in maschinenlaufbare Testskripte automatisieren, müssen Sie sicherstellen, dass diese Testskripte mit den entsprechenden manuellen Testfällen synchron sind und den Anwendungsänderungen entsprechen.
Außerdem verbringen Sie Zeit damit, die Codes zu debuggen, mit denen Sie Fehler erkennen können. Meiner Meinung nach sind die meisten dieser Fehler darauf zurückzuführen, dass das Testteam die Anwendungsänderungen im Automatisierungstestskript nicht berücksichtigt hat. Änderungen in der Geschäftslogik, der Benutzeroberfläche und anderen internen Dingen können dazu führen, dass Ihre Skripte nicht mehr oder nicht mehr zuverlässig ausgeführt werden. Manchmal sind die Änderungen sehr subtil und schwer zu erkennen. Einmal meldeten alle meine Skripte einen Fehler, weil sie ihre Berechnung auf Informationen aus Tabelle 1 basierten, während Tabelle 1 jetzt Tabelle 2 war (weil jemand den Namen der Tabellenobjekte im Anwendungscode ausgetauscht hatte).
quelle
Das größte Problem sind die Leute, die nicht wissen, wie man richtige Unit-Tests schreibt. Sie schreiben Tests, die voneinander abhängen (und sie funktionieren hervorragend mit Ant, aber dann scheitern sie plötzlich, wenn ich sie von Eclipse aus ausführe, nur weil sie in unterschiedlicher Reihenfolge ausgeführt werden). Sie schreiben Tests, die nichts Besonderes testen - sie debuggen einfach den Code, überprüfen das Ergebnis und ändern ihn in Test, indem sie ihn "test1" nennen. Sie erweitern den Umfang der Klassen und Methoden, nur weil es einfacher sein wird, Unit-Tests für sie zu schreiben. Der Code von Unit-Tests ist schrecklich, mit all den klassischen Programmierproblemen (starke Kopplung, Methoden mit einer Länge von 500 Zeilen, hartcodierten Werten, Codeduplizierung) und eine Hölle, die es zu pflegen gilt. Aus irgendeinem seltsamen Grund behandeln Leute Unit-Tests als etwas, das dem "echten" Code unterlegen ist, und sie tun es nicht. Ich kümmere mich überhaupt nicht um ihre Qualität. :-(
quelle
Sie verlieren viel Zeit damit, Tests zu schreiben. Dies könnte natürlich bis zum Ende des Projekts gespeichert werden, indem Fehler schneller erkannt werden.
quelle
Der größte Nachteil ist, dass Sie viel scheitern müssen, wenn Sie TDD wirklich richtig machen wollen, bevor Sie Erfolg haben. Wenn man bedenkt, wie viele Softwareunternehmen arbeiten (Dollar pro KLOC), werden Sie schließlich entlassen. Selbst wenn Ihr Code schneller, sauberer, einfacher zu warten und weniger Fehler aufweist.
Wenn Sie in einem Unternehmen arbeiten, das Sie durch die KLOCs bezahlt (oder die implementierten Anforderungen - auch wenn sie nicht getestet wurden), halten Sie sich von TDD (oder Codeüberprüfungen oder Paarprogrammierung oder kontinuierlicher Integration usw. usw. usw.) fern.
quelle
Sie verlieren die Fähigkeit zu sagen, dass Sie "fertig" sind, bevor Sie Ihren gesamten Code testen.
Sie verlieren die Fähigkeit, Hunderte oder Tausende von Codezeilen zu schreiben, bevor Sie sie ausführen.
Sie verlieren die Möglichkeit, durch Debuggen zu lernen.
Sie verlieren die Flexibilität, Code zu versenden, dessen Sie sich nicht sicher sind.
Sie verlieren die Freiheit, Ihre Module eng zu koppeln.
Sie verlieren die Möglichkeit, das Schreiben von Konstruktionsdokumentationen auf niedriger Ebene zu überspringen.
Sie verlieren die Stabilität, die mit Code einhergeht, den jeder fürchten muss.
quelle
Ich stimme der Antwort über die anfängliche Entwicklungszeit zu. Sie verlieren auch die Fähigkeit, bequem ohne die Sicherheit von Tests zu arbeiten. Ich wurde auch als TDD-Nutbar beschrieben, sodass du ein paar Freunde verlieren könntest;)
quelle
Es wird als langsamer wahrgenommen. Langfristig ist das nicht wahr in Bezug auf die Trauer, die Sie später retten werden, aber Sie werden am Ende mehr Code schreiben, so dass Sie wahrscheinlich Zeit damit verbringen, "nicht zu codieren" zu testen. Es ist ein fehlerhaftes Argument, aber Sie haben gefragt!
quelle
Sich auf schwierige, unvorhergesehene Anforderungen zu konzentrieren, ist der ständige Fluch des Programmierers. Testgetriebene Entwicklung zwingt Sie, sich auf die bereits bekannten, alltäglichen Anforderungen zu konzentrieren, und beschränkt Ihre Entwicklung auf das, was Sie sich bereits vorgestellt haben.
Denken Sie darüber nach, es ist wahrscheinlich, dass Sie bestimmte Testfälle entwerfen, sodass Sie nicht kreativ werden und denken: "Es wäre cool, wenn der Benutzer X, Y und Z ausführen könnte." Wenn sich dieser Benutzer über die möglichen coolen Anforderungen X, Y und Z aufregt, ist Ihr Design möglicherweise zu stark auf bereits festgelegte Testfälle ausgerichtet, und es ist schwierig, sie anzupassen.
Dies ist natürlich ein zweischneidiges Schwert. Wenn Sie Ihre ganze Zeit damit verbringen, für jedes denkbare, vorstellbare X, Y und Z zu entwerfen, das ein Benutzer jemals haben möchte, werden Sie unweigerlich nie etwas fertigstellen. Wenn Sie etwas vervollständigen, kann niemand (einschließlich Sie selbst) eine Vorstellung davon haben, was Sie in Ihrem Code / Design tun.
quelle
Das Schreiben von Tests für "zufällige" Daten wie XML-Feeds und Datenbanken kann schwierig und zeitaufwändig sein (nicht so schwierig). Ich habe in letzter Zeit einige Zeit damit verbracht, mit Wetterdaten-Feeds zu arbeiten. Es ist ziemlich verwirrend, Tests dafür zu schreiben, zumindest weil ich nicht zu viel Erfahrung mit TDD habe.
quelle
Sie verlieren große Klassen mit mehreren Verantwortlichkeiten. Sie werden wahrscheinlich auch große Methoden mit mehreren Verantwortlichkeiten verlieren. Möglicherweise verlieren Sie die Fähigkeit zur Umgestaltung, aber Sie verlieren auch einen Teil der Notwendigkeit zur Umgestaltung.
Jason Cohen sagte so etwas wie: TDD erfordert eine bestimmte Organisation für Ihren Code. Dies könnte architektonisch falsch sein; Da private Methoden beispielsweise nicht außerhalb einer Klasse aufgerufen werden können, müssen Sie Methoden nicht privat machen, um sie testbar zu machen.
Ich sage, dies deutet auf eine fehlende Abstraktion hin. Wenn der private Code wirklich getestet werden muss, sollte er sich wahrscheinlich in einer separaten Klasse befinden.
Dave Mann
quelle
Sie müssen Anwendungen auf eine andere Art und Weise schreiben: eine, die sie testbar macht. Sie wären überrascht, wie schwierig dies zunächst ist.
Einige Leute finden das Konzept, darüber nachzudenken, was sie schreiben werden, bevor sie es zu schwer schreiben. Konzepte wie Spott können auch für manche schwierig sein. TDD in Legacy-Apps kann sehr schwierig sein, wenn sie nicht zum Testen entwickelt wurden. TDD um Frameworks, die nicht TDD-freundlich sind, kann ebenfalls ein Kampf sein.
TDD ist eine Fähigkeit, mit der Junior-Entwickler zunächst Schwierigkeiten haben können (hauptsächlich, weil ihnen nicht beigebracht wurde, auf diese Weise zu arbeiten).
Insgesamt werden die Nachteile jedoch gelöst, wenn die Leute kompetent werden und Sie am Ende den "stinkenden" Code abstrahieren und ein stabileres System haben.
quelle
Es dauert einige Zeit, um sich darauf einzulassen, und einige Zeit, um in einem Projekt damit zu beginnen, aber ... Ich bedauere immer, dass ich keinen testgetriebenen Ansatz gewählt habe, wenn ich dumme Fehler finde, die ein automatisierter Test sehr schnell hätte finden können. Darüber hinaus verbessert TDD die Codequalität.
quelle
quelle
Gute Antworten alle. Ich würde ein paar Möglichkeiten hinzufügen, um die dunkle Seite von TDD zu vermeiden:
Ich habe Apps geschrieben, um ihren eigenen randomisierten Selbsttest durchzuführen. Das Problem beim Schreiben spezifischer Tests besteht darin, dass selbst wenn Sie viele davon schreiben, diese nur die Fälle abdecken, an die Sie denken. Zufallstestgeneratoren finden Probleme, an die Sie nicht gedacht haben.
Das gesamte Konzept vieler Komponententests impliziert, dass Sie Komponenten haben, die in ungültige Zustände geraten können, z. B. komplexe Datenstrukturen. Wenn Sie sich von komplexen Datenstrukturen fernhalten, müssen Sie viel weniger testen.
Wenn Ihre Anwendung dies zulässt, sollten Sie sich vor einem Design scheuen, das auf der richtigen Reihenfolge von Benachrichtigungen, Ereignissen und Nebenwirkungen beruht. Diese können leicht fallen gelassen oder durcheinander gebracht werden, so dass sie viele Tests benötigen.
quelle
TDD erfordert eine bestimmte Organisation für Ihren Code. Dies kann ineffizient oder schwer zu lesen sein. Oder sogar architektonisch falsch; zum Beispiel seit
private
Methoden nicht außerhalb einer Klasse aufgerufen werden können, müssen Sie Methoden nicht privat machen, um sie testbar zu machen, was einfach falsch ist.Wenn sich der Code ändert, müssen Sie auch die Tests ändern. Mit Refactoring kann dies eine Menge zusätzlicher Arbeit sein.
quelle
Lassen Sie mich hinzufügen, dass Sie, wenn Sie BDD-Prinzipien auf ein TDD-Projekt anwenden, einige der hier aufgeführten Hauptnachteile (Verwirrung, Missverständnisse usw.) beseitigen können. Wenn Sie mit BDD nicht vertraut sind, sollten Sie die Einführung von Dan North lesen. Er entwickelte das Konzept als Antwort auf einige der Probleme, die sich aus der Anwendung von TDD am Arbeitsplatz ergaben. Dans Einführung in BDD finden Sie hier .
Ich mache diesen Vorschlag nur, weil BDD einige dieser Negative anspricht und als Lückenstopp fungiert. Sie sollten dies berücksichtigen, wenn Sie Ihr Feedback sammeln.
quelle
Sie müssen sicherstellen, dass Ihre Tests immer auf dem neuesten Stand sind. Sobald Sie rote Ampeln ignorieren, werden die Tests bedeutungslos.
Sie müssen auch sicherstellen, dass die Tests umfassend sind, oder sobald ein großer Fehler auftritt, wird sich der stickige Verwaltungstyp beschweren, von dem Sie schließlich überzeugt sind, dass Sie Zeit damit verbringen, mehr Code zu schreiben.
quelle
Die Person, die meinem Team agile Entwicklung beigebracht hat, glaubte nicht an Planung, Sie haben nur so viel für die kleinste Anforderung geschrieben.
Sein Motto war Refactor, Refactor, Refactor. Ich habe verstanden, dass Refactor bedeutet, nicht vorauszuplanen.
quelle
Die Entwicklungszeit erhöht sich: Jede Methode muss getestet werden. Wenn Sie eine große Anwendung mit Abhängigkeiten haben, müssen Sie Ihre Daten für Tests vorbereiten und bereinigen.
quelle