Come posso aggiornare una base di codice legacy di grandi dimensioni per soddisfare specifici standard di qualità?

10

Ci sono molte informazioni su strumenti e tecniche per migliorare le codebase legacy, ma non ho mai trovato casi di successo nel mondo reale. La maggior parte dei consigli è a livello micro e, sebbene utile, non convince molte persone a causa della mancanza di prove che possono aiutare a livello macro.

Sto cercando specificamente miglioramenti incrementali che hanno dimostrato di essere un successo nel mondo reale quando si aggiorna una base di codice legacy di grandi dimensioni per soddisfare gli attuali standard di qualità e non una completa riscrittura.

Prima:

  • Grande: superiore a 1MLOC
  • Legacy: nessun test automatico
  • Qualità scadente: alta complessità, alto accoppiamento, difetti di fuga elevati

Dopo

  • Test automatici
  • Aggiornamenti e manutenzione più facili
  • Alta qualità: complessità ridotta, codice disaccoppiato, pochi difetti di escape

Che tipo di passaggi incrementali sono stati dimostrati nel mondo reale per aggiornare una base di codice legacy di grandi dimensioni con successo per soddisfare gli standard di qualità precedenti, senza passare attraverso una riscrittura totale?

Se possibile, includi un esempio di azienda o case study di un grande progetto legacy che ha attraversato un processo di miglioramento della qualità "di successo" nella tua risposta per eseguire il backup.

    
posta mikelong 29.01.2013 - 09:26
fonte

4 risposte

8

Libri come link dovrebbero essere testimoni di quanto siano largamente diffuse basi di codice di bassa qualità legacy nel settore .

La mia ipotesi sul perché non hai sentito o visto, e, cosa più importante, probabilmente non ne sentirai mai parlare fino a quando non lavorerai su uno di loro da solo, è, nessuno sembra capace per vari motivi, di venire pulito e dire che la loro base di codice era tutto quanto sopra senza affrontare ripercussioni non banali.

Questo potrebbe spiegare la mancanza di studi di cui parli. Se leggi abbastanza libri, ad esempio Deep C Secrets di Peter van der Linden, leggerai circa milioni di bug in dollari in cui mancherà la parte relativa al progetto.

NOTA: volevo rendere questo un commento, ma era troppo lungo. Capisco che questo non risponda completamente alla domanda.

EDIT: C ++ 11 & La redditività a lungo termine di GCC è messa in dubbio - se gli sviluppatori refactoring GCC e renderlo più utilizzabile come LLVM / clang, potrebbe fornire un buon esempio. La discussione rileva che la documentazione è scarsa in alcuni punti, spingendo più in alto la barriera di ingresso per i nuovi sviluppatori.

    
risposta data 30.01.2013 - 01:35
fonte
4

Il 3 febbraio 2013, Michael Meeks, uno degli sviluppatori di LibreOffice, terrà un discorso in un paio di giorni intitolato, " LibreOffice: ripulire e ridisegnare una gigantesca base di codice, o perché riscriverlo sarebbe ancora peggio. " Sembra esattamente quello che stai chiedendo: una discussione su ciò che hanno fatto per prendere "un code-base gigantesco comprensibile, ampiamente commentato in tedesco, senza test unitari, un'infrastruttura di costruzione ingarbugliata e venticinque anni di debito tecnico non pagato" e modernizzarlo.

La presentazione può essere in streaming online e (credo) le registrazioni saranno disponibili in una data futura.

    
risposta data 31.01.2013 - 17:58
fonte
4

In realtà ho attraversato un refactoring abbastanza significativo per tre volte nella mia carriera. Il codice tende a decadere, quindi se il tuo codice base è abbastanza lungo, un grande refactore è praticamente inevitabile. Tutti i miei esempi erano su basi di codice private, il che potrebbe spiegare perché è difficile trovare esempi pubblici.

La prima volta era un'applicazione che, che ci crediate o no, aveva un'architettura fondamentale che lo faceva funzionare solo con le stampanti ad aghi. Quando la mia azienda non riusciva più a trovare un fornitore che fornisse i nastri, mi assegnarono per farlo funzionare con una stampante laser.

La seconda volta è stata una migrazione di diverse centinaia di script di test automatici da C a Java, in parte perché avevamo bisogno di migliori capacità cross-platform e in parte perché era difficile assumere nuovi sviluppatori C.

La terza volta che mi trovo ancora nel mezzo, che sta modularizzando un'enorme applicazione monolitica per consentire il collaudo delle unità riducendo l'accoppiamento e per scopi cross-platform.

Paragono lo sforzo per scalare una montagna. Hai questo enorme obiettivo davanti a te, ma non lo affronta a livello macro. Lo prendi un appiglio alla volta, avendo sempre una posizione di sicurezza stretta, senza mai staccare la sicurezza precedente fino a quando il prossimo non è a posto. Inizi solo facendo piccoli miglioramenti incrementali, e dopo un po 'ti giri e improvvisamente c'è questa bellissima vista.

Supponiamo che tu abbia 60.000 file di codice altamente accoppiati, per esempio. Vuoi iniziare a metterlo sotto test unitario, ma le dipendenze lo rendono impossibile. Come lo aggiustate? Dissocia il file uno . Aggiungi test automatici. Si ritorna su terreno stabile prima di andare avanti. Ripeti 59.999 volte.

Se ciò sembra semplice, è perché è semplice. Non è facile, ma è semplice. All'inizio è difficile notare qualsiasi progresso. Siamo in due anni in quello che sembrava un refactoring impossibile, e probabilmente avremo anni davanti a noi fino a quando non avremo finito, ma guardando indietro ci rendiamo improvvisamente conto di quanto il codice sia già migliorato e siamo stati in grado di continuare a fornire nuove funzionalità ai nostri clienti nel frattempo.

Le altre due volte hanno funzionato allo stesso modo. Trovi il più piccolo passo sicuro che puoi intraprendere e lo prendi, mantenendo sempre l'applicazione in uno stato funzionante. Ti preoccupi solo del quadro generale per assicurarti di essere nella giusta direzione. Tutte le tue azioni sono piccole, costanti e incrementali.

    
risposta data 31.01.2013 - 23:22
fonte
1

Dall'esperienza personale lavorando su una base di codice di linea multi-milioni ho trovato alcune strategie che sembrano funzionare.

Guarda tutti i bug (anche quelli chiusi) e prova a suddividerli in categorie. Specificamente per provare a scomporli dal componente a cui appartengono. Se appartengono a più di un componente, nota che lo fanno. Una volta che hai fatto questo sguardo su quale secchio è il più grande e usalo per determinare da dove cominciare. Inoltre è possibile esaminare la cronologia delle revisioni dei file per determinare quali sono le modifiche più importanti e utilizzarle come guida su dove iniziare. Fondamentalmente quello che stai cercando di fare è trovare quello che è più risolto e ripeterlo. Inoltre ho scoperto che provare a sistemare tutto nello stesso momento non funziona mai e causa solo più problemi.

Se trovi che molte cose che appartengono a più componenti è un'indicazione di problemi di "sistema" e potrebbe puntare a un codice troppo strettamente accoppiato o a un'API che necessita di aggiornamento.

Un'altra area in cui ho trascorso molto tempo è testare la base di codice esistente. Ci sono più strategie qui e tutti hanno il merito, ma nessuno è una soluzione completa al problema.

  • I test delle unità possono funzionare ma spesso si è limitati a ciò che può essere testato su unità a causa del codice strettamente accoppiato. Comunque fallo dove puoi.
  • Il test esterno è un'altra strada. Presumo che probabilmente tu abbia già questo e, se non lo farò, passerò un po 'di tempo a crearlo. Inoltre qualcosa che ha funzionato per me è aggiungere la capacità di iniettare casualmente errori / eventi nel sistema. Inoltre, cerca di iniettare più cose contemporaneamente per cercare di farlo fallire in modi nuovi.
risposta data 31.01.2013 - 19:34
fonte

Leggi altre domande sui tag