compiler construction - Código inalcanzable: ¿error o advertencia?
compiler-construction language-agnostic (12)
Creo que debería ser una advertencia por la misma razón que dijo Roalt. Un buen compilador también debería excluir este código de la compilación.
Esta es una pregunta de diseño de lenguaje:
¿Cree que el código inalcanzable (en los lenguajes de programación en general) debería generar una advertencia (es decir, "reportar un problema y compilar de todos modos") o un error ("rechazar compilar")?
Personalmente, creo que debería ser un error: si el programador escribe un fragmento de código, siempre debe hacerlo con la intención de ejecutarlo en algún escenario. Pero el compilador de C #, por ejemplo, parece estar en desacuerdo con esto y simplemente informa una advertencia.
Nota: Me doy cuenta de que una buena detección de código muerto es un problema muy difícil, pero ese no es el tema central de esta pregunta.
Aquí hay algunos ejemplos de piezas de código donde algunas declaraciones son claramente inalcanzables:
return;
foo();
-
throw new Exception();
foo();
-
if (...) {
return;
} else {
throw new Exception();
}
foo();
Creo que debería ser una advertencia.
En términos generales, la regla común es que "debe tratar las advertencias como errores" . Si accidentalmente escribo un código inalcanzable, lo veré en las advertencias y lo arreglaré de todos modos.
Sin embargo, a veces, como dice Neil, intencionalmente creas código muerto, para propósitos de depuración o por cualquier motivo. Realmente, realmente odiaría si el compilador no me dejara hacer eso.
Creo que una advertencia es apropiada. Luego, el usuario puede optar por usar el interruptor OTHER que dice "tratar todas las advertencias como errores" para cuando realice una versión de lanzamiento. Darle poder al desarrollador siempre es mejor que imponerle elecciones esencialmente aleatorias.
Debería ser una advertencia por defecto con un indicador de compilador que permita que se trate como un error. Requerir que sea indiscutiblemente uno u otro es desconsiderado.
En general debería ser un error.
Una excepción viene a mi mente sin embargo:
if (false) {
doStuffThatITemporarilyDisabled();
}
Algunos desarrolladores pueden quejarse si su compilador niega la compilación de un código como ese.
Es muy común crear código muerto intencionalmente al depurar, es improbable que un compilador que lo evita sea popular entre sus usuarios.
La respuesta es que la decisión final sobre si el código inalcanzable genera un error o una advertencia debe dejarse en manos del desarrollador. El compilador debería permitir cualquiera.
En el caso del código de liberación de producción, la balanza favorece que se trate de un error. Ningún programa de producción debe contener código inalcanzable.
En el caso de un código de depuración / prueba, el saldo favorece que sea una advertencia. Es extremadamente conveniente poder deshabilitar partes del código para depurar o probar.
Lo anterior se refiere solo al código escrito a mano. En el caso de código generado por una herramienta automatizada, la balanza favorece que se trate de una advertencia o se ignore. La generación de código que incluye partes inalcanzables no tiene consecuencias adversas particulares y puede ser extremadamente difícil de evitar.
Preferiría mucho (probablemente) el código inalcanzable para producir una advertencia o una notificación (como una advertencia, solo sin connotaciones negativas). Principalmente porque esto hace que la generación automática de código sea un poco más fácil.
Si especifico su idioma:
- Considera que el código muerto es un error
- No admite el preprocesamiento de "nivel de texto" de estilo C
- Carece de comentarios de estilo de bloque que pueden anidar con comentarios de estilo de línea
... entonces realmente apestará. Es imperativo poder deshabilitar grandes bloques de código sin tener que cortarlos físicamente del archivo.
Todavía no estoy claro por qué Java está implementando el código muerto como un error. Uso C y Objective-C, que tienen preprocesadores, por lo que puedo usar fácilmente las directivas de preprocesador para habilitar (o enmascarar) una función / método, como:
// C code
#define ENABLE_FOO //Comment off this to turn off foo(void);
int foo(void)
{
#ifdef ENABLE_FOO
// Do actual stuff.
int returnVaue = 2;
// ...
return returnValue;
#else
return 0; // Turned off
#endif
}
// Compiling using clang, enforcing dead code detection:
// clang main.c -Wall -Werror
O, como en Objective-C, con reflexión disponible:
// Class
#define MYCLASS_ENABLE_FOO // Comment off to enable -[MyClass foo]
@interface MyClass : NSObject
#ifdef MYCLASS_ENABLE_FOO
- (int)foo;
#endif
@end
// The like is done in implementation.
// Invoking:
int main(int argc, char **argv)
{
MyClass *object = [[MyClass alloc] init];
int value = ([object respondsToSelector:@selector(foo)]) ? // Introspection.
[object foo] : 0;
printf("Value: %d", value);
return 0;
}
Una buena razón para tener ese código es durante la fase de desarrollo: desea deshabilitar temporalmente cierto código, pero aún desea que este código se verifique en la sintaxis.
por ejemplo:
int i = 2, j = 3;
int result = 0;
// FIXME: Commented out for now because I have to recheck calculation
if (false) {
result = i*2+j+3+i*j;
}
System.out.println("Result of difficult calculation = "+result);
Si coloca la lista "resultado = i * 2 + j + 3 + i j;" solo en / comments * /, está bastante seguro de que cuando elimina o cambia el nombre de ciertas variables (por ejemplo, i), no recibe un error.
Un error significa que el compilador no puede lidiar físicamente con su código.
Una advertencia significa que el compilador es capaz de manejar su código, pero cree que lo que ha escrito está mal de alguna manera.
Me parece bastante claro, debería ser una advertencia.
Además, ¿qué pasa con el caso en el que he decidido acortar un método para fines de depuración:
public bool ShowMenu()
{
return true;
/* The standard implementation goes here */
}
Sé que está mal, pero que el compilador me pida que también comente que el código sería un dolor.