Esperienza negativa TDD [chiusa]

93

Qual è un aspetto negativo della tua esperienza TDD? Trovate fastidiosi e inutili i piccoli passi (la soluzione più semplice per rendere il test green)? Trovate critici i test senza valore (quando il test ha senso inizialmente ma nell'implementazione finale controlla la stessa logica degli altri test)? ecc.

Le domande di cui sopra riguardano cose a cui sono a disagio durante la mia esperienza TDD. Quindi mi interessa sapere se altri sviluppatori hanno sentimenti simili e cosa pensano di loro.

Sarebbe grato per i link agli articoli che descrivono i lati negativi di TDD (Google è riempito da articoli positivi e spesso fanatici).

    
posta Idsa 04.08.2011 - 09:04
fonte

16 risposte

93

Come tutto ciò che rientra nello striscione "Agile", TDD è qualcosa che suona bene in teoria, ma in pratica non è così chiaro quanto sia bello (e anche come la maggior parte delle cose "Agili", ti viene detto che se tu non mi piace, lo stai facendo male).

La definizione di TDD non è incisa nella pietra: ragazzi come Kent Beck richiedono che un test non di compilazione debba essere scritto prima di una singola riga di codice e che ogni singola riga di codice debba essere scritta per superare un test negativo. Il design frontale è minimo e tutto è driven dai test. Semplicemente non funziona. Ho visto una grande app aziendale sviluppata utilizzando questa metodologia e spero che sia il codice peggiore che vedo nella mia carriera (non sarà molto lontano, e questo nonostante abbia lavorato con alcuni sviluppatori di talento). Da quello che ho visto si traduce in un enorme numero di test mal concepiti che convalidano principalmente che le chiamate di funzione si verificano, che le eccezioni vengono generate quando le variabili sono nulle e il quadro di derisione riceve un allenamento completo (whoop-de-whoop); il tuo codice di produzione viene strongmente associato a questi test e il sogno di un costante e facile refactoring non appare - in effetti le persone hanno ancora meno probabilità di correggere il codice errato a causa di tutti i test che si romperanno. In questo tipo di ambiente, i gestori di software preferiscono avere software scadente con test di superamento e copertura di codice elevato rispetto a un buon software con meno test.

Al contrario, ho sentito persone dire che TDD significa progettare i test in anticipo su un livello elevato come parte della fase di pianificazione, accanto al progetto architettonico. Questi test possono cambiare durante lo sviluppo man mano che maggiori informazioni diventano disponibili, ma sono stati attentamente considerati e offrono una buona guida su ciò che il codice dovrebbe effettivamente fare. Per me ha perfettamente senso.

    
risposta data 28.10.2011 - 16:39
fonte
65

Questo ( Clojure autore) L'intervista di Rich Hickey contiene quanto segue. Mi sento al 100% simpatico:

Life is short and there are only a finite number of hours in a day. So, we have to make choices about how we spend our time. If we spend it writing tests, that is time we are not spending doing something else. Each of us needs to assess how best to spend our time in order to maximize our results, both in quantity and quality. If people think that spending fifty percent of their time writing tests maximizes their results—okay for them. I’m sure that’s not true for me—I’d rather spend that time thinking about my problem. I’m certain that, for me, this produces better solutions, with fewer defects, than any other use of my time. A bad design with a complete test suite is still a bad design.

Un'altra dichiarazione analoga di Donald Knuth nell'intervista del libro Coders at Work , copiata da here :

Seibel: Speaking of practical work, in the middle of working on The Art of Computer Programming you took what turned into a ten-year break to write your typesetting system TeX. I understand you wrote the first version of TeX completely away from the computer.

Knuth: When I wrote TeX originally in 1977 and ’78, of course I didn’t have literate programming but I did have structured programming. I wrote it in a big notebook in longhand, in pencil. Six months later, after I had gone through the whole project, I started typing into the computer. And did the debugging in March of ’78 while I had started writing the program in October of ’77. The code for that is in the Stanford archives—it’s all in pencil—and of course I would come back and change a subroutine as I learned what it should be. This was a first-generation system, so lots of different architectures were possible and had to be discarded until I’d lived with it for a while and knew what was there. And it was a chicken-and-egg problem—you couldn’t typeset until you had fonts but then you couldn’t have fonts until you could typeset. But structured programming gave me the idea of invariants and knowing how to make black boxes that I could understand. So I had the confidence that the code would work when I finally would debug it. I felt that I would be saving a lot of time if I waited six months before testing anything. I had enough confidence that the code was approximately right.

Seibel: And the time savings would be because you wouldn’t spend time building scaffolding and stubs to test incomplete code?

Knuth: Right.

    
risposta data 04.08.2011 - 23:00
fonte
55

La mia esperienza negativa con TDD è stata la mia prima esperienza. TDD suonava alla grande, avevo fatto il QA per anni e avevo ancora gli orrori freschi nella mia mente. Volevo eliminare tutti i bug prima che diventasse una build. Sfortunatamente, l'utilizzo di TDD non garantisce la scrittura di buoni test. In effetti, la mia predisposizione iniziale era scrivere semplici test che generassero un codice semplice. Codice davvero semplice che conteneva poche astrazioni. Test davvero semplici che si intrecciavano con gli interni della classe. E una volta che hai qualche migliaio di test di bitty in atto, non ti sembra che ti stia muovendo più velocemente quando devi cambiarne un centinaio per rifattorizzare il tuo codice per usare il concetto di dominio X molto importante.

La luce si accende per me - TDD non è un'abilità di prova. È un'abilità progettuale. Può solo portarti a un codice buono, semplice e lavorabile con la pratica e una consapevolezza costante delle direzioni di progettazione in cui ti porta. Se stai scrivendo dei test per la copertura del codice, creerai dei test fragili. Se stai scrivendo dei test per aiutarti a progettare le tue astrazioni, allora è solo un modo più rigoroso di scrivere codice top-down. Puoi vedere prima il codice dalla prospettiva del chiamante, che ti incoraggia a semplificare la sua vita, piuttosto che rispecchiare gli interni di una classe al suo limite esterno.

Penso che il TDD sia utile, ma non ne sono dogmatico. Se quei "test senza valore" rendono difficile la manutenzione - Cancellali! Tratto i test allo stesso modo del resto del codice. Se può essere rifatto e rendere le cose più semplici, fallo!

Non l'ho visto personalmente, ma ho sentito che alcuni punti riguardano la copertura del codice di traccia e il conteggio dei test. Quindi se la raccolta delle metriche è un effetto collaterale del TDD, allora potrei vederlo anche come negativo. Eliminerò con entusiasmo 1000 righe di codice, e se questo obsoleto 20 test e la mia percentuale di copertura del codice diminuirà, vabbè.

    
risposta data 05.08.2011 - 13:39
fonte
40

Vado qui su un ramo qui e dichiaro con brutale onestà che è letteralmente una perdita di tempo ritualistica. (Nella maggior parte delle situazioni.)

Ho comprato un libro su Unit Testing che parlava anche di TDD, e mentre concordo con i benefici di UT, dopo circa un centinaio di ore di prove su TDD, ho rinunciato a farlo per una miriade di ragioni. Sono tipo di cross-posting qui, ma TDD:

  1. Non è una documentazione migliore della documentazione reale.
  2. Non cattura bug o regressioni .
  3. Non rende davvero i miei progetti migliori di quelli che finiscono per essere se applichi alcuni concetti di programmazione funzionale e componibilità .
  4. È il tempo che potrebbe essere meglio speso nella revisione del codice o nella documentazione e nelle specifiche di lucidatura.
  5. Fornisce ai gestori un falso senso di sicurezza quando vedono un elenco di centinaia di icone verdi.
  6. Migliora la produttività nell'implementazione di algoritmi con mapping di input-output limitati.
  7. È maldestro in quanto potresti sapere cosa stai facendo come risultato di TDD, ma non stai guadagnando alcuna comprensione del perché funzioni così bene, perché i tuoi disegni escono come fanno loro

Un'altra preoccupazione è il grado di perfezione di cui si deve fare TDD per farlo con successo. Alcuni insistono sul fatto che se TDD non viene eseguito in modo persistente da tutti i membri del team dall'inizio del progetto, soffrirai solo tu. Altri insistono sul fatto che nessuno faccia mai TDD dal libro. Se questi sono entrambi veri, allora ne consegue che i praticanti del TDD stanno soffrendo, che lo capiscano o meno.

Naturalmente, se si sostiene che facendo le cose in un modo simile al TDD arriverai a progetti che possono funzionare facilmente con TDD, beh, ci sono modi molto più rapidi per ottenerlo, cioè studiando davvero i concetti di componibilità. Ci sono un sacco di risorse là fuori, un sacco di teoria matematica rigorosa anche (in gran parte nella programmazione funzionale, ma anche in altri campi). Perché non passare tutto il tempo TDD apprendimento ?

Culturalmente, il TDD mostra i sintomi di essere una pratica rituale. Corre sul senso di colpa; incoraggia la procedura sulla comprensione; ha tonnellate di dottrine e slogan ("fingere fino a che non lo fai" è davvero allarmante se lo guardi oggettivamente). La definizione di Wikipedia della parola "rituale" è in effetti abbastanza pertinente:

In psychology, the term ritual is sometimes used in a technical sense for a repetitive behavior systematically used by a person to neutralize or prevent anxiety; it is a symptom of obsessive–compulsive disorder.

    
risposta data 12.04.2017 - 09:31
fonte
17

Per aggiungere, un'altra preoccupazione con TDD che ho notato è:

Il TDD causa un involontario cambiamento nell'attenzione del team di sviluppo dal codice qualità al test e alla copertura del codice! Personalmente non mi piaceva TDD perché mi rende meno creativo e rende lo sviluppo del software un processo meccanico noioso ! I test unitari sono utili se utilizzati con giudizio ma diventano un peso quando vengono trattati gli obiettivi dello sviluppo del software.

Conosco un ragazzo che è un manager ed è tecnicamente noioso una volta ossessionato da TDD. Era una cosa così magica per lui che credeva avrebbe portato soluzioni magiche a tutti i problemi del suo software scarsamente architettato con il codice meno gestibile. Per non dire cosa è successo a quel progetto - ha fallito miseramente nelle sue mani, mentre tutte le sue prove erano verdi. Immagino che TDD lo abbia aiutato a ottenere qualche tipo di informazione statistica come "99/100 dei miei casi sono verdi" ecc. E questo è stato il motivo della sua ossessione perché non sarebbe mai stato in grado di valutare la qualità o suggerire miglioramenti nel design.

    
risposta data 10.08.2011 - 07:16
fonte
14

La mia esperienza negativa principale è provare a utilizzare TDD per modificare il codice di un altro programmatore che non ha test o test di integrazione molto, molto semplici. Quando vado ad aggiungere una funzione, o risolvere un problema con detto codice; Preferirei scrivere prima un test (il modo TDD). Sfortunatamente, il codice è strettamente accoppiato, e non posso testare nulla senza un sacco di refactoring.

Il refactoring è comunque un ottimo esercizio, ma è obbligatorio per ottenere il codice in uno stato verificabile. E dopo questo passaggio, non ho controlli ed equilibri per vedere se i miei cambiamenti hanno rotto qualcosa; a corto di eseguire l'applicazione ed esaminare ogni caso d'uso.

D'altro canto, l'aggiunta di funzionalità / correzione di bug a un progetto TDD diventa molto semplice. Per natura, il codice scritto con TDD è solitamente abbastanza disaccoppiato con pezzi piccoli con cui lavorare.

In ogni caso, TDD è una linea guida. Seguilo fino al punto in cui trovi che ottieni la massima efficacia. Copertura del test decente e codice disaccoppiato, codice ben scritto.

    
risposta data 04.08.2011 - 17:38
fonte
12

Ho fatto l'esperienza che a volte mi baso troppo sui miei test quando si tratta del design del sistema. Io sono fondamentalmente troppo basso nei dettagli di implementazione nitty-grintosi per fare il passo indietro per guardare al quadro più ampio. Ciò si traduce spesso in un design inutilmente complesso. Lo so, dovrei rifattorizzare il codice ma a volte ho l'impressione che potrei risparmiare un sacco di tempo facendo il passo indietro più spesso.

Detto questo, se hai un framework come binari in cui le tue decisioni architettoniche sono molto limitate, questi problemi sono fondamentalmente inesistenti.

Un altro problema è quando ci si fida ciecamente dei test. La verità è - come qualsiasi altro codice - anche i tuoi test possono avere bug. Quindi sii critico nei confronti dei tuoi test quanto lo sei per la tua implementazione.

    
risposta data 12.11.2018 - 18:58
fonte
11

Come grande fan di TDD, a volte vedo questi inconvenienti

  • Tentazione di scrivere troppi test per ottenere una copertura del codice quasi del 100%. Secondo me non è necessario scrivere test
    • per semplici getter / setter di proprietà
    • per ogni caso in cui viene lanciata un'eccezione
    • che controlla la stessa funzionalità attraverso diversi livelli. (Esempio: se hai un unittest per verificare la validazione dell'input per ogni parametro, allora non è necessario ripetere tutti questi test attraverso un test di integrazione)
  • Costi di manutenzione del codice di prova per test simili, che variano solo leggermente (creati attraverso la duplicazione del codice (nota anche come copia-incolla-eredità)). Se ne hai già uno, è facile crearne uno simile. Tuttavia, se non si effettua il refactoring del codice di test, eliminando la duplicazione del codice in metodi helper, potrebbe essere necessario del tempo per correggere i test se i dettagli dell'implementazione del codice aziendale cambiano.

  • Se hai la pressione del tempo potresti essere tentato di eliminare i test non funzionanti (o commentarli) invece di correggere loro. In questo modo perdi l'investimento nei test

risposta data 15.02.2014 - 02:34
fonte
9

Devo ancora imbattersi in più di uno scenario come sviluppatore di giochi in cui valeva la pena di TDD. E l'istanza in cui si trovava, era un pezzo di codice di natura puramente matematica e aveva bisogno di un solido approccio per testare simultaneamente un numero enorme di casi limite - una necessità rara.

Forse qualcosa, un giorno cambierà idea, ma tra le pratiche XP, l'idea di refactoring , e del codice in evoluzione della sua stessa forma sono molto più importanti e portano per la massima produttività per me, cf. una citazione da un articolo di James Newkirk :

Simplicity - "What is the simplest thing that could possibly work?"
The message is very clear. Given the requirements for today, design and write your software. Do not try to anticipate the future, let the future unfold. It will often do this in very unpredictable ways making anticipation a cost that is often too expensive to afford."

I concetti di coraggio e di stringere i cicli di feedback che egli menziona sono anche, a mio avviso, la chiave della produttività.

    
risposta data 04.08.2011 - 13:20
fonte
7

La mia esperienza TDD negativa, per quanto limitata, è semplicemente sapere da dove cominciare! Ad esempio, proverò a fare qualcosa di TDD e non saprei da dove cominciare a escludere test di cose banali (posso aggiungere un oggetto Foo , posso passare a Quux a Baz , e Mi piace. Test che non testano nulla), o se sto cercando di implementarlo in un progetto esistente, allora trovo che dovrei riscrivere varie classi per poterle usare in TDD. Il risultato finale è che abbandono rapidamente la nozione del tutto.

Probabilmente non aiuta che spesso io sia l'unica persona dell'intera azienda a sapere quale sia il test dell'unità (TDD o altro) e perché sia una buona cosa.

    
risposta data 04.08.2011 - 17:00
fonte
7

zeloti TDD.

Per me, sono solo una lunga fila di matti religiosi che bussano alla mia porta, cercando di dimostrare che il mio modo di fare le cose è irrimediabilmente rotto e l'unica via per la salvezza è Gesù, Kent Back, o Unit Testing.

IMO, la loro più grande bugia è che TDD ti condurrà a salvezza a una migliore progettazione dell'algoritmo. Guarda il famoso solutore Soduku scritto in TDD: qui , qui , qui , qui e qui

E confrontalo con il risolutore di sudoku di Peter Norvig non usando TDD, ma usando l'ingegneria vecchio stile: link

    
risposta data 04.04.2016 - 13:16
fonte
4

Se utilizzi TDD da questi articoli "fanatici", ti verrà in errore la sensazione che il tuo software non abbia errori.

    
risposta data 04.08.2011 - 09:24
fonte
4

TDD ha alcuni vantaggi:

  • Ti concentri su come chiamare il tuo codice e cosa aspettarti prima (mentre scrivi prima il test) invece di concentrarti sulla risoluzione del problema e poi incollare una chiamata dall'applicazione. La modularità semplifica la simulazione e il wrap.
  • I test assicurano che il tuo programma funzioni allo stesso modo prima e dopo un refactoring. Questo non significa che il tuo programma sia privo di errori, ma che continui a funzionare allo stesso modo.

TDD riguarda investimenti a lungo termine. Lo sforzo si ripaga quando si raggiunge la modalità di manutenzione della propria applicazione e se l'applicazione non è pianificata per raggiungere tale punto, è possibile che non si possa mai recuperare l'investimento.

Considero il ciclo rosso-verde TDD con i passi del bambino simili a una lista di controllo per un aereo. È fastidioso e noioso controllare ogni cosa nell'aereo prima del decollo, specialmente se è banalmente semplice (i passi del bambino TDD) ma è stato riscontrato che aumenta la sicurezza. Oltre a verificare che tutto funzioni, essenzialmente ripristina il piano . In altre parole, un aereo viene riavviato prima di ogni decollo.

    
risposta data 04.08.2011 - 22:17
fonte
3

La mia esperienza negativa su TDD è qualcosa che sento con un sacco di cose nuove e pubblicizzate. In effetti mi piace TDD perché garantisce la validità del mio codice, e ancora più importante: posso riconoscere i test falliti, dopo aver aggiunto un nuovo codice o qualsiasi tipo di refactoring.

Ciò che mi infastidisce di TDD è il fatto che ci sono molte regole o linee guida a riguardo. Dato che è ancora abbastanza nuovo, molti di noi hanno esperienza di principianti al TDD. Quindi, ciò che funziona bene per alcuni di noi, potrebbe non funzionare per gli altri. Quello che voglio dire è che non esiste un vero modo "sbagliato o giusto" per eseguire il TDD: c'è il modo in cui funziona per me - e il mio team se ne ho uno.

Quindi, se scrivi dei test - prima o dopo che il codice di produzione non è veramente importante per IMHO - non sono sicuro che il test guidato significhi veramente che devi seguire tutte le linee guida che vengono dichiarate in questo momento, poiché non sono ancora dimostrato di essere la soluzione ideale per il lavoro di tutti i giorni. Se trovi un modo migliore per scrivere i test, devi pubblicarlo in un blog, discuterlo qui o scrivere un articolo a riguardo. Quindi in dieci anni circa avremmo potuto condividere un'esperienza sufficiente per essere in grado di dire quale regola di TDD può essere considerata buona o meno in una determinata situazione.

    
risposta data 05.08.2011 - 08:42
fonte
3

Ho, in più di un'occasione, un codice scritto che ho scartato il giorno successivo da quando era goffo. Ho ricominciato con TDD e la soluzione era migliore. Quindi non ho avuto troppo nella linea dell'esperienza TDD negativa. Tuttavia, detto questo, ho passato del tempo a pensare a un problema ea trovare una soluzione migliore al di fuori dello spazio TDD.

    
risposta data 05.08.2011 - 11:25
fonte
3

Ho trovato che TDD si comporta male quando si tratta di sistemi emergenti. Sono uno sviluppatore di videogiochi e recentemente ho utilizzato TDD per creare un sistema che utilizza più comportamenti semplici per creare movimenti dall'aspetto realistico per un'entità.

Ad esempio, ci sono comportamenti responsabili per allontanarti da aree pericolose di diverso tipo e da persone responsabili di spostarti verso aree interessanti di diverso tipo. Amalgamando l'output di ogni comportamento crea un movimento finale.

Le budella del sistema sono state implementate facilmente e TDD è stato utile qui per specificare di cosa dovrebbe essere responsabile ciascun sottosistema.

Tuttavia mi sono imbattuto in problemi quando si trattava di specificare come interagiscono i comportamenti e, ancora più importante, come interagiscono nel tempo. Spesso non c'era una risposta giusta e, sebbene i miei primi test fossero passati, la QA poteva continuare a trovare casi limite in cui il sistema non funzionava. Per trovare la soluzione corretta ho dovuto ripetere iteraggi diversi e, se avessi aggiornato i test ogni volta per riflettere i nuovi comportamenti prima di controllare che funzionassero nel gioco, potrei aver finito per buttare via i test più e più volte. Così ho cancellato quei test.

Avrei dovuto possedere test più potenti che hanno catturato i casi limite scoperti dal QA, ma quando hai un sistema come questo che si trova in cima a molti sistemi fisici e di gameplay, e hai a che fare con comportamenti nel tempo, diventa un po 'un incubo per specificare esattamente cosa sta succedendo.

Quasi certamente ho commesso degli errori nel mio approccio, e come ho detto per il coraggio del sistema TDD ha funzionato brillantemente, e persino supportato alcuni refactoring ottimizzanti.

    
risposta data 09.08.2011 - 09:54
fonte

Leggi altre domande sui tag