Going TDD nel bel mezzo del progetto

7

Vogliono che sviluppiamo nuove funzionalità di un prodotto con TDD. So che di solito non scrivono test per il codice legacy di moduli già sviluppati.

Ma ancora, che cosa succede se nuove funzionalità devono essere aggiunte ai moduli precedenti e vogliamo ancora attaccarci a TDD?

    
posta Vladimir Stazhilov 07.02.2015 - 15:38
fonte

2 risposte

10

Il problema che potresti colpire rapidamente è che per testare un particolare pezzo di codice, dovresti rendere testabile il codice che lo circonda. La modifica del codice circostante richiede anche test, il che, a sua volta, richiede ulteriori modifiche.

Esempio pratico. Un anno fa, ho dovuto lavorare su ... chiamiamolo sistema legacy . Milioni di righe di codice C #. Indice di manutenibilità (MI) che raggiunge a volte zero (suggerimento per chi non ha mai utilizzato l'MI in Visual Studio: scendere sotto l'MI di 50 è abbastanza difficile: devi davvero iniziare a scrivere codice spaghetti di proposito). Metodi contenenti fino a 4 000 LOC di codice procedurale. E ovviamente zero test , perché, francamente, tutti sanno scrivere e mantenere i costi di denaro.

Poiché l'aggiunta della funzione di base stava causando ore o giorni di spreco di tempo (oltre a sprecare tempo risolvendo bug scoperti successivamente in produzione, quindi giorni risolvendo i bug introdotti quando si risolvevano i bug precedenti), stavo pensando di aggiungere almeno un po ' di test.

Quando ho lasciato un progetto, c'erano effettivamente alcune centinaia di test. Questi test riguardavano le parti del codice che inserivo in classi separate e che erano abbastanza indipendenti dal resto del codice. Questo è abbastanza facile da fare, ma anche non molto utile. Sì, quei test coprivano alcune regole aziendali, ma il loro scopo era molto limitato.

Stavo anche pensando di aggiungere test più sostanziali, ma senza successo.

  • Il problema principale era che quasi ogni pezzo di codice si basava sul database. Ho provato, su supporto cartaceo, ad astrarre il database per poterlo sostituire con mock e stub. Sulla carta, ha funzionato, ma richiederebbe una quantità enorme di tempo per implementare realmente.

  • Un altro problema, ovviamente, era l'aspetto spaghetti del codice. Come testare l'unità con un metodo LOC da 4 000 che ha bisogno di passare 16 parametri, dato che quei parametri non sono documentati (e nessuno sa veramente come dovrebbero essere usati) e provare a rimpiazzarli con stub causa stranezze? bug in luoghi strani?

Quindi sì, è possibile introdurre test, incluso lo sviluppo basato su test, sulle parti che vengono modificate, ma se la base di codice è un disastro, l'ambito di tali test sarà troppo piccolo per essere particolarmente utile.

Quello che posso suggerire personalmente è di iniziare a refactoring moduli uno per uno (si spera che stiano interagendo attraverso le interfacce e siano abbastanza indipendenti l'uno dall'altro), e garantendo che quei moduli abbiano dei test. Una volta che hai una copertura di codice sufficiente, noterai che testare nuove funzionalità è molto più semplice.

    
risposta data 07.02.2015 - 17:13
fonte
1

Ho avuto un'esperienza simile a MainMa descritta in la sua risposta .

Ho iniziato a lavorare nel bel mezzo di un progetto che aveva un codice spaghetti, alcuni test unitari ma con alcuni commenti spezzati o commentati, molte classi di dio e una cattiva progettazione dell'architettura che richiedeva allo sviluppatore di cambiare 10 o 12 file solo aggiungere un DropDownList che recupera i dati dal database.

Quando cerchi di usare TDD in un progetto del genere, avrai difficoltà a rimuovere il codice strettamente accoppiato, fingere cose e lo scopo dei test potrebbe finire molto limitato. Il refactoring è la soluzione migliore, ma sappiamo che se il debito tecnico è veramente alto, nessuno è disposto a pagare per questo .

Tuttavia, anche nei progetti di manutenzione, alcune funzionalità saranno abbastanza grandi da richiedere un nuovo servizio o una nuova pagina Web . Quando arriva il momento, cogli l'opportunità di costruirlo usando TDD, buoni schemi di progettazione e di usare una nuova architettura, se necessario. L'obiettivo è interrompere il ciclo del codice errato e interrompere le scelte disordinate di copia e incolla.

Con questo approccio, non pagherai il debito tecnico, ma puoi ridurlo in termini assoluti e, cosa più importante, sommergerlo in termini relativi.

In pochi mesi abbiamo avuto due lati distinti all'interno della stessa soluzione: uno in buona salute che è servito come esempio per gli sviluppatori junior per continuare il lavoro e un altro che abbiamo chiamato la parte "malata".

TL; DR

Rifattorizzare il vecchio codice per consentire a TDD è la soluzione migliore, ma il tuo manager potrebbe non autorizzarti a trascorrere il tuo tempo con questo. Almeno, prova a creare nuove funzionalità / moduli con buone pratiche invece di copiare e incollare codice brutto.

    
risposta data 03.11.2015 - 02:52
fonte

Leggi altre domande sui tag