Refactoring e documentazione di un grande sistema monolitico

5

Ho iniziato a lavorare su un nuovo progetto e con mia sorpresa è stato scritto da un singolo sviluppatore con quasi nessun test, i test rimanenti sono o buggy o si sentono in errore inclini a lanciare un sacco di NullPointerException quando qualcosa è cambiato. Con mia sorpresa, è stata programmata una versione appena dopo l'inizio, quindi non ho avuto il tempo di capire il codice base e la funzionalità.

Ora, dopo il rilascio, sto pensando a come migliorare la qualità del codice e la comprensione dei sistemi. So che ci sarà un pesante refactoring dai database al codice del server per il frontend. Inoltre, ho documentato le cose correttamente per uso futuro e come parte del mio lavoro.

Quello che sto pensando è iniziare con il test di integrazione in modo da conoscere i casi d'uso e quindi iniziare il refactoring sul pezzo alla volta mentre si scrivono i test delle unità appropriate. Sono abituato a scrivere test di integrazione e dopo alcuni googling mi sono confuso che ci sono anche test di accettazione.

Ho bisogno di sapere di vedere il mio stato attuale o qualcuno nelle stesse condizioni che la strategia di test sopra è utile? e come procedere?

    
posta CodeYogi 06.10.2017 - 11:28
fonte

3 risposte

6

Ti consiglio vivamente di non provare un refactor questo codice.

Sei in una situazione senza vincita qui, qualsiasi nuova funzionalità che aggiungi può introdurre un bug in una funzione esistente per la quale non esiste un test. Tuttavia, se si refactoring quella funzionalità esistente è probabile che sia possibile creare bug in altre funzionalità.

Se vendi il refactoring per il business come "abbiamo bisogno di passare un po 'di tempo a rendere il sistema meno bug e testabile", in 3 mesi ti ritroverai con un sistema ancora più bacato con qualche altro test l'azienda non sarà soddisfatto!

Inoltre, probabilmente scoprirai che i requisiti per il sistema sono "qualunque cosa faccia adesso". Scrivere test per questo non sarà facile.

La soluzione migliore è ottenere requisiti rigidi sulle nuove funzionalità e accertarsi di eseguire test per loro. Bug nelle vecchie funzionalità, beh, puoi dire "vuoi che scriva test per quella funzione? Quali sono i requisiti di come dovrebbe funzionare?".

Una volta che hai più familiarità con il progetto solo allora inizia a sostituire i bit man mano che vengono aggiornati con nuove funzionalità.

Consigli avanzati per gli utenti:

Se vuoi davvero che il prodotto funzioni al 100%, devi assolutamente avere l'azienda da acquistare per un progetto di "grande riscrittura".

Ciò va ben oltre lo scopo del team di sviluppo, poiché prima di iniziare a programmare è necessario raccogliere e comprendere sia i requisiti originali del sistema sia anche il modo in cui viene effettivamente utilizzato giorno per giorno.

Avrai bisogno di configurare un ambiente di test separato per il sistema esistente. Supponiamo che lo sviluppo normale del business continui mentre il progetto di riscrittura è in corso.

Una volta che hai questi puoi iniziare a scrivere test funzionali per il sistema attuale. Non toccare il codice fino a quando non vengono eseguiti. Sei destinato a trovare una serie di bug esistenti, o dovremmo dire differenze tra ciò che la gente pensava che i requisiti fossero e che cosa il sistema facesse. Ciò richiederà una serie di riunioni da risolvere, forse il sistema è giusto e i requisiti sono sbagliati, forse sono entrambi sbagliati, forse hanno ragione ma non sono più di quelli di cui l'azienda ha bisogno.

Solo dopo aver passato una serie completa di test funzionali puoi persino pensare di cambiare il codice; e ricorda, mentre stai facendo che un altro team si sta collegando aggiungendo altre funzionalità che dovrai duplicare sul "nuovo sistema" prima di poter andare in diretta.

Se riesci a fare tutto questo, supera il business come al solito team e rilasci poi un prodotto con le stesse caratteristiche che aveva all'inizio del processo. È una vendita molto difficile da fare per un'azienda se il prodotto funziona fondamentalmente ok.

    
risposta data 06.10.2017 - 16:37
fonte
3

Siamo stati tutti lì, ho dovuto refactoring alcuni progetti disordinati una volta. Quello che posso dirti è non sottovalutare quanto tempo ci vuole. Avere il sistema testato per primo renderà sicuramente più facile il tuo compito.

La scelta tra test di integrazione e accettazione dipende da quanto è grande il tuo refactoring. I test di accettazione sono scritti per testare l'intero sistema. È generalmente espresso come un esempio o uno scenario di utilizzo. ex: come utente, inserisco nome utente e password, premere il pulsante di accesso. Quindi dovrei vedere la schermata di benvenuto.

Una volta che hai effettuato test di accettazione di tutte le tue funzionalità, puoi iniziare a refactoring con molta fiducia, puoi dividere il progetto in diversi servizi o persino cambiare il linguaggio di programmazione stesso. Scrivere questi test da zero può richiedere molto tempo se il sistema è grande.

Se si desidera scrivere test di integrazione per alcune funzionalità e quindi refactoring, significa che si presume che alcune parti del progetto non cambieranno. ex: se si desidera testare un endpoint, si assume che questo endpoint non cambierà. E avrà la stessa interfaccia dopo il refactoring.

La decisione dipende da quanto tempo hai e quanto è disordinato il progetto. Quello che suggerisco è di essere realistico e non puntare troppo in alto. Inizia con alcuni test di integrazione, esegui il refactoring, continua ad aggiungere nuove funzionalità e refactor allo stesso tempo. Alla fine, non esiste comunque un software perfetto.

Buona fortuna

    
risposta data 06.10.2017 - 12:27
fonte
1

La risposta precedente è molto buona e dovrebbe essere seguita, quindi cercherò di coprire gli aspetti della tua domanda che non sono rigorosamente test unitari - il "e come procedere?" parte.

Chiedi a te stesso quanto è organizzato il progetto. È correttamente diviso in classi e funzioni che hanno un senso? Le classi genitore e le interfacce sono utilizzate in modo appropriato? È stato rimosso il codice inutilizzato o ridondante? C'è un flusso di lavoro chiaro mentre i dati passano attraverso il programma e vengono elaborati? Il codice è ben commentato, sia a livello di singola funzione che a livello di classe superiore per indicare a cosa serve ogni classe? E c'è una buona documentazione come requisiti e piani di progettazione? Il progetto può essere grande o orribile in questi aspetti; tutto dipende dallo sviluppatore precedente e dalle condizioni in base alle quali hanno dovuto realizzare il programma. E anche un buon sviluppatore può fare un programma mal implementato se costretto a lavorare con requisiti in evoluzione e tempo limitato.

Se stai usando Visual Studio o un IDE con caratteristiche simili a intellisense, allora il tuo lavoro è più semplice.

Un primo passo è mettere il progetto nel controllo del codice sorgente, se non lo è già. Questo è più importante. Il prossimo è rimuovere qualsiasi codice e / o variabili non utilizzati. Dopodiché, leggi almeno alcune delle classi e capisci cosa fa ognuno; aggiungi commenti che spieghino le classi a livello 'strategico' se tali commenti non esistono, ad esempio quando viene utilizzata la classe e cosa fa per il programma generale. Fallo per più classi prima di fare qualsiasi altra cosa. Ora puoi iniziare a costruire test unitari per quelle classi. Se una classe sembra gonfia, è possibile consolidare o riorganizzare le sue funzioni private e interne, quindi lavorare sulle sue funzioni pubbliche. Se vedi codice ripetuto o ridondante, puoi suddividerli in classi separate / funzioni / ecc. Secondo necessità.

Dopo aver attraversato abbastanza classi, probabilmente ne vedrete diverse che potrebbero condividere una classe genitore o un'interfaccia - è possibile creare quell'interfaccia e aggiornare i riferimenti e le chiamate secondo necessità, in modo che facciano riferimento all'interfaccia genitore / laddove possibile. Questo probabilmente ti permetterà di rimuovere molte istruzioni condizionali che sono state usate per gestire la variazione tra le classi.

Infine, ricorda che (se lo sviluppatore precedente era del tutto buono), c'è una ragione per cui tutto è stato fatto nel modo in cui è stato fatto. Non dare per scontato che tu sappia più della persona che ha originariamente scritto il programma. A volte un segmento può essere scadente perché lo sviluppatore non conosceva un modo migliore di programmarlo, ma a volte è a causa di un requisito specifico o di una stranezza del linguaggio o del sistema.

    
risposta data 06.10.2017 - 16:00
fonte