Come trovare codice non utilizzato / morto nei progetti Java [chiuso]


306

Quali strumenti usi per trovare codice non utilizzato / morto in grandi progetti Java? Il nostro prodotto è in fase di sviluppo da alcuni anni e sta diventando molto difficile rilevare manualmente il codice che non è più in uso. Cerchiamo comunque di eliminare quanto più codice inutilizzato possibile.

Sono apprezzati anche suggerimenti per strategie / tecniche generali (diversi dagli strumenti specifici).

Modifica: Nota che già utilizziamo strumenti di copertura del codice (Clover, IntelliJ), ma questi sono di scarso aiuto. Il codice morto ha ancora test unitari e si presenta come coperto. Immagino che uno strumento ideale identificherebbe i gruppi di codice che hanno pochissimo altro codice a seconda di esso, consentendo l'ispezione manuale dei documenti.


16
Mantenere i test unitari in un albero di origine separato (si dovrebbe comunque) ed eseguire gli strumenti di copertura solo sull'albero vivo.
agnul

5
Vorrei iniziare con l' ispezione "Dichiarazione non utilizzata" di IDEA e deselezionare Includi fonti di test . Puoi chiarire cosa intendi quando dici "di scarso aiuto" di IDEA?
David Moles,

1
Modi per trovare il codice morto: 1) non collegato da nulla al di fuori. 2) non è stato utilizzato dall'esterno anche se collegato in runtime. 3) Collegato e chiamato ma mai usato come variabile morta. 4) stato logicamente irraggiungibile. Quindi collegamento, accesso nel tempo, basato sulla logica, uso dopo l'accesso.
Muhammad Umer,

Usa IntelliJ Idea e la mia risposta da qui: stackoverflow.com/questions/22522013/... :)
BlondCode

Aggiunta alla risposta di David Mole: vedi questa risposta stackoverflow.com/a/6587932/1579667
Benj

Risposte:


40

Strumenterei il sistema in esecuzione per tenere registri dell'utilizzo del codice e quindi iniziare a ispezionare il codice che non viene utilizzato per mesi o anni.

Ad esempio, se si è interessati a classi inutilizzate, tutte le classi potrebbero essere strumentate per registrare quando vengono create le istanze. Quindi un piccolo script potrebbe confrontare questi registri con l'elenco completo delle classi per trovare le classi inutilizzate.

Ovviamente, se vai a livello di metodo, dovresti tenere a mente le prestazioni. Ad esempio, i metodi potevano registrare solo il loro primo utilizzo. Non so come sia meglio farlo in Java. Lo abbiamo fatto in Smalltalk, che è un linguaggio dinamico e consente quindi la modifica del codice in fase di esecuzione. Strumentiamo tutti i metodi con una chiamata di registrazione e disinstalliamo il codice di registrazione dopo che un metodo è stato registrato per la prima volta, quindi dopo un po 'di tempo non si verificano più penali di prestazione. Forse una cosa simile può essere fatta in Java con flag booleani statici ...


5
Mi piace questa risposta, ma qualcuno ha idea di come farlo in Java senza aggiungere esplicitamente la registrazione in ogni classe? Forse un po 'di magia "Proxy"?
Programmatore fuorilegge il

14
@Outlaw AOP sembra essere il caso d'uso perfetto per questo.
Pascal Thivent,

6
Se si capisce la struttura di caricamento di classe dell'applicazione, è possibile utilizzare AOP sul programma di caricamento classi per tenere traccia degli eventi di caricamento di classe. Ciò sarebbe meno invasivo su un sistema di produzione rispetto alla consulenza di tutti i costruttori.
ShabbyDoo,

5
Questa risposta è abbastanza buona per un linguaggio dinamico ma terribile per un linguaggio statico che potrebbe fare MOLTO meglio. Con un linguaggio tipicamente statico (a parte la riflessione) puoi sapere con certezza esattamente quali metodi sono usati e quali no, questo è uno dei maggiori vantaggi di un linguaggio tipicamente statico e dovresti usarlo piuttosto che il metodo di cui sopra come descritto qui .
Bill K,

4
@BillK succede più riflessione di quanto pensi. Ad esempio la primavera fa un bel po 'di magia sotto le coperte, incluso il riflesso. Lo strumento di analisi deve emularlo.
Thorbjørn Ravn Andersen,

220

Un plugin Eclipse che funziona abbastanza bene è Unused Code Detector .

Elabora un intero progetto o un file specifico e mostra vari metodi di codice inutilizzato / morto, oltre a suggerire cambiamenti di visibilità (ovvero un metodo pubblico che potrebbe essere protetto o privato).


Sembra carino ma non sono riuscito a farlo funzionare - l'azione "Rileva un ... codice" è disabilitata e non ho trovato il modo per abilitarlo.
Ondra Žižka,

1
Trovi davvero metodi inutilizzati, MA scopri anche che i miei EJB non vengono utilizzati (mentre lo sono) perché sto usando un modello di progettazione di delegati aziendali
Eildosa,

Funziona ancora su Kepler? le versioni parlano di eclipse 3.8: ucdetector.org/releases.html
Mr_and_Mrs_D

Sembra essere in perfette condizioni di lavoro su Kepler.
Erik Kaplun,

4
Vuoi aggiungere un link al marketplace marketplace.eclipse.org/content/unnecessary-code-detector ? Ciò semplifica l'installazione e risponde alla domanda se è supportato su versioni più recenti di Eclipse.
Thomas Weller,

64

CodePro è stato recentemente rilasciato da Google con il progetto Eclipse. È gratuito e molto efficace. Il plugin ha una funzione ' Trova codice morto ' con uno / più punti di ingresso. Funziona abbastanza bene.


1
Non funzionerà più con Eclipse Kepler. Dopo averlo installato correttamente tramite il sito di aggiornamento, ogni volta si arresta l'eclipse.
txulu,

Sfortunatamente, sembra che questo strumento non si renda conto dell'esistenza di Spring, quindi segnerà tutti i miei @Components come inutilizzati, a torto
Clint Eastwood

Diventa molto vecchio Non funziona più Last updated this plugin March 27, 2012 developers.google.com/java-dev-tools/download-codepro
mumair

2
Tutti i collegamenti sono obsoleti.
zygimantus

3
Purtroppo sembra che Google abbia scaricato il codice sul progetto Eclipse e se ne sia dimenticato tutto.
Thorbjørn Ravn Andersen,

30

Sono sorpreso che ProGuard non sia stato menzionato qui. È uno dei prodotti più maturi in circolazione.

ProGuard è un restringitore, ottimizzatore, offuscatore e preverificatore di file Java gratuito. Rileva e rimuove classi, campi, metodi e attributi non utilizzati. Ottimizza il bytecode e rimuove le istruzioni non utilizzate. Rinomina le restanti classi, campi e metodi usando nomi brevi privi di significato. Infine, preverifica il codice elaborato per Java 6 o Java Micro Edition.

Alcuni usi di ProGuard sono:

  • Creazione di codice più compatto, per archivi di codice più piccoli, trasferimento più veloce attraverso le reti, caricamento più veloce e impronte di memoria più piccole.
  • Rendere i programmi e le librerie più difficili da decodificare.
  • Elenco del codice morto, quindi può essere rimosso dal codice sorgente.
  • Retargeting e pre-verifica dei file di classe esistenti per Java 6 o versioni successive, per sfruttare appieno il loro caricamento di classe più veloce.

Ecco un esempio di elenco dei codici non validi : https://www.guardsquare.com/en/products/proguard/manual/examples#deadcode


8
Fornire un esempio di utilizzo fornirebbe una risposta migliore.
martedì

1
Leggendo la documentazione, vedo che riduce il codice inutilizzato, ma non riesco a trovare da nessuna parte dove lo elenca - concordato, un esempio o un collegamento alla sezione pertinente della documentazione, sarebbe abbastanza utile!
orbfish

26

Una cosa che sono stato conosciuto per fare in Eclipse, su una singola classe, è cambiare tutti i suoi metodi in privato e poi vedere quali lamentele ricevo. Per i metodi utilizzati, ciò provocherà errori e li restituirò al livello di accesso più basso possibile. Per i metodi non utilizzati, ciò provocherà avvisi sui metodi non utilizzati e questi potranno quindi essere eliminati. E come bonus, spesso trovi alcuni metodi pubblici che possono e devono essere resi privati.

Ma è molto manuale.


4
Forse non è la risposta ideale, ma è davvero intelligente.
Erik Reppen,

8
È intelligente ... fino a quando non hai ricevuto una chiamata da un codice inutilizzato di un'altra classe.
Danosaure,

L'iterazione su questo metodo potrebbe rimuovere enormi quantità di codice mentre un metodo utilizzato ne crea altri una volta rimosso.
4mile,

15

Utilizzare uno strumento di copertura test per strumentare la base di codice, quindi eseguire l'applicazione stessa, non i test.

Emma ed Eclemma ti daranno dei bei rapporti su quale percentuale di quali classi vengono eseguite per ogni data esecuzione del codice.


1
+1 perché è un buon punto di partenza, ma tieni presente che anche le variabili non utilizzate (ma dichiarate) diventeranno verdi.
DerMike,

13

Abbiamo iniziato a utilizzare Trova bug per aiutare a identificare parte del funk nell'ambiente ricco di target della nostra base di codice per i refactoring. Vorrei anche considerare Structure 101 per identificare i punti nell'architettura della tua base di codice che sono troppo complicati, quindi sai dove sono le vere paludi.


4
FindBugs non è in grado di rilevare codice morto e inutilizzato, solo campi non utilizzati. Vedere questo risposta .
Stefan Mücke,

12

In teoria, non è possibile trovare in modo deterministico codice inutilizzato. C'è una dimostrazione matematica di questo (beh, questo è un caso speciale di un teorema più generale). Se sei curioso, cerca il problema Halting.

Questo può manifestarsi nel codice Java in molti modi:

  • Caricamento di classi in base all'input dell'utente, ai file di configurazione, alle voci del database, ecc .;
  • Caricamento codice esterno;
  • Passare alberi degli oggetti a librerie di terzi;
  • eccetera.

Detto questo, uso IDEA IntelliJ come IDE di mia scelta e ha ampi strumenti di analisi per trovare dipendenze tra moduli, metodi inutilizzati, membri inutilizzati, classi inutilizzate, ecc. È abbastanza intelligente come un metodo privato che non viene chiamato è taggato inutilizzato ma un metodo pubblico richiede analisi più approfondite.


1
Grazie per il tuo contributo. Stiamo usando IntelliJ e stiamo ottenendo un aiuto lì. Per quanto riguarda il problema dell'arresto e l'indecidibilità, ho familiarità con la teoria, ma non abbiamo necessariamente bisogno di una soluzione deterministica.
Knatten,

12
La frase di apertura è troppo forte. Come nel caso del problema dell'arresto (spesso spesso citato / abusato), non esistono soluzioni generali complete, ma ci sono molti casi speciali che sono fattibili da rilevare.
joel.neely,

9
Anche se non esiste una soluzione generale per le lingue con valutazione e / o riflessione, ci sono molti casi in cui il codice è chiaramente irraggiungibile.
pjc50,

1
Senza riflessione e con il codice sorgente completo qualsiasi linguaggio tipizzato staticamente dovrebbe rendere abbastanza facile trovare in modo deterministico tutto il codice inutilizzato.
Bill K,

Non riesci a trovare ciò che è provabile irraggiungibile dalla riflessione o da chiamanti esterni, ma puoi trovare il codice che è provabile irraggiungibile staticamente da un determinato punto di ingresso o set di punti di ingresso
nafg

8

In Eclipse, vai a Windows> Preferenze> Java> Compilatore> Errori / Avvisi
e modifica tutti in errori. Risolvi tutti gli errori. Questo è il modo più semplice. Il bello è che questo ti permetterà di ripulire il codice mentre scrivi.

Screenshot Codice Eclipse:

inserisci qui la descrizione dell'immagine


5

IntelliJ dispone di strumenti di analisi del codice per rilevare il codice non utilizzato. Dovresti provare a rendere il maggior numero possibile di campi / metodi / classi non pubblici e ciò mostrerà più metodi / campi / classi inutilizzati

Vorrei anche provare a individuare il codice duplicato come un modo per ridurre il volume del codice.

Il mio ultimo suggerimento è provare a trovare il codice open source che, se usato, renderebbe il tuo codice più semplice.


Qualche esempio di cosa sono questi strumenti?
orbfish

@orbfish Puoi eseguire Analyse=> Run inspection by name=>unused
Peter Lawrey il


3

DCD non è un plug-in per alcuni IDE ma può essere eseguito da formica o autonomo. Sembra uno strumento statico e può fare ciò che PMD e FindBugs non possono fare . Lo proverò.

PS Come menzionato in un commento qui sotto, il Progetto vive ora in GitHub .


Questo dovrebbe scendere come un commento non rispondere
Conta il

Aggiorna la tua risposta per rimuovere la tua affermazione che DCD "sembra morto ora". La versione 2.1 è stata rilasciata 12 giorni fa . Inoltre, il link nella tua risposta non funziona.
skomisa,

2

Esistono strumenti che codificano il codice e forniscono dati sulla copertura del codice. Questo ti permette di vedere (mentre il codice viene eseguito) quanto viene chiamato. Puoi ottenere uno di questi strumenti per scoprire quanto codice orfano hai.


2
  • FindBugs è eccellente per questo genere di cose.
  • PMD (Project Mess Detector) è un altro strumento che può essere utilizzato.

Tuttavia, nessuno dei due può trovare metodi statici pubblici non utilizzati in un'area di lavoro. Se qualcuno conosce un tale strumento, per favore fatemelo sapere.


1

Strumenti di copertura degli utenti, come EMMA. Ma non è uno strumento statico (cioè richiede di eseguire effettivamente l'applicazione attraverso il test di regressione e tutti i possibili casi di errore, il che è, beh, impossibile :))

Tuttavia, EMMA è molto utile.


1

Gli strumenti di copertura del codice, come Emma, ​​Cobertura e Clover, strumenteranno il tuo codice e registreranno quali parti vengono invocate eseguendo una serie di test. Questo è molto utile e dovrebbe essere parte integrante del tuo processo di sviluppo. Ti aiuterà a identificare quanto bene la tua suite di test copre il tuo codice.

Tuttavia, questo non è lo stesso dell'identificazione del codice morto reale. Identifica solo il codice che è coperto (o non coperto) dai test. Questo può darti falsi positivi (se i tuoi test non coprono tutti gli scenari) così come falsi negativi (se i tuoi test accedono a un codice che in realtà non viene mai utilizzato in uno scenario del mondo reale).

Immagino che il modo migliore per identificare realmente il codice morto sarebbe quello di strumentare il tuo codice con uno strumento di copertura in un ambiente in esecuzione dal vivo e di analizzare la copertura del codice per un lungo periodo di tempo.

Se si esegue in un ambiente ridondante con bilanciamento del carico (e, in caso contrario, perché no?) Quindi suppongo che avrebbe senso strumentare solo un'istanza dell'applicazione e configurare il bilanciamento del carico in modo tale che una porzione casuale, ma piccola, di i tuoi utenti corrono sulla tua istanza strumentata. Se lo fai per un lungo periodo di tempo (per assicurarti di aver coperto tutti gli scenari di utilizzo del mondo reale - tali variazioni stagionali), dovresti essere in grado di vedere esattamente quali aree del tuo codice sono accessibili sotto l'uso del mondo reale e quali parti davvero non si accede mai e quindi codice morto.

Non l'ho mai visto personalmente e non so come gli strumenti di cui sopra possano essere utilizzati per strumentare e analizzare il codice che non viene invocato attraverso una suite di test, ma sono sicuro che possano esserlo.


1

Esiste un progetto Java - Dead Code Detector (DCD). Per il codice sorgente non sembra funzionare bene, ma per il file .jar - è davvero buono. Inoltre puoi filtrare per classe e per metodo.



0

Eclipse può mostrare / evidenziare il codice che non può essere raggiunto. JUnit può mostrarti la copertura del codice, ma avresti bisogno di alcuni test e devi decidere se manca il test rilevante o se il codice è davvero inutilizzato.


3
Eclipse ti dirà solo se l'ambito del metodo è locale (cioè privato); e anche in questo caso non puoi essere sicuro al 100% ... con la riflessione il metodo privato potrebbe essere chiamato dall'esterno.
p3t0r,

0

Ho trovato lo strumento di copertura Clover che codifica strumenti ed evidenzia il codice che viene utilizzato e che non viene utilizzato. A differenza di Google CodePro Analytics, funziona anche con WebApplications (secondo la mia esperienza e potrei non essere corretto su Google CodePro).

L'unico inconveniente che ho notato è che non tiene conto delle interfacce Java.


Afaict, è uno strumento CI lato server non libero.
Erik Kaplun,

0

Uso Doxygen per sviluppare una mappa delle chiamate dei metodi per individuare metodi che non vengono mai chiamati. Nel grafico troverai isole di cluster di metodi senza chiamanti. Questo non funziona per le librerie poiché è necessario iniziare sempre da un punto di ingresso principale.

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.