Por que usar System.out.println () é tão ruim? [fechadas]

18

Obviamente, é muito bom usar uma estrutura de log para mensagens de erro ou avisos. Mas às vezes eu uso System.out.println () se quiser tentar algo novo em pouco tempo.

É realmente tão ruim usar System.out.println () para algum teste rápido?

Kayser
fonte
3
Não. É um teste rápido, quem se importa?
precisa
10
Quem disse que é ruim? Qual a alternativa?
James James
1
As ferramentas de revisão de código estático do @Kayser são inadequadas para testes rápidos - são mais para o código que você pretende desenvolver com outras pessoas (ou que outras terão que entender). A lição que pareço aprender este ano é que existem espaços com problemas muito diferentes, mesmo durante o dia de trabalho, que exigem conjuntos de ferramentas e práticas muito diferentes. Portanto, para o seu teste rápido, jogue tudo e use o Groovy :) #
Bill K
1
Tente usar System.err.println()e veja o que acontece. Suponho que a ferramenta pense que você está usando System.outcom o objetivo errado.
Izkata
2
O principal problema é com escalabilidade e controle. Se você possui milhões dessas declarações, como pode ver o que precisa ver. Se você precisar reagir a uma delas, como você pode fazer isso programaticamente. As estruturas de log são geralmente esses dois pensamentos aplicados ao System.out.

Respostas:

18

Conforme revelado nos comentários, a verdadeira pergunta é: Por que as ferramentas de análise de código estático sinalizam os usos do System.out.println?

O motivo é que o envio de mensagens para o stdout geralmente é inadequado em um ambiente de produção. Se você estiver codificando uma biblioteca, a biblioteca deve retornar informações ao chamador, não imprimir em stdout. Se você estiver codificando um aplicativo GUI, as informações devem ser apresentadas ao usuário, e não para onde o stdout está apontando (o que pode não estar em lugar nenhum). Se você estiver codificando um servidor (ou algo que é executado em um contêiner do lado do servidor), você deve usar qualquer recurso de registro fornecido pela estrutura. E assim por diante.

Mas se você estiver usando println para depuração ou desenvolvimento, ou estiver escrevendo um programa e ler stdin e gravar em stdout, println estará perfeitamente bem. Não há nada de errado com esse tipo de casos.

Stuart Marks
fonte
3
Boa resposta. Graças .. +1 para "Se você está programando um aplicativo GUI, a informação deve ser apresentada ao usuário, não para onde stdout passa a ser apontando (que pode estar em lugar nenhum)"
Kayser
10

Tudo stdouté armazenado em buffer e, portanto, é possível que seu programa falhe depois que você ligou println(), mas antes que chegue à tela.

Com isso dito, esse cenário é realmente improvável. Vá em frente e use-o, mas mantenha essa pequena limitação no fundo da sua mente.

riwalk
fonte
Pelo menos dois grandes intérpretes de Python tentam liberar todos os arquivos abertos antes da saída, mesmo que a saída seja devido a uma exceção sem tratamento. As JVMs não fazem algo semelhante?
1
@ Delnan, Possivelmente, mas tudo pode acontecer. (O código que libera stdout pode ser o local onde o problema surge. O encadeamento em que você está executando pode ser fechado com força. O processo atual pode ser forçado a ser despejado da memória pelo sistema operacional.) Não viva sua vida em torno da minha declaração, mas apenas esteja ciente disso.
riwalk
1
O código que libera stdout está na própria VM e, portanto, não é afetado por erros no idioma implementado pela VM. Bom ponto sobre o final do processo forçado. Mas observe que, por exemplo, o SIGTERM do Unix e a maioria dos outros sinais podem ser capturados para fazer uma limpeza como esta - embora não funcione com o SIGKILL mais extremo.
2
Acho que nunca vi isso ou ouvi falar disso, embora tenha visto outros problemas. Também não é provável que esse problema melhore com ferramentas como loggers, pois é provável que eles usem o System.out como uma ferramenta subjacente.
Bill K
@delnan Nunca assuma que o seu código de limpeza é executado ... e nunca coloque o código crítico da transação comercial nos blocos finalmente;) System.out é bom para depuração, mas esteja atento ao buffer.
Steven
8

System.outé apenas um embrulho BufferedOutputStream. Provavelmente, isso é semelhante a qualquer estrutura de log que você usará; as estruturas apenas fornecem mais funcionalidade na forma de configuração e destino da sua saída de log

spinning_plate
fonte
4
Isso realmente não responde à pergunta. "É ruim?"
sergserg
@ Berg - Porque essa parte da questão é completamente dependente do contexto. (ou simplesmente, não, não é ruim) #
spinning_plate
7

É ruim se você estiver trabalhando em um programa não trivial e você

  • Estão usando System.out como muleta em vez de teste de unidade automatizado (JUnit)
  • Gaste muito tempo criando e excluindo ou comentando / descomentando instruções System.out
Aaron Kurtzhals
fonte
1
A maioria dos IDE deve ter teclas de atalho para o preenchimento automático de System.out.println, comentar / descomentar uma linha e excluir uma linha. Você está certo em princípio em tentar evitar o uso excessivo, mas pode pelo menos economizar tempo dessa maneira.
Steven
7

Existem algumas advertências sobre o uso System.out, mesmo em código descartável.

Um grande problema é que geralmente é lento . Por exemplo, se você está tentando ter uma idéia aproximada da velocidade de algum código (observe que as marcas de microbench são difíceis ), adicionar um único em System.out.println()qualquer lugar pode realmente atrapalhar o seu tempo (porque está sincronizando e geralmente aguarda a saída real) fique visível para o usuário antes de retornar).

Fora isso, eu não me preocuparia muito com isso no código descartável. Se você pretende confirmá-lo (seja como código de produção ou como código de teste), você deve se livrar dele e substituí-lo por uma chamada de registro apropriado (sim, mesmo no código de teste).

Joachim Sauer
fonte
Desempenho é um argumento bom ..
Kayser
4

Como é frequentemente o caso, a resposta é "depende". Se o seu aplicativo já tiver uma estrutura de log em vigor, você poderá usá-lo. Ele não pode ser menos capaz do que println(), e você pode se beneficiar de outros recursos que ele fornece - rastreios de pilha, contexto extra, melhor formatação e assim por diante. Há também a possibilidade distinta de que as estruturas de log oferecem melhor recuperação de erros, garantindo que seus logs sejam gravados com sucesso, mesmo no caso de uma falha catastrófica.

Portanto, a questão é quando adicionar um sistema de registro em primeiro lugar. Esta é uma decisão: você não deseja adicioná-lo muito cedo, apenas para descobrir que realmente não precisa dele. Você também não deseja adicioná-lo tarde demais e fazer um trabalho excessivo na conversão da sua solução ad-hoc.

Se você descobrir que está fazendo muito log println(), sua base de código está tentando dizer que está sofrendo dores de crescimento. Nesse ponto, vale a pena investir no registro adequado.

Jon Purdy
fonte
3

Costumo ter o problema de o System.out.print usar a página de código "padrão do sistema", que geralmente é UTF-8 no Linux, mas algumas coisas ruins da Microsoft no Windows.

Isso pode levar a caracteres unicode que são ou não são impressos corretamente na tela, dependendo de onde o programa é executado.

Portanto, prefiro um PrintWriter personalizado sobre System.out

Ingo
fonte
Por coisas ruins de MS. Você quer dizer CP1352 ou UTF16?
Cole Johnson
@ColeJohnson: Infelizmente, a janela do console do Windows ainda está presa em uma era anterior à UTF16. No entanto, o uso de um IDE sadio com console interno pode reduzir esse problema.
Joachim Sauer
@ Johnson Johnson - Eu poderia viver com o CP 65001 (ou seja, utf8), mas parece que não há como obtê-lo como página de código "padrão do sistema", quando, por exemplo, você tem um teclado alemão, obtém o CP 850 ou algo parecido.
Ingo
1

Não é nada mau. A noção pode resultar do fato de ser muito simples e não tão sofisticado quanto o uso de uma estrutura de log dedicada em seu aplicativo.

No entanto, isso não quer dizer que seja uma abordagem inválida. Eu o usei várias vezes para verificar o fluxo de aplicativos após alguns hijinks de programação de magia negra de vodu .

sergserg
fonte
0

Não há nada errado em usá-lo, ele ajuda a descobrir 'o que diabos está acontecendo'.

Mas se seus colegas / outros desenvolvedores / ferramentas estão ridicularizando você, você sempre pode usar o Logger ou iniciar o teste do Junit !

lwm
fonte
0

O maior problema com o System.out.println local, a meu ver, é que é um "mau hábito (tm)". Se você estiver fazendo isso, provavelmente poderá melhorar sua efetividade ficando mais confortável usando seu depurador favorito.

Também com um depurador, você tem certeza de que um ponto de interrupção não entra no seu código de produção, enquanto um System.out.println pode.

Em uma nota lateral, se você está apenas fazendo um teste rápido e persiste em não usar um depurador, acho que o System.out.println é melhor do que usar uma estrutura de log, pois se você deixar acidentalmente uma instrução log.debug quando você pronto, é mais difícil erradicar.

Buhb
fonte
0

Construir uma estratégia de teste inteira para ecoar o conteúdo do estado interno não é a jogada mais inteligente, mas para testes rápidos e sujos de código em desenvolvimento, a impressão estranha aqui e ali não será prejudicial enquanto você se lembrar de removê-los!

O perigo de esquecer de removê-los é provavelmente o motivo pelo qual é desaconselhado.

GordonM
fonte
Qual é o problema em esquecer de removê-los na sua opinião? Claro que haverá mais algumas mensagens no console. Você vê algum outro problema?
Kayser