online one ideone dgb debugger debug compiler java debugging compiler-construction

ideone - Cómo eliminar declaraciones de depuración del código de producción en Java



java ide one (8)

¿Es posible que el compilador elimine los enunciados utilizados para la depuración (como el registro) del código de producción? Las declaraciones de depuración deberían marcarse de alguna manera, tal vez utilizando anotaciones.

Es fácil establecer una propiedad (debug = true) y verificarla en cada instrucción de depuración, pero esto puede reducir el rendimiento. Sería bueno si el compilador simplemente hiciera desaparecer las declaraciones de depuración.


Dos recomendaciones

Primero: para el registro real, use un paquete de registro moderno como log4j o el propio registro integrado de java. No se preocupe tanto por el rendimiento, la verificación del nivel de registro es del orden de nanosegundos. (es una comparación entera).

Y si tiene más de una declaración de registro, guarde todo el bloque:

(log4j, por ejemplo :)

if (logger.isDebugEnabled()) { // perform expensive operations // build string to log logger.debug("...."); }

Esto le da el control de capacidad adicional de inicio de sesión en tiempo de ejecución. Tener que reiniciar y ejecutar una compilación de depuración puede ser muy inconveniente.

Segundo:

Puede encontrar afirmaciones que son más de lo que necesita. Una aserción es una declaración que evalúa a un resultado booleano, con un mensaje opcional:

assert (sky.state != FALLING) : "The sky is falling!";

Cada vez que la aserción da como resultado un falso, la aserción falla y se lanza un AssertionError que contiene su mensaje (esta es una excepción no verificada, con la intención de salir de la aplicación).

Lo bueno es que la JVM los trata de manera especial y puede alternarlos en el tiempo de ejecución hasta el nivel de clase, utilizando un parámetro VM (no es necesario volver a compilar). Si no está habilitado, no hay gastos generales.


Java contiene algún tipo de preprocesador propio. Se llama APT . Procesa y genera código. Por el momento no estoy seguro de cómo debería funcionar esto (no lo he probado). Pero parece ser usado para este tipo de cosas.


Otra posibilidad es poner la instrucción if dentro de su función de registro, obtendrá menos código de esta manera, pero a expensas de algunas llamadas a funciones adicionales.

Tampoco soy un gran fanático de eliminar por completo el código de depuración. Una vez que esté en producción, probablemente necesite acceder a los mensajes de depuración si algo sale mal. Si elimina toda la depuración del nivel de código, entonces esto no es una posibilidad.


Para responder directamente a su pregunta: No lo sé.

Pero aquí hay otra solución a su problema: en mi opinión, hay dos afirmaciones que colisionan entre sí aquí: "declaraciones de depuración" y "código de producción".

¿Cuál es el propósito de las declaraciones de depuración? Ayuda para deshacerse de errores mientras se realizan las pruebas (de la unidad). Si una pieza de software se prueba adecuadamente y funciona de acuerdo con los requisitos, las instrucciones de depuración no son otra cosa que OBSOLETO.

Estoy totalmente en desacuerdo con dejar cualquier declaración de depuración en el código de producción. Apuesto a que nadie se molesta en probar los efectos secundarios del código de depuración en el código de producción. El código probablemente hace lo que se supone que debe hacer, pero ¿hace más que eso? ¿Funcionan correctamente todas sus #defines y realmente eliminan TODO el código de depuración? ¿Quién analiza 100000 líneas de código preprocesado para ver si todas las cosas de depuración han desaparecido?

A menos que tengamos una definición diferente de código de producción, debería considerar extraer las instrucciones de depuración después de que el código haya sido probado y listo.


Use el preprocesador de Java ? (google foo low pero este es un enlace a los viejos foros de Joel discutiéndolo)


public abstract class Config { public static final boolean ENABLELOGGING = true; }

import static Config.*; public class MyClass { public myMethod() { System.out.println("Hello, non-logging world"); if (ENABLELOGGING) { log("Hello, logging world."); } } }

El compilador eliminará el bloque de código con "Hello, logging world". en él si ENABLE_LOGGING se establece en verdadero porque es un valor final estático. Si usas un ofuscador como proguard, la clase Config también desaparecerá.

Un ofuscador también permitiría cosas como esta en su lugar:

public class MyClass { public myMethod() { System.out.println("Hello, non-logging world"); Log.log("Hello, logging world."); } }

import static Config.*; public abstract class Log { public static void log(String s) { if (ENABLELOGGING) { log(s); } } }

El método Log #log se reduciría a nada en el compilador, y el ofuscador lo eliminaría, junto con cualquier llamada a ese método y eventualmente incluso la clase Log se eliminaría.


También recomendaría altamente usar un marco de registro.

El logger.IsDebugEnabled() no es obligatorio, es solo que puede ser más rápido verificar si el sistema está en el nivel de depuración antes de iniciar sesión.

El uso de una estructura de registro significa que puede configurar los niveles de registro sobre la marcha sin reiniciar la aplicación.

Podría tener logging como:

logger.error("Something bad happened") logger.debug("Something bad happend with loads more detail")


Este " truco " parece hacer que sus declaraciones de depuración desaparezcan

public static final boolean DEBUG = false; if (DEBUG) { //disapeared on compilation }

La publicación decía que javac es lo suficientemente inteligente como para verificar el static final boolean y excluir las declaraciones de depuración. (No lo probé personalmente)

Para el registro, personalmente no me gusta ver código como:

if (logger.isDebugEnabled()) { logger.debug("...."); } realImportantWork();

Las cosas de registro me distraen del realImportantWork() . La forma correcta para mí es:

logger.debug("...."); realImportantWork()

más la configuración que excluye todos los mensajes de depuración en Producción.

Quiero decir que el control logger.isDebugEnabled() debería ser el trabajo del marco de trabajo de registro, no de mi trabajo. La mayoría de los conceptos de soporte del marco de registro como "registrador", "LogLevel" ... que puede hacer el truco.