Ho visto alcune volte il libro Lavorare efficacemente con il codice legacy . Quali sono i punti chiave di questo libro?
C'è molto di più da fare con il codice legacy che aggiungere test unitari / di integrazione e quindi refactoring?
Ho visto alcune volte il libro Lavorare efficacemente con il codice legacy . Quali sono i punti chiave di questo libro?
C'è molto di più da fare con il codice legacy che aggiungere test unitari / di integrazione e quindi refactoring?
Risposte:
Il problema chiave con il codice legacy è che non ha test. Quindi è necessario aggiungere alcuni (e poi altro ...).
Questo di per sé richiederebbe molto lavoro, come ha notato @mattnz. Ma il problema speciale del codice legacy è che non è mai stato progettato per essere testabile . Quindi in genere è un enorme casino contorto di codice spaghetti, in cui è molto difficile o assolutamente impossibile isolare piccole parti da testare. Quindi, prima del test unitario, è necessario riformattare il codice per renderlo più testabile.
Tuttavia, al fine di effettuare il refactoring in modo sicuro, è necessario disporre di test unitari per verificare di non aver rotto nulla con le modifiche ... Questa è la cattura 22 del codice legacy.
Il libro ti insegna come uscire da questo problema apportando le modifiche minime e più sicure al codice solo per abilitare i test della prima unità. Questi non hanno lo scopo di rendere il design più gradevole, ma solo di abilitare i test unitari. In effetti, a volte rendono il design più brutto o più complesso. Tuttavia, ti consentono di scrivere test e, una volta che hai messo in atto i test unitari, sei libero di migliorare il design.
Ci sono molti trucchi per rendere testabile il codice - alcuni sono in qualche modo ovvi, altri no. Ci sono metodi che non avrei mai pensato a me stesso, senza leggere il libro. Ma ciò che è ancora più importante è che Feathers spiega cosa rende precisamente testabile un'unità di codice. Devi tagliare le dipendenze e introdurre barriere nel tuo codice, ma per due motivi distinti:
Tagliare le dipendenze in modo sicuro può essere complicato. L'introduzione di interfacce, simulazioni e dipendenza dall'iniezione è pulita e piacevole come obiettivo, ma non è necessariamente sicuro da fare a questo punto. Quindi a volte dobbiamo ricorrere alla sottoclasse della classe sotto test al fine di sovrascrivere un metodo che normalmente ad esempio avvia una richiesta diretta a un DB. Altre volte, potremmo anche aver bisogno di sostituire una classe di dipendenza / jar con una falsa nell'ambiente di test ...
Per me, il concetto più importante introdotto da Feathers è la cucitura . Una cucitura è un punto nel codice in cui puoi cambiare il comportamento del tuo programma senza modificare il codice stesso . La creazione di giunzioni nel codice consente di separare il pezzo di codice in prova, ma consente anche di rilevare il comportamento del codice in prova anche quando è difficile o impossibile eseguire direttamente (ad esempio perché la chiamata apporta modifiche in un altro oggetto o sottosistema , il cui stato non è possibile eseguire una query direttamente dall'interno del metodo di test).
Questa conoscenza ti consente di notare i semi della testabilità nel mucchio di codice più cattivo e di trovare le modifiche minime, meno dirompenti e più sicure per arrivarci. In altre parole, per evitare di rendere "ovvi" i refactoring che rischiano di infrangere il codice senza che te ne accorga, perché non hai ancora i test unitari per rilevarlo.
Modi rapidi per ottenere i punti chiave di lavorare in modo efficace con il codice legacy
Lavoro su una base di codice di milioni di righe di codice, alcune risalenti agli anni '80. È solo un software, quindi è solo una questione di scrivere alcuni test unitari, quindi puoi andare e semplicemente riformattarlo e renderlo molto migliore.
La parola chiave qui è solo - è una parola di quattro lettere che non appartiene al vocabolario di nessun programmatore, per non parlare di uno che sta lavorando su sistemi legacy.
Quanto pensi che ci voglia per scrivere un unit test, per testare un'ora di sforzo di sviluppo? Per amor di discussione, diciamo un'altra ora.
Quanto tempo viene investito in quel sistema legacy di 20 milioni di anni fa? Diciamo, 20 sviluppatori per 20 anni volte 2000 ore all'anno (hanno lavorato abbastanza duramente). Ora scegliamo un numero: hai nuovi computer e nuovi strumenti e sei molto più intelligente dei ragazzi che hanno scritto questo pezzo di $% ^^ in primo luogo, diciamo che ne vali 10. Hai 40 anni uomo, beh, hai ...?
Quindi la risposta alla tua domanda è che c'è molto di più. Ad esempio, quella routine ha 1000 righe (ne ho alcune che sono oltre 5000), è eccessivamente complessa ed è un pezzo di spaghetti. Ci vorranno solo (ancora un'altra parola di quattro lettere) un paio di giorni per ricodificarla in poche routine di 100 linee e qualche altro aiuto di 20 righe, giusto? SBAGLIATO. In quelle 1000 righe sono nascoste 100 correzioni di bug, ciascuna richiesta da un utente non documentato o un caso limite oscuro. Sono 1000 righe perché la routine originale da 100 righe non ha funzionato.
Devi lavorare con la mentalità " se non è rotto, non aggiustarlo ". Quando è rotto, devi stare molto attento quando lo aggiusti - mentre lo rendi migliore, non cambi accidentalmente qualcos'altro. Si noti che "rotto" può includere codice non mantenibile, ma che funziona correttamente, che dipende dal sistema e dal suo utilizzo. Chiedi "cosa succede se rovino tutto e lo peggioro", perché un giorno lo farai e dovrai dire al capo dei capi perché hai scelto di farlo.
Questi sistemi possono sempre essere migliorati. Avrai un budget su cui lavorare, una tempistica, qualunque cosa. In caso contrario, vai a crearne uno. Smetti di migliorarlo quando il tempo / denaro è scaduto. Aggiungi una funzione, concediti il tempo di migliorarla un po '. Risolvi un bug: di nuovo, dedica un po 'di tempo extra e miglioralo. Non consegnarlo mai peggio di quanto non fosse quando hai iniziato.
Ci sono due punti chiave da togliere dal libro.
Come hanno sottolineato altri soccorritori, cercare di aggiornare preventivamente il codice legacy esistente è una commissione da pazzi . Invece, ogni volta che devi apportare una modifica al codice legacy (per una nuova funzionalità o una correzione di bug), prenditi il tempo necessario per rimuovere il suo stato legacy.