2009-02-21 8 views
9

Abbiamo un enorme (vecchio legacy java) code-base, dove molti file (circa 5k) hanno System.out.println's. Stiamo pianificando di rimuoverli per motivi di pulizia/prestazioni. Come possiamo scrivere uno script che li sostituirà senza introdurre alcun problema nel codice? Lo script non può cancellare ciecamente loro come caso seguente può essere un problema:Come rimuovere System.out.println dalla codebase

if() 
    some.code... 
else 
    System.out.println(...); 
DB.close(); 

Sto pensando di sostituirli con ';'. Questo si occuperà del caso precedente. Vedi altri problemi? Qualche altro suggerimento?

+0

pontificate mode on :-) Questo è (tra molti altri motivi) perché uso sempre {} anche per cose di una riga! (So ​​che è legacy e probabilmente non lo farai). Li sostituirei con {} al posto di; ma entrambi stanno bene. – TofuBeer

+0

Pontificato eco: stavo per commentare la stessa identica cosa. –

+0

Lo so, e potrebbe non esserci nel codice. Tuttavia, dato che ci sono molti file e legacy (che quasi sempre significa cattivo), non voglio correre rischi. – amit

risposta

24

Avere si considera il caso sciocco:

System.out.println(" Print " + object.changeState()); 

Non credo che accada, ma è probabile che il println esegue un metodo che è in realtà eseguendo qualche azione su cui il sistema dipende e può introdurre bug sottili (credetemi o no, ma ho assistito a questo)

Probabilmente la sostituzione con un logger e la disabilitazione dei logger può fare.

o la creazione di un oggetto nullo utilizzando il modello NullObject:

public final class DevNull { 
    public final static PrintStream out = new PrintStream(new OutputStream() { 
     public void close() {} 
     public void flush() {} 
     public void write(byte[] b) {} 
     public void write(byte[] b, int off, int len) {} 
     public void write(int b) {} 

    }); 
} 

e sostituzione di

System.out.println(); 

Con

DevNull.out.println(); 
+0

Mi piace molto, Oscar. Ben pensato, devo dire. –

+0

Stordendo, ho dovuto rompere NetBeans e provarlo. – Paxic

+0

Bella idea: sarebbe ancora più facile vedere se hai cambiato il "caso stupido" da object.stateChanged() a object.changeState(), altrimenti suona come una query all'oggetto che vedo sempre come se non avessi alcun cambiamento di business lo stato degli oggetti. ... abitudine personale ... –

1

Personalmente vorrei usare {} invece, ma penso che funzioni lo stesso.

2

È possibile utilizzare un conditional compilation per avere una build di debug con il stampa dichiarazioni e una versione di build senza di loro.

Fondamentalmente, l'idea è di creare una classe statica finale con un booleano statico finale che si usa come commutatore in fase di compilazione.

public final class Debug { 
    //set to false to allow compiler to identify and eliminate 
    //unreachable code 
    public static final boolean ON = true; 
} 

Poi si può semplicemente sostituire tutti i tuoi System.out.println dichiarazioni con

if(Debug.ON) 
{ 
    System.out.println... 
} 

Dal momento che il compilatore ignorerà qualsiasi rami irraggiungibili di codice, si può solo impostare ON = false quando si esegue una build di rilascio e la stampa le dichiarazioni saranno escluse dal tuo bytecode.

Nota: Questo non si riferisce al caso che Oscar ha sottolineato, in cui un'istruzione di stampa può modificare lo stato di alcuni oggetti. È possibile utilizzare la compilazione condizionale per stampare su un oggetto nullo in modalità di rilascio, come suggerito, invece di rimuovere completamente le stampe.

11

Log4E è un plug-in di eclissi che presenta una funzionalità "Sostituisci System.out.println()". Sarà felice di convertire tutte quelle fastidiose chiamate println alle chiamate log4j. Li avvolgerà anche con un controllo del livello di registro.

+3

link: http://log4e.jayefem.de/ –

6

Si potrebbe iniziare chiamando Systems.setOut e passando nel proprio OutputStream che non fa nulla. Questo ti aiuterà a vedere se c'è un guadagno di perfomance. Questo è più sicuro che rimuoverli (per la ragione che ha sottolineato Oscar - codifica per effetto collaterale).Se il guadagno in termini di prestazioni è trascurabile, potresti voler concentrare i tuoi sforzi altrove.

Due problemi con il mio metodo di cui sopra:

  1. qualsiasi System.out.printlns si desidera mantenere saranno disapper troppo
  2. il concatination String sarà ancora prendere posto (e che può essere costoso a seconda di quanto c'è)

Tuttavia è un buon test veloce per vedere se si ottiene il guadagno di prestazioni che stai cercando.

0

Ho scritto una regex in perl che sostituisce la stringa "System.out.println" con "; // System.out.println". Credo che ci siano pochissimi casi in cui ciò romperebbe la costruzione. Sarebbe appena diventato un "else", che è compilato per azzerare le istruzioni bytecode.

Sembra che questo sia quello che hai proposto. Ha funzionato per me - tranne se hai dichiarazioni aggiuntive sulla stessa linea. Tuttavia, questo è uno stile negativo per cominciare (e sapevo di non averlo fatto).

8

Estendendo il concetto di Oscar si può fare ancora meglio IMHO:

if(!DEBUG) { 
    System.setOut(
     new PrintStream(new OutputStream() { 
      public void close() {} 
      public void flush() {} 
      public void write(byte[] b) {} 
      public void write(byte[] b, int off, int len) {} 
      public void write(int b) {} 

     }); 
    } 
} 

In questo caso, se non si è in modalità debug o qualsiasi altro sistema di default fuori è sostituito internamente con l'implementazione devnull, il resto funziona come previsto. In questo modo non devi trovare e sostituire nulla nel tuo codice.

+0

Abbastanza interessante. Le nuove istruzioni di stampa potrebbero essere gestite con i logger e disabilitare completamente System.out con questo. :) – OscarRyz

+0

Quindi, possiamo chiamare questo approccio "Oscar Reyes + Bill the Lizard"? : P: P +1 per quello – OscarRyz

+0

Questo presuppone che nessun altro codice stia già facendo setOut;) Sto scherzando. È un buon suggerimento. – amit

0

Hai pensato di modificare quei file sorgente per rimuovere le linee?

Si potrebbe scoprire che sarà solo uno sviluppatore un paio di giorni a passare e sbarazzarsi di molti di loro. Abbiamo avuto un problema simile e mi sono appena alzato molto presto e ho esaminato tutti i nostri file per liberarmi della spazzatura.

Ho usato Eclipse e la funzione di salvataggio su ripulisci per eliminare le importazioni e le cose allo stesso tempo.

È piuttosto una cosa terapeutica da fare!