Quali approcci posso adottare per ridurre le probabilità di introdurre nuovi bug in un'app legacy complessa?


10

Dove lavoro spesso devo sviluppare (e correggere bug) in un vecchio sistema (.NET 1) il cui codice è completo spaghetti - con poca attenzione data ai nomi delle variabili, alla struttura del programma o ai commenti.

Per questo mi ci vogliono anni per capire quali bit devono essere cambiati e spesso "rompo" il software esistente perché ho fatto una modifica. Io veramente veramente voglia di trascorrere un paio di mesi (con i colleghi) che attraverso di essa al refactoring, ma esistente sviluppatori sia non può vedere la necessità - né pensare Theres tempo per questo (il sistema è enorme).

Temo di dover lavorare sul suo codice perché ci vogliono giorni per riparare qualcosa solo per scoprire che ho rotto qualcos'altro. Questo ovviamente mi fa sembrare incompetente, quindi come posso affrontarlo?


Risposte:


16

Inizia a scrivere test per le parti su cui stai lavorando. Puoi provare un flusso di lavoro simile a questo:

  1. Scrivi dei test per la parte che stai per cambiare. Questo ti aiuterà anche a capire come si comporta il codice esistente.
    • Codice di refactor per supportare i test se necessario, ma potresti voler scrivere test non unitari se il tempo è breve.
  2. Esegui i test per assicurarti che le cose funzionino come previsto.
  3. Apporta le tue modifiche. Rifattorizza se necessario nello spirito del miglioramento continuo del codice, ma non lasciarti trasportare.
  4. Riesegui i test per assicurarti di mantenere la stessa funzionalità.

Se non si eliminano i test, nel tempo si creerà una suite di test che dovrebbe coprire le parti più importanti (e / o volatili) dell'applicazione e apportare modifiche in essa diventerà più facile e più sicuro.

Potresti anche trovare utile lavorare efficacemente con il codice legacy di Michael Feathers.


1
+1 per "... ma potresti voler scrivere test non unitari se il tempo è breve."!
Marcie,

1
Buona risposta. @ m.edmondson Durante il refactoring potresti anche scoprire che alcune parti del codice sono "enormi" perché ci sono duplicazioni dappertutto e che quando si esegue il refactoring diventa sia più piccolo che più semplice.
Alb

6

Mi piace seguire la regola del boy scout di zio Bob Martin :

"Quando hai un batuffolo legacy disordinato, quello che devi fare è ... Quello che devi fare è smettere di fare i pasticci e iniziare a ripulirli.

Ciò non significa che tu chiami i tuoi dirigenti in una sala conferenze e dica loro che non fornirai funzionalità per i prossimi tre mesi mentre esegui il refactoring del codice. Non farlo! Piuttosto, significa che stai per adottare la "regola del boy scout" e controllare ogni modulo in modo un po 'più pulito rispetto a quando lo hai verificato.

Dall'iterazione all'iterazione e dalla versione alla versione, pulirai questo sistema continuando ad aggiungere nuove funzionalità e funzionalità. Non c'è altro modo."


2

Potresti spiegare al gestore che le correzioni che dovrebbero richiedere ore finiscono per richiedere giorni a causa del disordine della base di codice. Gli altri sviluppatori non vedranno alcun bisogno di refactoring se sono gli sviluppatori originali: conosceranno il sistema da cima a fondo, ma il management dovrebbe sapere che c'è un rischio se quegli sviluppatori se ne vanno e portano le loro conoscenze.

Di solito non è possibile eseguire un refactoring completo, quindi spesso si refactoring piccoli bit alla volta: un paio di metodi o un modulo. Diamine, se ci vogliono diversi giorni per fare una correzione, forse puoi includere contemporaneamente un piccolo refactoring del modulo problematico.


1
Sono d'accordo - e in passato ho incluso questi "piccoli" refactor come ho semplicemente dovuto fare per capire il codice - eppure qualcuno di solito arriva "l'hai completamente rotto" e ripristinarlo per tornare indietro com'era ...
Billy.bob,

@ m.edmondson: Ah. Bene, se avessero una serie completa di test unitari, semplicemente eseguendo questo verificherebbe se il refactor era buono o no. Da quello che sembra, non ce l'hanno, quindi dovrai scrivere tu stesso i test unitari. So che non è facile e non c'è una vera risposta definitiva a questo problema (almeno non uno che ho trovato, anche se guarderò per vedere cosa suggeriscono gli altri visto che ci sono stato anche io).
FrustratedWithFormsDesigner

2

Hai davvero bisogno di passare mesi a refactoring del codice? O potresti refactificare il codice mentre apporti le modifiche. Quindi, ad esempio, se si determina che il metodo Foo deve essere modificato, è possibile cogliere l'occasione per riformattare il metodo Foo. E se devi passare attraverso una dozzina di altri metodi per capire che Foo è il problema, puoi lasciare commenti in quei metodi in modo che tu o qualcun altro in futuro sappia cosa dovrebbe fare il codice. Ovviamente, ciò significa che c'è ancora un mucchio di codice spaghetti, ma puoi almeno spostare la base di codice nella giusta direzione e renderti più facile per te lungo la linea. Ottenere più mesi di tempo per il refactoring del codice sarà una grande vendita perché ciò significa che non stai offrendo tutto ciò che l'utente finale desidera durante tutto quel tempo.

E la creazione di unit test (o, si spera, l'estensione della suite di test esistente) dovrebbe rendere meno probabile la rottura involontaria di qualcosa.


0

Un altro consiglio. Quando gli insetti si manifestano e dopo aver applicato la benda non fermarti qui!

Chiedi ai cinque perché, prendi la pillola rossa e vedi quanto è profonda la tana del coniglio, e fissa la causa principale (e il percorso laggiù).

Impari molto sul sistema. Aiuta a dare la priorità a cosa riparare e refactoring. E dopo alcuni di questi viaggi hai delle solide "travi di sostegno" per rafforzare il mucchio monolitico di spaghetti.


0

Puoi anche mantenere il vecchio codice in atto fino a quando non avrai la certezza assoluta che le tue modifiche siano a prova di suono. Casomai tutte le modifiche, in modo da poterle attivare in fase di esecuzione e individuare rapidamente la posizione del nuovo bug di regressione:

// old code
...

if (!File.ReadAllText("c:\patch_control.txt").Contains("StrangeUIBugFix=0"))
{
    // new code goes here
    ...
}

// old + new code
int someValue = 
    IsEnabled("StrangeUIBugFix") ? a + b :  // new code
    a * b; // old code

0

Una cosa: Never change any existing code if you are not sure what effect change would have on complete application.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.