¿Por qué es tan malo usar System.out.println ()? [cerrado]

18

Por supuesto, es muy bueno usar un marco de registro para los mensajes de error o advertencias. Pero a veces uso System.out.println () si quiero probar algo nuevo en poco tiempo.

¿Es realmente tan malo usar System.out.println () para alguna prueba rápida?

Kayser
fuente
3
No. Es una prueba rápida, ¿a quién le importa?
Bryan Boettcher
10
¿Quién dice que es malo? Cual es la alternativa?
James
1
Las herramientas de revisión de código estático de @Kayser son inapropiadas para las pruebas rápidas; son más para el código que tiene la intención de desarrollar con otros (o que otros tendrán que entender). La lección que parece estar aprendiendo este año es que hay espacios de problemas muy diferentes, incluso durante la jornada laboral, que requieren conjuntos de herramientas y prácticas muy diferentes. Entonces, para su prueba rápida, tírelo todo y use Groovy :)
Bill K
1
Intenta usar System.err.println()y ver qué pasa. Supongo que la herramienta cree que estás usando System.outpara un propósito incorrecto.
Izkata
2
El problema principal es con la escalabilidad y el control. Si tiene millones de estas declaraciones, ¿cómo puede ver lo que necesita ver? Si necesita reaccionar a uno de estos, ¿cómo puede hacerlo programáticamente? Los marcos de registro suelen ser esos dos pensamientos aplicados a System.out.

Respuestas:

18

Como se revela en los comentarios, la verdadera pregunta que se hace es: ¿Por qué las herramientas de análisis de código estático señalan los usos de System.out.println?

La razón es que enviar mensajes a stdout suele ser inapropiado en un entorno de producción. Si está codificando una biblioteca, la biblioteca debe devolver información a la persona que llama, no imprimirla en stdout. Si está codificando una aplicación GUI, la información debe presentarse al usuario, no a dónde está apuntando stdout (que podría no estar en ninguna parte). Si está codificando un servidor (o algo que se ejecuta en un contenedor del lado del servidor), debe usar cualquier recurso de registro que haya proporcionado el marco. Etcétera.

Pero si está utilizando println para depuración o desarrollo, o está escribiendo un programa y lee stdin y escribe en stdout, println está perfectamente bien. No hay nada de malo en ese tipo de casos.

Stuart Marks
fuente
3
Buena respuesta. Gracias .. +1 por "Si está codificando una aplicación GUI, la información debe presentarse al usuario, no a dónde está apuntando stdout (que podría no estar en ninguna parte)"
Kayser
10

Todo stdoutestá almacenado y, por lo tanto, es posible que su programa se bloquee después de que haya llamado println(), pero antes de que llegue a la pantalla.

Dicho esto, este escenario es realmente poco probable. Siga adelante y úselo, pero solo mantenga esa pequeña limitación en el fondo de su mente.

Riwalk
fuente
Al menos dos de los principales intérpretes de Python intentan vaciar todos los archivos abiertos antes de salir, incluso si la salida se debe a una excepción no resuelta. ¿Las JVM no hacen algo similar?
1
@delnan, posiblemente, pero puede pasar cualquier cosa. (El código que elimina stdout podría estar donde surge el problema. El hilo en el que se está ejecutando podría cerrarse a la fuerza. El sistema operativo podría arrojar el proceso actual de la memoria a la fuerza.) No viva su vida en torno a mi declaración, pero Sólo sé consciente de ello.
Riwalk
1
El código que elimina stdout está en la VM y, por lo tanto, no se ve afectado por errores en el lenguaje que implementa la VM. Buen punto sobre el final del proceso forzado. Pero tenga en cuenta que, por ejemplo, SIGTERM de Unix y la mayoría de las otras señales se pueden detectar para hacer una limpieza como esta, aunque no funciona con el SIGKILL más extremo.
2
No creo haber visto esto o haber escuchado que suceda, aunque he visto otros problemas. Tampoco es probable que este problema mejore con herramientas como los registradores, ya que es probable que utilicen System.out como herramienta subyacente.
Bill K
@delnan Nunca asuma que su código de limpieza está garantizado para ejecutarse ... y nunca ponga código de transacción comercial crítico en bloques finalmente;) System.out está bien para la depuración, pero tenga en cuenta el almacenamiento en búfer.
Steven
8

System.outes solo un envuelto BufferedOutputStream. Es probable que sea similar a cualquier marco de registro que usará, los marcos solo proporcionan más funcionalidad en forma de configuración y destino de su salida de registro

plato giratorio
fuente
44
Esto realmente no responde la pregunta. "¿Es mala?"
sergserg
@Berg: porque esa parte de la pregunta depende completamente del contexto. (o simplemente, no, no está mal)
spinning_plate
7

Es malo si está trabajando en un programa no trivial y usted

  • Están utilizando System.out como una muleta en lugar de pruebas unitarias automatizadas (JUnit)
  • Pase mucho tiempo creando y eliminando o comentando / descomentando declaraciones de System.out
Aaron Kurtzhals
fuente
1
La mayoría de los IDE deben tener teclas de acceso rápido para autocompletar System.out.println's, comentar / descomentar una línea y eliminar una línea. En principio, tiene razón al tratar de evitar el uso excesivo, pero al menos puede ahorrar tiempo de esta manera.
Steven
7

Hay algunas advertencias sobre el uso System.out, incluso en el código desechable.

Un problema importante es que generalmente es lento . Por ejemplo, si está tratando de tener una idea aproximada sobre la velocidad de algún código (tenga en cuenta que los microbenchmarks son difíciles ), agregar uno solo en System.out.println()cualquier lugar realmente puede arruinar su tiempo (porque se sincroniza y a menudo espera la salida real para ser visible para el usuario antes de regresar).

Aparte de eso, no me preocuparía demasiado en código desechable. Si tiene la intención de confirmarlo (ya sea como código de producción o como código de prueba), debe deshacerse de él y reemplazarlo con una llamada de registro adecuada (sí, incluso en el código de prueba).

Joachim Sauer
fuente
El rendimiento es un buen argumento ..
Kayser
4

Como suele ser el caso, la respuesta es "depende". Si su aplicación ya tiene un marco de registro, entonces también puede usarlo. No puede ser menos capaz que println(), y puede beneficiarse de otras características que proporciona: seguimientos de pila, contexto adicional, mejor formato, etc. También existe la clara posibilidad de que los marcos de registro ofrezcan una mejor recuperación de errores, asegurando que sus registros se escriban con éxito incluso en caso de una falla catastrófica.

Entonces, la pregunta es cuándo agregar un sistema de registro en primer lugar. Esta es una decisión: no desea agregarla demasiado pronto, solo para descubrir que realmente no la necesita. Tampoco desea agregarlo demasiado tarde, y hacer un trabajo excesivo convirtiendo desde su solución ad-hoc.

Si descubre que está haciendo muchos registros println(), entonces su base de código está tratando de decirle que está experimentando dolores de crecimiento. En ese punto, vale la pena invertir en un registro adecuado.

Jon Purdy
fuente
3

A menudo tengo el problema de que System.out.print utiliza la página de códigos "predeterminada del sistema", que a menudo es UTF-8 en Linux, pero algunas cosas de MS en Windows.

Esto puede conducir a caracteres Unicode que se imprimen o no correctamente en la pantalla, dependiendo de dónde se ejecute el programa.

Por lo tanto, prefiero un PrintWriter personalizado sobre System.out

Ingo
fuente
Por basura MS cosas. ¿Te refieres a CP1352 o UTF16?
Cole Johnson
@ColeJohnson: Desafortunadamente, la ventana de la consola de Windows todavía está atascada en una era anterior a UTF16. Sin embargo, el uso de un IDE sano con la consola integrada puede reducir ese problema.
Joachim Sauer
@Cole Johnson: podría vivir con CP 65001 (es decir, utf8), pero parece que no hay forma de obtener esto como una página de códigos "predeterminada del sistema", cuando, por ejemplo, tienes un teclado alemán, obtienes CP 850 o algo así.
Ingo
1

No está nada mal. La noción puede derivarse del hecho de que es muy simple y no tan sofisticado como el uso de un marco de registro dedicado en su aplicación.

Sin embargo, esto no quiere decir que sea un enfoque no válido. Lo he usado muchas veces para verificar el flujo de la aplicación después de algunos trucos de programación de vudú de magia negra .

sergserg
fuente
0

No hay nada de malo en usarlo, te ayuda a descubrir "qué demonios está pasando".

Pero si sus compañeros / otros desarrolladores / herramientas lo ridiculizan, ¡siempre puede usar Logger o comenzar las pruebas de Junit !

lwm
fuente
0

El mayor problema con el System.out.println ocupacional, según lo veo, es que es un "mal olor de hábito (tm)". Si te encuentras haciendo esto, entonces probablemente puedas mejorar tu efectividad al sentirte más cómodo usando tu depurador favorito.

También con un depurador, sabe con certeza que un punto de interrupción no se deslizará en su código de producción, mientras que un System.out.println sí.

En una nota al margen, si en realidad solo está haciendo una prueba rápida y persiste en no usar un depurador, creo que System.out.println es mejor que usar un marco de registro, ya que si accidentalmente deja una declaración log.debug cuando hecho, es más difícil de erradicar.

Buhb
fuente
0

Construir una estrategia de prueba completa en torno a la repetición del contenido del estado interno no es el movimiento más inteligente, pero para pruebas rápidas y sucias de código en desarrollo, la impresión extraña aquí y allá no dolerá mientras recuerde eliminarlas.

El peligro de olvidar eliminarlos es probablemente la razón por la que se desaconseja.

GordonM
fuente
¿Cuál es el problema de olvidar eliminarlos en tu opinión? Seguro que habrá algunos mensajes más en la consola. ¿Ves algún otro problema?
Kayser