Comprensione della base di codice complessa già esistente [duplicato]

34

Fino ad ora, tutto ciò su cui ho lavorato è con progetti Java che ho creato da zero (per lo più progetti di corso e alcune cose per hobby). Ma ora mi sono imbattuto in un'enorme base di codici di circa 46000 linee distribuite su circa 200 classi. Inoltre ci sono circa 10 librerie dipendenti.

Il problema non è solo il fatto che non abbia mai lavorato con il codice di qualcun altro prima, ma non ho ancora lavorato con una base di codice così enorme.

Mi viene chiesto di comprendere completamente il codice e suggerire miglioramenti al design esistente. Ora, sono abbastanza bloccato. Comincio con alcune parti del codice e quindi quando raggiungo un'altra parte del codice, ho perso i dettagli di lavoro della parte precedente.

Potrei davvero usare i tuoi suggerimenti ed esperienze per affrontare questo problema. Come posso procedere / documentare i dettagli delle classi per capire meglio il codice?

Modifica: Questo è un progetto di ricerca universitario. Gli studenti lo hanno sviluppato nel corso degli anni e la parte peggiore: gli studenti che lo hanno scritto si sono già laureati. La documentazione esistente (solo sotto forma di Javadoc, non di roba UML) è molto, ma non utile in termini di comprensione della progettazione dell'applicazione.

    
posta Ankit 29.04.2012 - 08:09
fonte

10 risposte

25

Lavorare con il codice è il modo migliore per impararlo. Non esiste un modo "esplicito" per imparare una base di codice enorme, ma ci sono alcune cose che puoi fare.

Puoi provare a modificare il codice per aggiungere piccole funzionalità, a refactoring e ad apprendere il codice base in questo modo. Prova a concentrarti su sezioni piccole e localizzate del codice base, cercando di impararlo in piccoli pezzi.

Se ci sono test unitari, puoi provare a studiarli per avere una visione migliore di come il codice è destinato a funzionare. Se non ci sono prove, scriverle può essere un modo fantastico per comprendere parti del codice. Per definizione, si suppone che i test unitari testino solo un'unità, in modo che tu possa concentrarti solo su quell'unità, prendendo in giro qualsiasi altra dipendenza. Questo ti consentirà di concentrarti e apprendere un'unità di codice alla volta, finché non conosci sempre più codice base.

Un'altra ottima tecnica è eseguire il codice in un debugger e passare attraverso l'intera esecuzione di alcuni casi d'uso. Questo ti darà una buona visione di come il sistema risponde ed esegue alcune funzionalità.

Non aspettarti che ciò accada da un giorno all'altro. Ci vorrà del tempo per comprendere le complessità della base di codice, ma scrivere / comprendere i test di unità è un modo fantastico per apprenderli.

    
risposta data 29.04.2012 - 08:13
fonte
17

Devo fare molte revisioni del codice e include larghe e code base complesse.

Cerco di creare una mappa mentale del componente quando è possibile.

Se devo lavorare o contribuire al progetto, qualcosa di molto efficace che faccio è aggiungere (o modificare) commenti in un'area che non erano chiari al primo posto.

Infine, una semplice panoramica di "architettura" del progetto deve essere costruita per futuri revisori di codice. La mappa mentale sarà molto utile per questo passaggio.

    
risposta data 29.04.2012 - 11:03
fonte
8
  • Ero in una posizione simile dopo aver finito il primo anno all'università. Sulla base di questa esperienza, penso che tu abbia un po 'più di quello che puoi masticare.

Quanto segue potrebbe renderti la vita più facile, ma dovrai impegnarti molto.

  • Ottieni una comprensione completa del tuo dominio problematico. Parla con il business e modella le funzionalità dell'applicazione con i diagrammi dei casi d'uso o qualcosa di simile. Presumo che tu abbia tempo e risorse illimitati per farlo.

  • Devi abbattere il tuo problema in compiti più piccoli. Mettiti un obiettivo e lavora verso l'obiettivo. Per esempio. Voglio capire il processo di autenticazione. Trova il codice che pensi di fare e inizia a lavorare su quello. Se ti capita di riagganciare su tutto il sistema, è molto improbabile che arrivi da qualche parte secondo me.

  • Ottieni contatti con persone che hanno già lavorato in precedenza. Se sono ancora nella stessa azienda, collaborare con loro dopo aver familiarizzato con il sistema.

  • Passare attraverso il codice, documentare ciò che fa ci vorrà molto tempo. Dubito che te lo puoi permettere.

  • Distribuisci il sistema in un ambiente nuovo. Spero che si rompa e che dovrai eseguire il debug di molti codici per vedere cosa sta succedendo.

  • Supponendo che tu abbia i casi d'uso, inizia a eseguire il debug attraverso il codebase.

  • Assicurati di essere chiaro sul motivo per cui l'azienda vuole che tu riesaminare il codice base. Sicuramente non è solo un esercizio costoso e inutile, quindi devono avere una buona ragione. Questo dovrebbe darti una buona idea su dove cercare.

  • Esistono strumenti che analizzano codebase e ti dicono se è strettamente accoppiato e quanti codici duplicati ci sono. Questo potrebbe essere utile, ma non all'inizio del tuo progetto.

  • Controlla se ci sono dei test unitari. Inizia a eseguirli per vedere cosa è in grado di fare il sistema.

Cose da tenere a mente:

  • Non è un compito facile, quindi non picchiarti.

  • Ci saranno molte cose che non capirai, quindi non riattaccare su quelle cose e andare avanti.

  • Normalmente è abbastanza demotivazionale, quindi è importante prendere nota dei tuoi progressi. Di solito ce l'ho su una lavagna di fronte a me.

  • Non riagganciare su grandi numeri. Sì, puoi usarlo per autodifesa e 200 classi probabilmente equivalgono a un bel po 'di responsabilità, ma questo non ti semplifica la vita, quindi cerchiamo soluzioni :)

risposta data 29.04.2012 - 11:04
fonte
5

Benvenuti nel mondo dello sviluppo del software. La maggior parte delle volte hai intenzione di:

  • Funziona con una base di codice preesistente di grandi dimensioni.
  • Ci sarà documentazione limitata.
  • I creatori originali se ne sono andati da tempo.
  • Nessuno conoscerà veramente il sistema end to end.

La maggior parte delle volte verrai sballottato e ti aspetti di capirlo. Certo ci saranno persone lungo la strada e una certa quantità di documentazione per aiutare ma alla fine spetta a te dare un senso alle cose. Penso che questo dare un senso alle cose sia diverso per ogni persona ed è un'abilità che fa davvero la differenza.

Dalle mie esperienze / osservazioni su come gli altri fanno qui è ciò che vedo che funziona:

  • Avvicinandolo in modo da trovare prima lo scheletro del sistema e poi iniziare a riempire i dettagli.
  • Scrittura di alberi di chiamata che mostrano come passare da un posto all'altro nel codice. Molte volte questa è solo una particolare area, non l'intero sistema.
  • Uso di strumenti che aiutano a comprendere il codice. Uso la funzione di ricerca e la funzione di riferimento di Slickedit. Penso anche che eclipse abbia alcuni strumenti come questo.
  • Sperimentazione su come funziona il sistema. Spesso utilizzo un livello elevato di traccia / stampa con test diversi per aiutarmi a capire il flusso.

Alla fine la cosa che aiuta di più è Ripetizione ! Più volte attraversi le cose, più è facile sapere che cosa. Nell'industria spesso diciamo che ci vorranno alcuni mesi prima che tu possa considerare qualcuno che abbia le conoscenze per essere efficace. Questo è dovuto alla curva di apprendimento.

Infine, nella mia esperienza personale, sento che ci sono alcune fasi per comprendere una nuova grande base di codice:

  • Fase 1: come orientarsi. In questa fase si tratta di imparare dove sono le cose e prendere confidenza. Direi che dovresti essere in grado di apportare piccole modifiche con successo.
  • Fase 2: conosci bene dove sono le cose e sei capace di fare cambiamenti di medie dimensioni con un po 'di fortuna. Direi che a questo punto avresti bisogno di una buona dose di aiuto per ottenere le cose giuste ma puoi fare le cose.
  • Fase 3: hai una buona conoscenza del codice e sei capace di apportare grandi e complicate modifiche. Il problema più comune a questo livello è che una comprensione incompleta a livello di sistema ti porta a introdurre bug. Sei ancora molto efficace.
  • Fase 4: hai una comprensione completa e puoi piegare il sistema alla tua volontà. Direi che davvero pochi arrivano qui.
risposta data 29.04.2012 - 20:05
fonte
5

Se nella documentazione non esiste qualcosa di simile, mi piace disegnare diagrammi di classe e sequenza UML per avere un'idea della struttura statica e del comportamento dinamico del codice. Questi diagrammi non devono essere formalmente corretti, ma mi danno qualcosa da guardare quando ho un "che cosa sta facendo di nuovo ??" momento.

Se sono già lì, mi piace anche guardare i test unitari per vedere come tutto si riunisce. Se non ce ne sono, scriverli è anche un buon modo per entrare nella base di codice.

EDIT: Non disegno i diagrammi per tutto il codice, solo la parte su cui sto lavorando attualmente e che mi confonde (gerarchie di ereditarietà complessa ecc.)

    
risposta data 29.04.2012 - 10:36
fonte
2

Concentrati su strutture dati : è lì che la gomma colpisce la strada.

La definizione dei dati (ad esempio lo schema del database, i formati dei file) richiede molte meno linee (di codice) rispetto alla logica dell'applicazione, ma è fondamentale per capire veramente cosa sta facendo l'applicazione. Impara le strutture e le relazioni dei dati. Dopo di che è molto più facile avvolgere il resto del programma.

Conoscere il layout dei dati ti dà senso dell'orientamento durante la lettura del codice. È come avere la mappa e la bussola mentre navighi nella foresta.

"Mostrami il tuo diagramma di flusso e nascondi i tuoi tavoli, e continuerò a essere mistificato Mostrami le tue tabelle e di solito non avrò bisogno del tuo diagramma di flusso, sarà ovvio." - Fred Brooks, The Mythical Man-Month

PS. I dati vivono per sempre. I programmi (e i computer) sono transitori.

    
risposta data 29.04.2012 - 14:08
fonte
2

Ho lavorato su una base di codice complessa per più di un anno. Verifica se i miei approfondimenti possono aiutarti:

I tuoi approfondimenti sono corretti, quando raggiungi una parte diversa del codice, dimentichi la parte precedente. Può essere un ciclo senza fine. La lezione importante da portare via qui è che il prodotto non può funzionare senza che tutte le parti funzionino correttamente. Anche se una parte fallisce, il prodotto non funziona. Guardalo da un altro punto di vista: se migliori una parte in modo drammatico, NON POTREBBE conseguire un migliore funzionamento del prodotto, che è il tuo obiettivo principale qui.

Quindi, in primo luogo: non essere uno sviluppatore. Diventa un tester.

Non cercare di capire parte per parte. Comprendi l'intero prodotto e il suo funzionamento quando tutte le parti sono insieme. Da un ambiente di produzione (ad esempio un ambiente non di sviluppo - nessun punto di debug), testare il prodotto. Quindi, proprio come fa ogni tester, registra i problemi che affronti in un bug tracker. Assegna la gravità e la priorità ad essa. Poiché questo software esiste già da un po 'di tempo, verifica se è già stato creato un bug tracker. Se ce n'è già, sei fortunato. Aggiungi a quelli e prendi tempo e verifica ciascuno di quelli esistenti. Alla fine di questo ciclo, capisci il prodotto da un punto di vista dell'utente (non dovresti assolutamente perderlo) e anche un punto di vista del QA. A tempo debito, potresti anche rendertene conto che una riga di codice risolverà il bug, e coloro che lo hanno codificato non l'hanno fatto perché non c'era un reale bisogno allora.

Secondo passaggio: indossa un capo firmato

Rompere il prodotto in più parti (non letteralmente o secondo la tua convenienza, ma in base al modo in cui lavorano insieme). Potrebbe essere il tuo lavoro al massimo o le conoscenze esistenti potrebbero entrare in gioco. Quindi, cerca di capire come funzionano tra loro e con le 10 librerie dipendenti. Quindi, per ogni bug tracciato, scrivi le tue note identificando le entità del codice (ad esempio: questo cambiamento comporta la modifica delle classi X, Y, Z, ecc.). Probabilmente, alla fine di questo passaggio, avrai alcuni suggerimenti su quali sono i problemi con l'architettura corrente e cosa può essere migliorato.

Quindi, puoi decidere se l'architettura / design corrente è sufficiente e puoi migliorare il software OPPURE se il prodotto ha bisogno di un design migliore o di modifiche nel design esistente.

House of Cards

Inoltre, poiché i prodotti complessi hanno un sacco di codice, potremmo non essere in grado di raccogliere alcune cose e modificarle o migliorarle. Questo perché l'intero sistema può essere intrecciato in modo tale che il cambiamento di una delle classi equivale a cambiare la posizione di una carta in un castello di carte, non si sa mai quale fine potrebbe rompersi. Nella mia esperienza, questo è stato vero. Ho scelto una parte, migliorato il suo codice, ignaro dei contratti che aveva con altre parti del codice e ho finito per abbandonare il codice e realizzare il mio errore. Quindi, invece di cercare di capire le parti, prova a capire che è un intero.

Assegna la priorità ai tuoi dubbi

Devi tenere a mente ciò che stai cercando di migliorare:

Do you want the product to be faster?

Certo che lo fai. Ma è la principale delle preoccupazioni? È lento? In caso affermativo, crea criteri di rendimento, identifica i colli di bottiglia e migliora quelle parti. Prova di nuovo.

Do you want to improve the usability?

Quindi è più o meno il lato API / interfaccia utente.

Do you want to improve the security?

Quindi sono i limiti che dovresti esplorare.

Ho fornito solo 3 esempi, ma c'è molto altro da cercare.

Ultima e migliore documentazione

Ho letto qui in uno dei post che la documentazione più recente e migliore è il codice stesso. Anche se oggi crei una buona quantità di documentazione, è una storia dopo un po '. Quindi, il codice è il tuo ultimo pezzo di documentazione. Quindi, ogni volta che sfogli un po 'di codice, scrivi la tua comprensione nei commenti lì. Passando il codice di base, fai in modo che dipendano NON SOLO dai commenti!

    
risposta data 30.04.2012 - 12:24
fonte
1

In relazione a questo . Ma con l'aggiunta di una linea di componenti di codice. E a proposito, 46000 linee di codice sono un'applicazione di dimensioni medie nella mia esperienza.

    
risposta data 29.04.2012 - 14:20
fonte
1

Alcune strategie:

  • Crea un diagramma di ereditarietà. Ci sono strumenti che faranno questo per te, ma anche disegnarlo a mano potrebbe essere utile.

  • Delle 200 classi, probabilmente scoprirai che una dozzina di persone sono davvero importanti. Queste saranno le classi vicine alla radice dell'albero di ereditarietà. Gli altri saranno variazioni su un tema, e una volta che saprai cosa fanno le loro superclassi, avrai una buona idea di come funzionino anche tutte quelle classi foglia.

  • Crea note. L'utilizzo di una wiki può essere utile qui. Alla fine, potresti trasformare alcune note in una documentazione migliore di quella attualmente esistente.

  • Disegna i diagrammi degli oggetti che vengono creati e in che modo si relazionano tra loro.

  • Utilizza un debugger per scorrere sezioni che non capisci.

  • Utilizza uno strumento di profilazione per individuare i problemi di rendimento senza preoccuparti troppo di ciò che sta accadendo nel codice. Basta mettere l'applicazione a pieno ritmo mentre si registrano le metriche sul rendimento. Sapere dove l'applicazione trascorre la maggior parte del tempo può a) darti un'idea di come funziona e b) suggerire aree di miglioramento senza che tu debba capire ogni dettaglio.

risposta data 30.04.2012 - 00:11
fonte
0

tl; dr: Scrivi documenti, scrivi test. Trasforma la comprensione in making.

Versione completa:

Non molto tempo fa anche io ho avuto modo di lavorare su progetti esistenti per la prima volta in un'azienda e ho dovuto alzarmi rapidamente.

Ho scoperto che tutti i progetti soffrono inevitabilmente del problema molto serio: documentazione e test insufficienti. Questo è molto negativo dal punto di successo del progetto.

  • Alto fattore di bus . Poche persone capiscono davvero come funzionano le cose, tranne forse uno sviluppatore principale che è stato assegnato a lavorare sul progetto.

  • La comunicazione è difficile poiché non esiste un'immagine comune dell'architettura a cui ci si possa riferire. Decisioni di miglioramento dell'architettura ben informate sono difficili da fare.

  • È difficile per le persone. I nuovi arrivati fanno fatica a capire un programma.

Quindi ciò che ha funzionato per me è trasformare capire in fare .

  • Se c'è un compito particolare che devo fare nel nuovo progetto, lo farei nel modo che mi consente di raccogliere la maggior parte delle informazioni sul sistema.

  • Se non ci sono compiti, ma 'solo' è necessaria una comprensione generale (che sembra essere il tuo caso), quindi scriverei la documentazione.

Scrivere documentazione per ottenere una comprensione generale

Ho scoperto che è difficile far capire al cervello i complessi sistemi astratti. Tuttavia, la stessa comprensione viene facilmente se si sta facendo qualcosa (probabilmente è in qualche modo correlato al concetto di "flusso").

È una specie di hack. Penso che la maggior parte della gente si diverta a fare prodotti di qualità e ad essere orgogliosi del proprio lavoro, quindi è possibile rendere la documentazione del prodotto finale. Imparerai nuovi strumenti (sistema di documentazione come la Sfinge, per esempio) e risolvi difficili problemi su come trasmettere la tua comprensione, come emerge, al pubblico di destinazione. Avrai un prodotto finale per mostrare te stesso e gli altri, e la gente ti ringrazierà più tardi, il che è un grande motivatore.

Non dimenticare la metadocumentazione: è frustrante quando i tuoi documenti diventano obsoleti perché altri non si preoccupano di aggiornarli. Documenta brevemente il workflow di sviluppo: versioning, testing, documentazione e guida allo stile di codifica, ecc.

Scrittura test

Se ho un compito particolare a portata di mano - nuova funzione o bugfix - prima scrivo per prima cosa un test.

Per scrivere un test, devo capire come funziona la suite di test e farlo funzionare. Questo di solito non è ovvio, quindi lo documento brevemente. La suite di test ha spesso molti problemi, come test unitari e test di integrazione, quindi ho anche preso nota delle idee su come risolverlo in seguito. A volte la suite di test non funziona o tutti i test falliscono, quindi lo aggiusto. Ci sono casi in cui la suite di test è completamente assente, che è la possibilità di imparare come configurarne uno.

Quindi scrivo un test. Se è un compito importante, scrivo prima un test di "integrazione" ad alto livello. Quando si scrivono i test delle unità, il primo compito è capire quale unità deve implementare la funzionalità necessaria. Questo ti darà un po 'di comprensione dell'architettura. Dopodiché, scrivere il codice che implementa la funzione è facile.

Scrivere un test può benissimo diventare un compito più grande che implementare una funzione o correggere un ma. Tuttavia, è gratificante in seguito. Una volta che c'è una solida suite di test, tu (o altri sviluppatori) puoi imparare molto cercando di migliorare le cose a caso e vedere se i test superano.

    
risposta data 30.04.2012 - 07:35
fonte

Leggi altre domande sui tag