Perché usare System.out.println () è così male? [chiuso]


18

Naturalmente, è molto utile utilizzare un framework di registrazione per i messaggi di errore o gli avvisi. Ma a volte uso System.out.println () se voglio provare qualcosa di nuovo in breve tempo.

È davvero così male usare System.out.println () per alcuni test rapidi?


3
No. È un test rapido, a chi importa?
Bryan Boettcher,

10
Chi dice che è cattivo? Qual è l'alternativa?
James,

1
Gli strumenti di revisione del codice statico di @Kayser sono inappropriati per i test rapidi - sono più per il codice che intendi sviluppare con altri (o che altri dovranno capire). La lezione che sembra apprendere quest'anno è che ci sono spazi problematici molto diversi, anche durante la giornata lavorativa, che richiedono set di strumenti e pratiche molto diversi. Quindi per il tuo test rapido, buttalo tutto e usa Groovy :)
Bill K,

1
Prova a usare System.err.println()e guarda cosa succede. Immagino che lo strumento pensi che stai usando System.outper lo scopo sbagliato.
Izkata,

2
Il problema principale riguarda la scalabilità e il controllo. Se hai milioni di queste affermazioni, come puoi vedere cosa devi vedere. Se devi reagire a uno di questi, come puoi farlo in modo programmatico. I framework di registrazione sono generalmente quei due pensieri applicati a System.out.

Risposte:


18

Come rivelato nei commenti, la vera domanda che viene posta è: Perché gli strumenti di analisi del codice statico indicano gli usi di System.out.println?

Il motivo è che l'invio di messaggi a stdout è generalmente inappropriato in un ambiente di produzione. Se stai codificando una libreria, la libreria dovrebbe restituire informazioni al chiamante, non stampare su stdout. Se stai codificando un'app GUI, le informazioni dovrebbero essere presentate all'utente, non a dove stdout sembra puntare (che potrebbe non essere da nessuna parte). Se stai codificando un server (o qualcosa che viene eseguito in un contenitore sul lato server), dovresti utilizzare qualsiasi funzione di registrazione fornita dal framework. E così via.

Ma se stai usando println per il debug o lo sviluppo, o stai scrivendo un programma e legge stdin e scrive su stdout, println va benissimo. Non c'è niente di sbagliato in questo tipo di casi.


3
Bella risposta. Grazie .. +1 per "Se stai codificando un'app GUI, le informazioni dovrebbero essere presentate all'utente, non a dove stdout sembra puntare (che potrebbe non essere da nessuna parte)"
Kayser

10

Tutto stdoutè bufferizzato, quindi è possibile che il programma si arresti in modo anomalo dopo aver chiamato println(), ma prima che raggiunga lo schermo.

Detto questo, questo scenario è davvero improbabile. Vai avanti e usalo, ma mantieni quel limite minore nella parte posteriore della tua mente.


Almeno due principali interpreti Python si sforzano molto di svuotare tutti i file aperti prima dell'uscita, anche se l'uscita è dovuta a un'eccezione non gestita. Le JVM non fanno qualcosa di simile?

1
@delnan, possibilmente, ma può succedere di tutto. (Il codice che elimina stdout potrebbe essere il punto in cui si presenta il problema. Il thread in esecuzione potrebbe essere chiuso forzatamente. Il processo corrente potrebbe essere scaricato forzatamente dalla memoria dal sistema operativo.) Non vivere la tua vita attorno alla mia affermazione, ma basta esserne consapevoli.
riwalk

1
Il codice che elimina stdout si trova nella VM stessa e quindi non è influenzato da errori nella lingua implementata dalla VM. Un buon punto sulla fine del processo forzato. Ma nota che, ad esempio, SIGTERM di Unix e la maggior parte degli altri segnali possono essere catturati per eseguire la pulizia in questo modo, tuttavia non funziona con SIGKILL più estremo.

2
Non credo di aver mai visto questo o sentito parlare di ciò, anche se ho visto altri problemi. Inoltre, è probabile che questo problema non migliori con strumenti come i logger poiché è probabile che utilizzino System.out come strumento sottostante.
Bill K,

@delnan Non dare mai per scontato che il tuo codice di pulizia sia garantito per essere eseguito ... e non mettere mai il codice di transazione aziendale critico in blocchi finalmente;) System.out va bene per il debug, ma fai attenzione al buffering.
Steven,

8

System.outè solo un incartato BufferedOutputStream. Questo è probabilmente simile a qualsiasi framework di registrazione che utilizzerai, i framework forniscono solo più funzionalità sotto forma di configurazione e destinazione dell'output del log


4
Questo non risponde davvero alla domanda. "È male?"
sergserg,

@Berg - Perché quella parte della domanda dipende completamente dal contesto. (o semplicemente no, non è male)
spinning_plate il

7

È un male se stai lavorando su un programma non banale e tu

  • Stanno usando System.out come stampella anziché come test unitario automatizzato (JUnit)
  • Trascorrere molto tempo a creare e cancellare o commentare / annullare il commento delle istruzioni System.out

1
La maggior parte degli IDE dovrebbe avere tasti di scelta rapida per completare automaticamente System.out.println, commentare / annullare il commento di una riga ed eliminare una riga. Hai ragione in linea di principio a cercare di evitarne un uso eccessivo, ma puoi almeno risparmiare tempo in questo modo.
Steven,

7

Ci sono alcune avvertenze sull'uso System.out, anche nel codice usa e getta.

Un grosso problema è che di solito è lento . Ad esempio, se stai cercando di avere un'idea approssimativa della velocità di alcuni codici (nota che i microbenchmark sono difficili ), quindi l'aggiunta di un singolo System.out.println()ovunque può davvero rovinare i tuoi tempi (perché è sincronizzato e spesso attende che l'output effettivo sia essere visibile all'utente prima di tornare).

A parte questo, non me ne preoccuperei troppo nel codice usa e getta. Se si intende impegnarlo (sia come codice di produzione o come codice di prova), è necessario eliminarlo e sostituirlo con una chiamata di registrazione del propper (sì, anche nel codice di prova).


Le prestazioni sono un buon argomento ..
Kayser,

4

Come spesso accade, la risposta è "dipende". Se l'applicazione dispone già di un framework di registrazione, è possibile utilizzarlo. Non può essere meno capace di println(), e potresti trarre vantaggio da altre funzionalità che fornisce: impilare tracce, contesto extra, migliore formattazione e così via. Esiste inoltre la chiara possibilità che i framework di registrazione offrano un migliore recupero degli errori, garantendo che i log vengano scritti correttamente anche in caso di errore irreversibile.

Quindi la domanda diventa quando aggiungere un sistema di registrazione in primo luogo. Questa è una chiamata di giudizio: non vuoi aggiungerla troppo presto, solo per scoprire che non ne hai davvero bisogno. Inoltre, non vuoi aggiungerlo troppo tardi e fare un lavoro eccessivo convertendolo dalla tua soluzione ad hoc.

Se scopri che stai effettuando molti accessi println(), allora la tua base di codice sta cercando di dirti che sta soffrendo di problemi. A quel punto, vale la pena investire nella registrazione adeguata.


3

Ho spesso il problema che System.out.print utilizza la tabella codici "predefinita di sistema", che spesso è UTF-8 su Linux, ma alcune cose MS saltate su Windows.

Ciò può portare a caratteri unicode che sono o non sono stampati correttamente sullo schermo, a seconda di dove viene eseguito il programma.

Preferisco quindi un PrintWriter personalizzato rispetto a System.out


Per roba da MS crapped. Intendi CP1352 o UTF16?
Cole Johnson,

@ColeJohnson: la finestra della console di Windows è purtroppo ancora bloccata in un'era pre-UTF16. L'uso di un IDE sano con console integrata può tuttavia ridurre questo problema.
Joachim Sauer,

@Cole Johnson - Potrei vivere con CP 65001 (cioè utf8), ma sembra che non ci sia modo di ottenerlo come tabella codici "default di sistema", quando, ad esempio, hai una tastiera tedesca ottieni CP 850 o qualcosa del genere.
Ingo,

1

Non è affatto male. L'idea potrebbe derivare dal fatto che è molto semplice e non sofisticato come l'utilizzo di un framework di registrazione dedicato nell'applicazione.

Tuttavia, questo non vuol dire che si tratta di un approccio non valido. L'ho usato molte volte per controllare il flusso dell'applicazione dopo alcuni dirottamenti di programmazione voodoo di magia nera .


0

Non c'è niente di sbagliato nell'usarlo, ti aiuta a capire "che diavolo sta succedendo".

Ma se i tuoi colleghi / altri sviluppatori / strumenti ti stanno ridicolizzando, puoi sempre usare Logger o iniziare i test Junit !


0

Il problema più grande con l'occasionale System.out.println, a mio modo di vedere, è che si tratta di un "cattivo odore di abitudine (tm)". Se ti ritrovi a fare questo, allora probabilmente potresti migliorare la tua efficacia diventando più comodo usando il tuo debugger preferito.

Anche con un debugger, sai per certo che un breakpoint non scivolerà nel tuo codice di produzione, mentre un System.out.println potrebbe farlo.

In una nota a margine, se in realtà stai solo facendo un test rapido e persisti nel non usare un debugger, penso che System.out.println sia meglio dell'uso di un framework di registrazione, poiché se lasci accidentalmente un'istruzione log.debug quando fatto, è più difficile sradicare.


0

Costruire un'intera strategia di test per echeggiare il contenuto dello stato interno non è la mossa più intelligente ma per test rapidi e sporchi di codice in sviluppo la stampa dispari qui e lì non farà male finché ti ricordi di rimuoverli!

Il pericolo di dimenticare di rimuoverli è probabilmente il motivo per cui è sconsigliato.


Qual è il problema di dimenticare di rimuoverli secondo te? Sicuramente ci saranno alcuni messaggi in più sulla console. Vedi qualche altro problema?
Kayser,
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.