In una base di codice legacy, come posso scoprire rapidamente cosa viene utilizzato e cosa no?


21

Mi è stato chiesto di valutare ciò che sembra essere una base di codice legacy sostanziale, come un precursore di prendere un contratto mantenendo tale base di codice.

Questa non è la prima volta che mi trovo in questa situazione. Nella fattispecie, il codice è per un sito di gioco multiplayer di alto profilo e abbastanza alto carico, che supporta almeno diverse migliaia di giocatori online contemporaneamente. Come molti di questi siti, questo è un mix di tecnologie front-end e back-end.

La struttura del sito vista dall'interno verso l'esterno, è un casino. Ci sono cartelle con il suffisso "_OLD" e "_DELETE" in tutto il luogo. Molte delle cartelle sembrano non avere alcuno scopo o hanno nomi molto criptici. Potrebbero esserci un numero qualsiasi di script vecchi e inutilizzati in giro anche in cartelle dall'aspetto legittimo. Non solo, ma ci sono senza dubbio molte sezioni di codice defunte anche in script altrimenti operativi (una preoccupazione molto meno urgente).

Si tratta di una consegna da parte dei manutentori storici, di nuovo agli sviluppatori / manutentori originali del sito. Com'è comprensibilmente tipico in questo tipo di scenari, l'operatore storico non vuole avere nulla a che fare con il passaggio di consegne diverso da quello che è loro richiesto contrattualmente e legalmente di spingerlo al manutentore neoeletto. Quindi estrarre informazioni sulla struttura del sito esistente dall'operatore storico è semplicemente fuori discussione.

L'unico approccio che viene in mente per entrare nella base di codice è iniziare dalla radice del sito e navigare lentamente ma sicuramente attraverso gli script collegati ... e probabilmente ce ne sono centinaia in uso e altre centinaia che non lo sono. Dato che una parte sostanziale del sito si trova in Flash, ciò è ancora meno semplice poiché, in particolare nelle applicazioni Flash meno recenti, i collegamenti ad altri script possono essere incorporati nei file binari (.LLA) anziché nei file di testo (.AS / ActionScript).

Quindi mi chiedo se qualcuno abbia suggerimenti migliori su come affrontare la valutazione della base di codice nel suo insieme per la manutenibilità. Sarebbe meraviglioso se ci fosse un modo per guardare un grafico della frequenza di accesso ai file sul sistema operativo del server web (a cui ho accesso), in quanto ciò potrebbe offrire una visione di quali file sono più critici, anche se non lo farebbe essere in grado di eliminare quei file che non sono mai stati utilizzati (poiché alcuni file potrebbero essere utilizzati solo una volta all'anno).


7
Non so abbastanza di Flash, ma se ricevi errori di compilazione quando il codice non è presente, dovresti essere in grado di rinominare le cartelle per vedere se sono referenziate.
Oded,

Soluzione malvagia: eliminali e attendi la segnalazione di errori / bug. (Assicurati solo che sia recuperabile!)
Izkata,

1
@Nick Potresti chiarire se ti viene pagato per la valutazione come parte della prossima fase del contratto su cui devi ancora fare offerte / altrimenti ottenere? La tua risposta non cambierà la domanda "c'è uno strumento", ma alcuni di noi potrebbero creare risposte in merito a un processo che sarebbe più adatto alla tua situazione (ad es. Impedirti di essere fregato, ecc.).
jcmeloni,

@jcmeloni No, non vengo pagato per la valutazione. Ma nella mia esperienza , e dalle piccole cose che ho raccolto negli ultimi due giorni, non hanno nessun altro al tavolo in questo momento. Il mio skillset è abbastanza insolito, quindi sono ancora più a mio agio che non hanno nessun altro in competizione per questo, in base alla citazione. Il preventivo effettivo in questione proviene dal mio futuro cliente per il suo cliente, che sta pianificando di riconfermare il contratto. Davvero dalla mia fine, sono destinato ad aiutarli a fornire detto preventivo. HTH.
Ingegnere il

@Oded Rename è sicuramente più semplice della cancellazione di tentativi ed errori! Buona riflessione lì. Questo è un altro strumento nella confezione.
Ingegnere,

Risposte:


32

Poiché ciò che ti viene chiesto di fare è fornire input al tuo client per scrivere una proposta appropriata all'altro client (codice del proprietario dell'incubo) per qualsiasi lavoro su quel codice, sto per uscire un arto e dire che a questo punto non si eseguiranno test approfonditi o refactoring o nulla del genere. Probabilmente hai un tempo molto breve per ottenere una stima approssimativa. La mia risposta si basa sulla mia esperienza nella stessa situazione, quindi se la mia interpretazione è errata, ignora tutto ciò che segue.

  • Usa uno strumento di spidering per avere un'idea di quali pagine sono presenti e di cosa è in entrata. Anche uno strumento di controllo dei link di base - non uno strumento specifico "spider a fini di controllo" - sarà utile in questo senso.
  • Crea un foglio di calcolo / inventario di base. Potrebbe essere semplice come un elenco di file e l'ora dell'ultima modifica, organizzata per directory. Questo ti aiuterà ad avere un senso dell'ambito e quando arrivi a directory come _OLD e _DELETE puoi notare che a) la tua valutazione si basa su elementi non presenti in quelle directory b) la presenza di tali directory e il potenziale per incubi / incubi nascosti attestano problemi più profondi che dovrebbero essere contabilizzati nell'offerta del cliente , in qualche modo. Non devi passare un milione di anni a elencare i possibili problemi in _OLD o _DELETE; le informazioni verranno inserite nell'eventuale offerta.
  • Dato che stai recensendo quella che sembra un'app interamente basata sul web, anche gli strumenti standard di analisi dei log diventeranno tuoi amici. Sarai in grado di aggiungere al foglio di lavoro un senso di "questo è tra i primi 10 degli script a cui si accede" o alcuni di questi. Anche se gli script sono incorporati nei file Flash e quindi non sono spiderabili, è molto probabile che siano accessibili tramite POST o GET e verranno visualizzati nei registri del server. Se sai di avere 10 script a cui si ha molto accesso, non 100 (o viceversa), questo ti darà una buona idea di come probabilmente andranno i lavori di manutenzione.

Anche in un sito complicato, quello che ho descritto sopra è qualcosa che potresti fare in un giorno o un giorno e mezzo. Poiché la risposta che darai al tuo cliente è qualcosa del tipo "questo sarà un tremendo dolore nel sedere, e qui ci sono alcuni motivi per cui ti limiterai a mettere il rossetto su un maiale, quindi dovresti fare offerte di conseguenza "o" qualsiasi persona ragionevole si aspetterebbe di non mantenere ma di ricominciare, quindi dovresti fare offerte di conseguenza "o addirittura" non è così male, ma sarà un flusso di lavoro coerente in un determinato periodo di tempo, quindi fai offerte di conseguenza " , il punto è che stanno andando a fare l'offerta e, quindi, non hai bisogno di essere il più preciso come si sarebbe se tu fossi di essere assunti direttamente per fare un contenuto completo e l'architettura di controllo.


2
+1 Questa è una risposta fantastica. Dov'è quel pulsante +5 ottenuto ...
Ingegnere il

1
TL; DR: non mandarti in una tana di coniglio fino a quando non è necessario. :)
jcmeloni,

4

Consiglio vivamente di refactoring il codice sorgente esistente (al contrario di una riscrittura) usando gli schemi trovati nel libro " Lavorare efficacemente con il codice legacy ".

Il libro descrive diversi meccanismi per coprire in modo efficiente il codice legacy nei test unitari, in modo da poter iniziare a riformattare in modo sicuro il codice. Il libro è suddiviso in parti, uno che descrive la filosofia alla base dell'approccio, e poi diversi capitoli che risolvono problemi particolari, come "Ci vuole un'eternità per fare un cambiamento", "Non ho molto tempo e ho bisogno di cambiarlo" e "Non riesco a far entrare questa classe in un cablaggio di prova". Ognuno di questi capitoli ha tecniche dettagliate e comprovate che ti aiutano a imparare come applicare le migliori pratiche nei test sui problemi del mondo reale.

Leggere il libro mi ha lasciato con la sensazione molto reale che "non siamo soli" ... molti di noi, o forse tutti, stanno lavorando con basi di codice complesse che sono diventate difficili da gestire. Le tecniche elencate nel libro mi hanno dato molte speranze e sono stato personalmente in grado di applicarle quasi immediatamente.

Il post sul blog di Joel Spolsky fa un ottimo lavoro nel spiegare perché è meglio mantenere una base di codice funzionante, anziché iniziare da zero. Ho scelto una citazione dall'articolo che lo riassume, ma è una lettura fantastica.

"C'è una ragione sottile per cui i programmatori vogliono sempre buttare via il codice e ricominciare. La ragione è che pensano che il vecchio codice sia un disastro. Ed ecco l'osservazione interessante: probabilmente hanno torto. La ragione per cui pensano che il vecchio il codice è un casino a causa di una legge cardinale e fondamentale della programmazione:

È più difficile leggere il codice che scriverlo ". - http://www.joelonsoftware.com/articles/fog0000000069.html


4
+1. In risposta al commento di Joel, "Non dovrebbe essere dannatamente bene." Perché non vedo il problema come inerente. Vedo che è in parte il fatto che molte persone scrivono codice scadente e non se ne curano, mentre molte altre scrivono un codice ragionevolmente buono ma vivono secondo il concetto di "codice auto-documentante" ... che è semplicemente BS: Uno potrebbe lusingare il proprio stile di codifica tutto ciò che si desidera in termini di privacy, ma quando si tratta di basi di codice pubbliche generano commenti come se non ci fosse un domani. Non fa male. E infine ci sono persone che devono far funzionare le cose in una base di codici legacy, con un budget limitato.
Ingegnere

2

In una tipica base di codice Java, prenderò in considerazione l'utilizzo di strumenti come PMD, FindBugs o Sonar e quindi proverò a comprendere la segnalazione degli strumenti (codice morto, codice non documentato, codice duplicato, ecc.)

Sulla base dei rapporti, proverò a trovare i diversi livelli dell'applicazione / sito (livello aziendale, DB, SQL, ecc.)

Se i livelli sono accoppiati (html all'interno di servlet, sql all'interno del codice java) Inizierò prima disaccoppiando ciascuno di questi passaggi che dovrebbero essere considerati isolati e si può impegnare alla fine di ognuno (avviando un ramo e poi unendo) .


1
Grazie. Sebbene la tua risposta sia in qualche modo specifica per Java, è interessante vedere il tuo approccio a strati ... sbucciare la cipolla, per così dire. Qualcosa a cui pensare.
Ingegnere,

1

Dalla tua descrizione sembra che questo codice abbia raggiunto lo stato non mantenibile, il che significa che l'approccio migliore è probabilmente una riscrittura completa. Gli sviluppatori avrebbero stipendi molto più piccoli se esistessero strumenti di qualità che funzionassero per mantenere una base di codice disordinata mantenibile. È possibile esaminare e ripulire il vecchio codice non necessario dalle cartelle, ma è un'attività manuale e probabilmente non otterrai tutto senza irragionevoli quantità di tempo. Sto solo indovinando qui, ma scommetto che il codice di lavoro in sé è altrettanto un disastro quanto la struttura del file, il che significa che anche quando riesci a tagliare la base di codice al codice che funziona attivamente sarà ancora un incubo per aggiornare o riparare qualsiasi cosa.

Vorrei sottolineare che lo sforzo richiesto per riportare il codice esistente in uno stato mantenibile sarebbe uguale o maggiore dello sforzo di ricominciare da capo su una riscrittura. parte del mantenimento di qualsiasi cosa è sapere quando "portarlo dietro il capannone e sparargli".


Di solito sarei al 100% con te nell'approccio di lancio e riscrittura. Ma in questo caso (e almeno per ora), dovrò essere pagato solo per il lavoro di manutenzione del sito, piuttosto che una revisione più ampia che richiederebbe diverse settimane. Inoltre, anche se volessi farlo in questo momento, non potrei continuare a farlo e trattenere gli altri contratti che ho in viaggio, poiché la mia disponibilità settimanale per questo è esplicitamente limitata - il mio contratto principale deve essere soddisfatto Minimo 40 ore settimanali.
Ingegnere,

1
Non sono d'accordo con il lancio e la riscrittura! Da joelonsoftware.com/articles/fog0000000069.html ... "C'è una ragione sottile per cui i programmatori vogliono sempre buttare via il codice e ricominciare da capo. La ragione è che pensano che il vecchio codice sia un disastro. Ed ecco l'osservazione interessante : probabilmente hanno torto. La ragione per cui pensano che il vecchio codice sia un disastro è a causa di una legge cardinale e fondamentale della programmazione: è più difficile leggere il codice che scriverlo. " Invece, consiglio vivamente il refactoring: amazon.ca/Working-Effectively-Legacy-Michael-Feathers/dp/…
Kyle Hodgson,

1
@KyleHodgson a volte il codice in realtà è un casino, e quando sei nel punto in cui è un casino trovare il codice prima di leggerlo, è il momento di ricominciare.
Ryathal,

Sì, non penso sia così chiaro, anche se quel libro sembra degno di essere letto. Dipende molto dalle dimensioni / complessità della base di codice e dai corpi caldi disponibili per fare il lavoro.
Ingegnere,

1

Un web crawler potrebbe aiutarti a determinare quali URL sono accessibili. Soprattutto se è abbastanza intelligente per estrarre collegamenti da Flash o JavaScript. Una volta che hai un elenco di pagine Web, esaminale ed elenca i file a cui fanno riferimento. Tutto ciò che rimane dopo questo processo dovrebbe essere considerato un codice morto.


1
Non sono assolutamente d'accordo con la tua ultima frase. Il crawler può solo scoprire quali pagine sono collegate tra loro come un grafico diretto con un singolo o più punti di partenza. Ma mentre parliamo di un sito Web, ci sono anche le cosiddette "landing page", che rimandano ad altre pagine ma non vi sono collegamenti che puntino a esse. Inoltre, potrebbero esserci vecchie parti dell'interfaccia amministrativa che sono anche disconnesse da altre pagine. Attualmente ho un progetto di questo tipo.
scriptin

0

Nota: ho messo l'accento sull'utilizzo del database, mentre mi hai chiesto dell'uso del codice stesso. La risposta vale ancora per entrambi i casi in ogni punto che ho citato.

Hai già risposto in parte alla tua domanda nell'ultimo paragrafo: vedi cosa si accede mentre l'applicazione è in esecuzione.

  1. È possibile che si desideri creare un profilo del database e chiedere al profiler di registrare tutte le query per un giorno. Ti fornirà una panoramica degli oggetti di database più utilizzati, ma non ti dirà quali non vengono mai utilizzati. Inoltre, devi comunque fare attenzione ai risultati: ad esempio una tabella può essere utilizzata esclusivamente attraverso le procedure memorizzate, ma quando guarderai le query dal profiler, sembrerebbe che la tabella non venga utilizzata affatto.

  2. La revisione del codice sorgente, la ricerca di query è più utile e, dopo aver raccolto tutte le query, è possibile avere una buona comprensione dell'utilizzo del database, non in termini di frequenza (è qui che un profiler è utile), ma in termini di usato / no tavoli usati. Purtroppo, per una base di codice scritta male / non mantenuta per anni, può essere estremamente difficile e soggetta a errori , specialmente se le query sono costruite in modo dinamico (immagina un metodo che, in a select, utilizza un parametro come nome della tabella; come puoi possibilmente sapere quali sono i possibili valori del parametro semplicemente guardando il codice sorgente?).

  3. Anche l'analisi statica e alcuni compilatori possono rivelare un codice morto, ma non ti danno ancora la risposta che desideri.

  4. L'analisi dei dati stessi o dei metadati del database può rivelare alcune informazioni interessanti. Ad esempio, sarebbe facile per affermare che la tabella LogonAudit(uniqueidentifier LogonAuditId, datetime LogonEvent, ...)non viene più utilizzato, se contiene 10 000 registrazioni al giorno per gli anni dal 2006 al 2009, e nessun record da settembre, il 18 ° , 2009. Lo stesso non vale per una tabella che contiene i dati indentati in gran parte di sola lettura.

Questi quattro punti insieme ti daranno l'elenco delle tabelle utilizzate. Quelli rimanenti vengono utilizzati o meno. Puoi fare affermazioni e testarle, ma senza una buona copertura dei test unitari non sarebbe facile. Anche qualsiasi modo "semplice" fallirebbe. Ad esempio, se si dispone di una products_delme_not_usedtabella, è possibile affermare che la tabella non viene utilizzata affatto e verificare la presenza di "products_delme_not_used" nel codice. Questo è ottimista: non è insolito trovare il candidato DailyWTF come questo in una vecchia base di codice:

// Warning: WTF code below. Read with caution, never reuse it, and don't trust
// the comments.

private IEnumerable<Product> GetProducts()
{
    // Get all the products.
    return this.GetEntities<Product>("PRODUCT");
}

private IEnumerable<T> GetEntities<T>(string tableName)
{
    // Everyone knows that SQL is case sensitive.
    tableName = tableName.ToLower();

    if (tableName == "user" || tableName == "product")
    {
        // Those tables were renamed recently in the database. Don't have time
        // to refactor the code to change the names everywhere.
        // TODO: refactor the code and remove this `if` block.
        tableName += "s";
    }

    if (this.IsDelme(tableName))
    {
        // We have some tables which are marked for deletion but are still
        // used, so we adjust their name.
        tableName = this.Delme(tableName);
    }

    return this.DoSelectQuery<T>("select top 200 * from " + tableName);
}

private bool IsDelme(string name)
{
    // Find if the table is among candidates for removal.
    List<string> names = this.Query<string>("select Names from DelmeTables");
    return names.Contains(name);
}

private string Delme(string name)
{
    // Return the new name for a table renamed for deletion.
    return string.Join("_", new [] { name, "delme", "not", "used" });
}

Riesci a capire che questo codice utilizza effettivamente la products_delme_not_usedtabella?

Se fossi in te lo farei:

  1. Mantieni in posizione tutti gli oggetti del database,
  2. Rifattorizza l'intera applicazione (se ne vale la pena),
  3. Documentare (durante il refactoring) l'applicazione e in particolare l'utilizzo del database.

Al termine degli ultimi due passaggi, avrai probabilmente una migliore comprensione dell'utilizzo del database, che ti aiuterà a capire i nomi delle tabelle che non vengono più utilizzati e che potrebbero rimuoverli più o meno in sicurezza.


0

Mi sembra che tu abbia bisogno di informazioni sufficienti per creare un preventivo, quindi mi concentrerò su quello sforzo.

Vorrei provare a determinare quanti casi d'uso sono coinvolti in questo sito. Questo in genere ti dà un'idea di quanto sia grande e complicato il sito e di quanto tempo ci vorrà per ricreare o mantenere il sito / l'applicazione.

Sì, è vero che a volte il codice non viene più utilizzato e renderà l'applicazione un po 'più grande di quanto non sia in realtà, ma non credo che questo influenzerà i numeri di oltre il 20% al massimo , quindi non mi preoccuperei per quella parte.

Osservare il codice sorgente, le pagine Web e le tabelle del database dovrebbe aiutarti a scoprirlo.

Potresti anche considerare di limitare il numero di ore al mese che spenderai per questo progetto per la tariffa predeterminata per proteggerti.

Per quanto riguarda la scoperta di ciò che viene utilizzato e non utilizzato, non esiste davvero un modo semplice. Gli strumenti di analisi del codice possono essere d'aiuto, ma dal momento che hai a che fare con un male così misto non credo che esista alcun singolo strumento che possa aiutare. Per ogni area specifica è probabilmente possibile trovare uno strumento di analisi del codice che può essere d'aiuto.

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.