La cobertura del código destaca los métodos no utilizados: ¿qué debo hacer?

59

Se me ha encomendado la tarea de aumentar la cobertura del código de un proyecto Java existente.

Noté que la herramienta de cobertura de código ( EclEmma ) ha resaltado algunos métodos que nunca se llaman desde ningún lugar.

Mi reacción inicial no es escribir pruebas unitarias para estos métodos, sino resaltarlas ante mi gerente / equipo de línea y preguntar por qué estas funciones están ahí para empezar.

¿Cuál sería el mejor enfoque? Escriba pruebas unitarias para ellos o pregunte por qué están allí.

Lucas T
fuente
1
Los comentarios no son para discusión extendida; Esta conversación se ha movido al chat .
maple_shaft

Respuestas:

118
  1. Eliminar.
  2. Cometer.
  3. Olvidar.

Razón fundamental o base lógica:

  1. El código muerto está muerto. Por su propia descripción no tiene ningún propósito. Puede que haya tenido un propósito en un momento, pero eso ya no existe, por lo que el código debería desaparecer.
  2. El control de versiones asegura que, en mi experiencia, un evento único y raro en el que alguien venga más tarde en busca de ese código, se pueda recuperar.
  3. Como efecto secundario, mejora instantáneamente la cobertura del código sin hacer nada (a menos que se pruebe el código muerto, lo que rara vez es el caso).

Advertencia de los comentarios: la respuesta original suponía que había verificado a fondo que el código está, sin duda, muerto. Los IDE son falibles, y hay varias formas en que el código que parece muerto podría llamarse de hecho. Traiga un experto a menos que esté absolutamente seguro.

l0b0
fuente
118
En general, estaría de acuerdo con este enfoque, pero si eres nuevo en un proyecto y / o un desarrollador junior, mejor pregúntale a tu mentor / superior antes de eliminarlo. Dependiendo del proyecto, algunos métodos pueden no parecer usados, pero pueden ser llamados / utilizados por un código externo que no está en el código del proyecto al que tiene acceso. Puede ser un código autogenerado, por lo que su eliminación no logrará más que ruido de historial de registro. Es posible que su IDE no pueda encontrar el acceso basado en la reflexión desde el proyecto. Etc. pp. Si no está seguro acerca de estos casos de esquina, al menos pregunte una vez.
Frank Hopkins
11
Aunque estoy de acuerdo con el núcleo de esta respuesta, la pregunta literal era "¿debería preguntar por qué están allí?" . Esta respuesta podría dar la impresión de que el OP no debería preguntar a su equipo antes de eliminar.
Doc Brown
58
Sin embargo, primero agregaría un paso: verifique el registro de culpa de git para ver las líneas de código no utilizadas. Si puede encontrar a la persona que los escribió, puede preguntar para qué son. Si las líneas son nuevas, entonces hay una buena posibilidad de que alguien planee usarlas pronto (en cuyo caso, probablemente deberían probarse ahora).
bdsl
10
Hay tantas cosas mal con esta respuesta, como se expresa en los comentarios u otras respuestas, que no puedo creer que esta sea la respuesta más votada y aceptada.
user949300
11
@Emory La mejor manera de comenzar en un nuevo equipo es romper la construcción eliminando cosas sin cuidado porque creía que nadie las necesitaba. Garantiza que eres popular desde el primer día. Seguro que puede que no sea necesario (porque cada aplicación grande y antigua siempre tiene una tos de cobertura de código del 100% ), pero es un ROI muy malo.
Voo
55

Todas las demás respuestas se basan en el supuesto de que los métodos en cuestión no se utilizan realmente. Sin embargo, la pregunta no especificó si este proyecto es autónomo o una biblioteca de algún tipo.

Si el proyecto en cuestión es una biblioteca, los métodos aparentemente no utilizados pueden usarse fuera del proyecto y eliminarlos rompería esos otros proyectos. Si la biblioteca en sí se vende a los clientes o se pone a disposición del público, puede ser incluso imposible rastrear el uso de estos métodos.

En este caso, hay cuatro posibilidades:

  • Si los métodos son privados o privados del paquete, se pueden eliminar de forma segura.
  • Si los métodos son públicos, su presencia puede estar justificada incluso sin un uso real, para completar las características. Sin embargo, deberían ser probados.
  • Si los métodos son públicos e innecesarios, eliminarlos será un cambio radical y si la biblioteca sigue las versiones semánticas , esto solo se permite en una nueva versión principal.
  • Alternativamente, los métodos públicos también pueden ser desaprobados y eliminados más tarde. Esto les da algo de tiempo a los consumidores de API para pasar de las funciones obsoletas antes de que se eliminen en la próxima versión principal.
Zoltan
fuente
99
Además, si se trata de una biblioteca, las funciones están ahí por razones de
integridad
¿Puedes explicar cómo deberían ser probados? Si no sabe por qué existe el método, probablemente no sepa qué se supone que debe hacer.
No U
Los nombres de métodos como filter_name_exists, ReloadSettingso addToSchema(seleccionados al azar de 3 proyectos arbitrarios de código abierto) deberían proporcionar algunas pistas sobre lo que se supone que debe hacer el método. Un comentario de javadoc puede ser aún más útil. No es una especificación adecuada, lo sé, pero podría ser suficiente para crear algunas pruebas que al menos puedan evitar regresiones.
Zoltan
1
Los métodos públicos en una clase o interfaz privada no deben considerarse públicos para este propósito. de manera similar, si una clase pública está anidada dentro de una clase privada, no es realmente pública.
emory
30

Primero verifique que su herramienta de cobertura de código sea correcta.

He tenido situaciones en las que no han captado los métodos que se llaman a través de referencias a la interfaz, o si la clase se carga dinámicamente en algún lugar.

Ewan
fuente
Gracias, lo hare. En Eclipse, hago una búsqueda en la base de código para la función, y no aparece nada. Si tiene alguna otra sugerencia sobre cómo hacer una búsqueda más completa, le agradecería mucho.
Lucas T
3
sí, debe verificar otros proyectos que podrían importar la clase como un archivo DLL
Ewan
77
Esta respuesta se siente incompleta. "Primero verifique que su herramienta de cobertura de código sea correcta. Si es así, entonces ... [inserte el resto de la respuesta] ". Específicamente, el OP quiere saber qué hacer si la herramienta de cobertura de código es correcta.
Jon Bentley
1
@jonbentley El OP está pidiendo el mejor enfoque para el informe de herramientas. "Verifíquelo manualmente" porque es bastante obvio por el contexto que es incorrecto
Ewan
15

Como Java está compilado estáticamente, debería ser bastante seguro eliminar los métodos. Eliminar el código muerto siempre es bueno. Existe cierta probabilidad de que haya algún sistema de reflexión loco que los ejecute en tiempo de ejecución, así que verifique primero con otros desarrolladores, pero de lo contrario elimínelos.

max630
fuente
99
+1 para consultar con la gente, es como seguir el principio de la menor sorpresa. No desea que alguien pase demasiado tiempo buscando el método que acaba de dejar allí algunas confirmaciones antes. Además, en algunos casos extremos, el código muerto puede ser lo nuevo que ya se ha registrado pero que aún no está conectado (aunque en este caso debe documentarse bien con comentarios y probarse).
Frax
44
Bueno, a menos que el código utilice la reflexión para llamar a los métodos "no utilizados", pero en ese caso tiene problemas mucho mayores, y esperamos ver el código en thefailywft.com (haga una prueba rápida para ver si algún código hace un ClassName. clase).
MTilsted
2
Está compilado estáticamente, pero también hay invokedynamicinstrucciones, así que, ya sabes ...
corsiKa
@MTilsted: Hay muchos marcos que llamarán al código usando cadenas; puedo pensar en al menos Spring e Hibernate fuera de mi cabeza.
jhominal
9

¿Cuál sería el mejor enfoque? Escriba pruebas unitarias para ellos o pregunte por qué están allí.

Eliminar código es algo bueno.

Cuando no puede eliminar el código, ciertamente puede marcarlo como @Deprecated , documentando a qué versión principal está apuntando para eliminar el método. Luego puede eliminarlo "más tarde". Mientras tanto, estará claro que no se debe agregar ningún código nuevo que dependa de él.

No recomendaría invertir en métodos obsoletos, por lo que no hay nuevas pruebas unitarias solo para alcanzar los objetivos de cobertura.

La diferencia entre los dos es principalmente si los métodos son o no parte de la interfaz publicada . Eliminar arbitrariamente partes de la interfaz publicada puede ser una sorpresa desagradable para los consumidores que dependían de la interfaz.

No puedo hablar con EclEmma, ​​pero según mi experiencia, una de las cosas de las que debes tener cuidado es la reflexión. Si, por ejemplo, usa archivos de configuración de texto para elegir a qué clases / métodos acceder, la distinción utilizada / no utilizada puede no ser obvia (eso me ha quemado un par de veces).

Si su proyecto es una hoja en el gráfico de dependencia, entonces el caso de desaprobación se debilita. Si su proyecto es una biblioteca, entonces el caso de desaprobación es más fuerte.

Si su empresa utiliza un mono-repos , entonces eliminar es un riesgo menor que en el caso de múltiples repos.

Como se señala en 10b0 , si los métodos ya están disponibles en el control de origen, recuperarlos después de la eliminación es un ejercicio sencillo. Si estaba realmente preocupado por la necesidad de hacer eso, piense cómo organizar sus confirmaciones para que pueda recuperar los cambios eliminados si los necesita.

Si la incertidumbre es lo suficientemente alta, podría considerar comentar el código , en lugar de eliminarlo. Es un trabajo extra en el camino feliz (donde el código eliminado nunca se restaura), pero hace que sea más fácil de restaurar. Supongo que debería preferir una eliminación directa hasta que se haya quemado un par de veces, lo que le dará algunas ideas sobre cómo evaluar la "incertidumbre" en este contexto.

pregunta por qué están allí?

El tiempo invertido en capturar la tradición no se desperdicia necesariamente. Se sabe que realizo una eliminación en dos pasos: primero, agregando y confirmando un comentario que explica lo que hemos aprendido sobre el código, y luego eliminando el código (y el comentario).

También podría usar algo análogo a los registros de decisiones arquitectónicas como una forma de capturar la historia con el código fuente.

VoiceOfUnreason
fuente
9

Una herramienta de cobertura de código no lo sabe todo, todo lo ve. El hecho de que su herramienta afirme que el método no se llama, eso no significa que no se llame. Hay reflexión, y dependiendo del idioma puede haber otras formas de llamar al método. En C o C ++ puede haber macros que construyen nombres de funciones o métodos, y es posible que la herramienta no vea la llamada. Entonces, el primer paso sería: hacer una búsqueda textual del nombre del método y de los nombres relacionados. Pregunta a colegas con experiencia. Puede encontrar que realmente se usa.

Si no está seguro, coloque una afirmación () al comienzo de cada método "no utilizado". Tal vez se llama. O una declaración de registro.

Quizás el código sea realmente valioso. Puede ser un nuevo código en el que un colega ha estado trabajando durante dos semanas, y que él o ella iba a activar mañana. No se llama hoy porque la llamada se agregará mañana.

Tal vez el código sea realmente valioso parte 2: el código puede estar realizando algunas pruebas de tiempo de ejecución muy costosas que podrían encontrar que las cosas van mal El código solo se activa si las cosas realmente salen mal. Puede estar eliminando una valiosa herramienta de depuración.

Curiosamente, el peor consejo posible "Eliminar. Comprometerse. Olvidar". es el mejor valorado (¿Revisiones de código? ¿No haces revisiones de código? ¿Qué demonios estás programando si no haces revisiones de código?)

gnasher729
fuente
Respetuosamente estoy en desacuerdo acerca de "ELIMINAR. COMPROMETERSE. OLVIDAR" es el peor consejo. (Creo que es lo mejor). Tu enfoque también está bien. Creo que el peor consejo posible sería escribir pruebas unitarias que ejerzan el "código muerto" pero no hagan afirmaciones. La herramienta de cobertura de código se dejará engañar pensando que se usan.
emory
3
Nada en la respuesta "Eliminar. Confirmar. Olvidar" dice que no se debe revisar el código. Es perfectamente posible (y recomendable, en mi humilde opinión) revisar el código después de que se haya confirmado (pero antes de la implementación :-)).
sleske
@sleske ¿Cómo revisas el código que ya no existe? Tampoco esa respuesta menciona "revisión".
user949300
@ user949300: Si un cambio de código necesita revisión o no, es una pregunta separada e independiente de si el código se agrega, cambia o elimina (agregar código puede ser aún más desastroso que eliminarlo, ver, por ejemplo, la vulnerabilidad Heartbleed). Además, la respuesta (ahora) dice "traer un experto", lo que suena bastante parecido a una revisión de código.
sleske
1
@ user949300: En cuanto a "¿Cómo se revisa el código que ya no existe?", espero que sea obvio: al observar el cambio en la herramienta de control de versiones de su elección. ¿De qué otra manera revisaría los cambios (cualquier cambio)?
sleske
6

Dependiendo del entorno en el que se ejecute el software, puede iniciar sesión si alguna vez se llama al método. Si no se llama dentro de un período de tiempo adecuado, entonces el método se puede eliminar de forma segura.

Este es un enfoque más cauteloso que simplemente eliminar el método, y puede ser útil si está ejecutando en un entorno altamente sensible a fallas.

Iniciamos sesión en un #unreachable-codecanal dedicado dedicado con un identificador único para cada candidato para la eliminación, y se demostró que es bastante efectivo.

Jamie Bull
fuente
Pero, ¿qué pasa si rara vez se llama (como 1 en 1440 en promedio) ?
Peter Mortensen
entonces "un período de tiempo adecuado" es más largo (aunque me gusta un "hombre después de la medianoche")
Jamie Bull